mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 00:39:50 +03:00
feat: add Modbus support
This commit is contained in:
119
lib/eModbus/src/ModbusClient.h
Normal file
119
lib/eModbus/src/ModbusClient.h
Normal file
@@ -0,0 +1,119 @@
|
||||
// =================================================================================================
|
||||
// eModbus: Copyright 2020 by Michael Harwerth, Bert Melis and the contributors to eModbus
|
||||
// MIT license - see license.md for details
|
||||
// =================================================================================================
|
||||
#ifndef _MODBUS_CLIENT_H
|
||||
#define _MODBUS_CLIENT_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "options.h"
|
||||
#include "ModbusMessage.h"
|
||||
|
||||
#if HAS_FREERTOS
|
||||
extern "C" {
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
}
|
||||
#elif IS_LINUX
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if USE_MUTEX
|
||||
#include <mutex> // NOLINT
|
||||
using std::mutex;
|
||||
using std::lock_guard;
|
||||
#endif
|
||||
|
||||
typedef std::function<void(ModbusMessage msg, uint32_t token)> MBOnData;
|
||||
typedef std::function<void(Modbus::Error errorCode, uint32_t token)> MBOnError;
|
||||
typedef std::function<void(ModbusMessage msg, uint32_t token)> MBOnResponse;
|
||||
|
||||
class ModbusClient {
|
||||
public:
|
||||
bool onDataHandler(MBOnData handler); // Accept onData handler
|
||||
bool onErrorHandler(MBOnError handler); // Accept onError handler
|
||||
bool onResponseHandler(MBOnResponse handler); // Accept onResponse handler
|
||||
uint32_t getMessageCount(); // Informative: return number of messages created
|
||||
uint32_t getErrorCount(); // Informative: return number of errors received
|
||||
void resetCounts(); // Set both message and error counts to zero
|
||||
inline Error addRequest(ModbusMessage m, uint32_t token) { return addRequestM(m, token); }
|
||||
inline ModbusMessage syncRequest(ModbusMessage m, uint32_t token) { return syncRequestM(m, token); }
|
||||
|
||||
// Template function to generate syncRequest functions as long as there is a
|
||||
// matching ModbusMessage::setMessage() call
|
||||
template <typename... Args>
|
||||
ModbusMessage syncRequest(uint32_t token, Args&&... args) {
|
||||
Error rc = SUCCESS;
|
||||
// Create request, if valid
|
||||
ModbusMessage m;
|
||||
rc = m.setMessage(std::forward<Args>(args) ...);
|
||||
|
||||
// Add it to the queue and wait for a response, if valid
|
||||
if (rc == SUCCESS) {
|
||||
return syncRequestM(m, token);
|
||||
}
|
||||
// Else return the error as a message
|
||||
return buildErrorMsg(rc, std::forward<Args>(args) ...);
|
||||
}
|
||||
|
||||
// Template function to create an error response message from a variadic pattern
|
||||
template <typename... Args>
|
||||
ModbusMessage buildErrorMsg(Error e, uint8_t serverID, uint8_t functionCode, Args&&... args) {
|
||||
ModbusMessage m;
|
||||
m.setError(serverID, functionCode, e);
|
||||
return m;
|
||||
}
|
||||
|
||||
// Template function to generate addRequest functions as long as there is a
|
||||
// matching ModbusMessage::setMessage() call
|
||||
template <typename... Args>
|
||||
Error addRequest(uint32_t token, Args&&... args) {
|
||||
Error rc = SUCCESS; // Return value
|
||||
|
||||
// Create request, if valid
|
||||
ModbusMessage m;
|
||||
rc = m.setMessage(std::forward<Args>(args) ...);
|
||||
|
||||
// Add it to the queue, if valid
|
||||
if (rc == SUCCESS) {
|
||||
return addRequestM(m, token);
|
||||
}
|
||||
// Else return the error
|
||||
return rc;
|
||||
}
|
||||
|
||||
protected:
|
||||
ModbusClient(); // Default constructor
|
||||
virtual void isInstance() = 0; // Make class abstract
|
||||
ModbusMessage waitSync(uint8_t serverID, uint8_t functionCode, uint32_t token); // wait for syncRequest response to arrive
|
||||
// Virtual addRequest variant needed internally. All others done by template!
|
||||
virtual Error addRequestM(ModbusMessage msg, uint32_t token) = 0;
|
||||
// Virtual syncRequest variant following the same pattern
|
||||
virtual ModbusMessage syncRequestM(ModbusMessage msg, uint32_t token) = 0;
|
||||
// Prevent copy construction or assignment
|
||||
ModbusClient(ModbusClient& other) = delete;
|
||||
ModbusClient& operator=(ModbusClient& other) = delete;
|
||||
|
||||
uint32_t messageCount; // Number of requests generated. Used for transactionID in TCPhead
|
||||
uint32_t errorCount; // Number of errors received
|
||||
#if HAS_FREERTOS
|
||||
TaskHandle_t worker; // Interface instance worker task
|
||||
#elif IS_LINUX
|
||||
pthread_t worker;
|
||||
#endif
|
||||
MBOnData onData; // Data response handler
|
||||
MBOnError onError; // Error response handler
|
||||
MBOnResponse onResponse; // Uniform response handler
|
||||
static uint16_t instanceCounter; // Number of ModbusClients created
|
||||
std::map<uint32_t, ModbusMessage> syncResponse; // Map to hold response messages on synchronous requests
|
||||
#if USE_MUTEX
|
||||
std::mutex syncRespM; // Mutex protecting syncResponse map against race conditions
|
||||
std::mutex countAccessM; // Mutex protecting access to the message and error counts
|
||||
#endif
|
||||
|
||||
// Let any ModbusBridge class use protected members
|
||||
template<typename SERVERCLASS> friend class ModbusBridge;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user