mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-04 18:29:48 +02:00
Update eModbus to v1.7.1stable
This commit is contained in:
parent
73e01b8a37
commit
ca452d120b
12 changed files with 114 additions and 43 deletions
|
@ -98,7 +98,7 @@ public:
|
||||||
// Return number of coils set to 0 (or OFF)
|
// Return number of coils set to 0 (or OFF)
|
||||||
uint16_t coilsSetOFF() const;
|
uint16_t coilsSetOFF() const;
|
||||||
|
|
||||||
#if !ISLINUX
|
#if !LINUX
|
||||||
// Helper function to dump out coils in logical order
|
// Helper function to dump out coils in logical order
|
||||||
void print(const char *label, Print& s);
|
void print(const char *label, Print& s);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,8 +29,8 @@ public:
|
||||||
ModbusBridge();
|
ModbusBridge();
|
||||||
|
|
||||||
// Constructors for the RTU variant. Parameters as are for ModbusServerRTU
|
// Constructors for the RTU variant. Parameters as are for ModbusServerRTU
|
||||||
ModbusBridge(HardwareSerial& serial, uint32_t timeout, int rtsPin = -1);
|
ModbusBridge(uint32_t timeout, int rtsPin = -1);
|
||||||
ModbusBridge(HardwareSerial& serial, uint32_t timeout, RTScallback rts);
|
ModbusBridge(uint32_t timeout, RTScallback rts);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~ModbusBridge();
|
~ModbusBridge();
|
||||||
|
@ -85,13 +85,13 @@ ModbusBridge<SERVERCLASS>::ModbusBridge() :
|
||||||
|
|
||||||
// Constructors for RTU variant
|
// Constructors for RTU variant
|
||||||
template<typename SERVERCLASS>
|
template<typename SERVERCLASS>
|
||||||
ModbusBridge<SERVERCLASS>::ModbusBridge(HardwareSerial& serial, uint32_t timeout, int rtsPin) :
|
ModbusBridge<SERVERCLASS>::ModbusBridge(uint32_t timeout, int rtsPin) :
|
||||||
SERVERCLASS(serial, timeout, rtsPin) { }
|
SERVERCLASS(timeout, rtsPin) { }
|
||||||
|
|
||||||
// Alternate constructors for RTU variant
|
// Alternate constructors for RTU variant
|
||||||
template<typename SERVERCLASS>
|
template<typename SERVERCLASS>
|
||||||
ModbusBridge<SERVERCLASS>::ModbusBridge(HardwareSerial& serial, uint32_t timeout, RTScallback rts) :
|
ModbusBridge<SERVERCLASS>::ModbusBridge(uint32_t timeout, RTScallback rts) :
|
||||||
SERVERCLASS(serial, timeout, rts) { }
|
SERVERCLASS(timeout, rts) { }
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
template<typename SERVERCLASS>
|
template<typename SERVERCLASS>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
|
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
// Constructor takes Serial reference and optional DE/RE pin
|
// Constructor takes an optional DE/RE pin and queue size
|
||||||
ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
|
ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
|
||||||
ModbusClient(),
|
ModbusClient(),
|
||||||
MR_serial(nullptr),
|
MR_serial(nullptr),
|
||||||
|
@ -32,7 +32,7 @@ ModbusClientRTU::ModbusClientRTU(int8_t rtsPin, uint16_t queueLimit) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternative constructor takes Serial reference and RTS callback function
|
// Alternative constructor takes an RTS callback function
|
||||||
ModbusClientRTU::ModbusClientRTU(RTScallback rts, uint16_t queueLimit) :
|
ModbusClientRTU::ModbusClientRTU(RTScallback rts, uint16_t queueLimit) :
|
||||||
ModbusClient(),
|
ModbusClient(),
|
||||||
MR_serial(nullptr),
|
MR_serial(nullptr),
|
||||||
|
@ -54,20 +54,20 @@ ModbusClientRTU::~ModbusClientRTU() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin: start worker task - general version
|
// begin: start worker task - general version
|
||||||
void ModbusClientRTU::begin(Stream& serial, uint32_t baudRate, int coreID) {
|
void ModbusClientRTU::begin(Stream& serial, uint32_t baudRate, int coreID, uint32_t userInterval) {
|
||||||
MR_serial = &serial;
|
MR_serial = &serial;
|
||||||
doBegin(baudRate, coreID);
|
doBegin(baudRate, coreID, userInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// begin: start worker task - HardwareSerial version
|
// begin: start worker task - HardwareSerial version
|
||||||
void ModbusClientRTU::begin(HardwareSerial& serial, int coreID) {
|
void ModbusClientRTU::begin(HardwareSerial& serial, int coreID, uint32_t userInterval) {
|
||||||
MR_serial = &serial;
|
MR_serial = &serial;
|
||||||
uint32_t baudRate = serial.baudRate();
|
uint32_t baudRate = serial.baudRate();
|
||||||
serial.setRxFIFOFull(1);
|
serial.setRxFIFOFull(1);
|
||||||
doBegin(baudRate, coreID);
|
doBegin(baudRate, coreID, userInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID) {
|
void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID, uint32_t userInterval) {
|
||||||
// Task already running? End it in case
|
// Task already running? End it in case
|
||||||
end();
|
end();
|
||||||
|
|
||||||
|
@ -77,11 +77,16 @@ void ModbusClientRTU::doBegin(uint32_t baudRate, int coreID) {
|
||||||
// Set minimum interval time
|
// Set minimum interval time
|
||||||
MR_interval = RTUutils::calculateInterval(baudRate);
|
MR_interval = RTUutils::calculateInterval(baudRate);
|
||||||
|
|
||||||
|
// If user defined interval is longer, use that
|
||||||
|
if (MR_interval < userInterval) {
|
||||||
|
MR_interval = userInterval;
|
||||||
|
}
|
||||||
|
|
||||||
// Create unique task name
|
// Create unique task name
|
||||||
char taskName[18];
|
char taskName[18];
|
||||||
snprintf(taskName, 18, "Modbus%02XRTU", instanceCounter);
|
snprintf(taskName, 18, "Modbus%02XRTU", instanceCounter);
|
||||||
// Start task to handle the queue
|
// Start task to handle the queue
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, 4096, this, 6, &worker, coreID >= 0 ? coreID : NULL);
|
xTaskCreatePinnedToCore((TaskFunction_t)&handleConnection, taskName, CLIENT_TASK_STACK, this, 6, &worker, coreID >= 0 ? coreID : NULL);
|
||||||
|
|
||||||
LOG_D("Client task %d started. Interval=%d\n", (uint32_t)worker, MR_interval);
|
LOG_D("Client task %d started. Interval=%d\n", (uint32_t)worker, MR_interval);
|
||||||
}
|
}
|
||||||
|
@ -102,6 +107,7 @@ void ModbusClientRTU::end() {
|
||||||
// Kill task
|
// Kill task
|
||||||
vTaskDelete(worker);
|
vTaskDelete(worker);
|
||||||
LOG_D("Client task %d killed.\n", (uint32_t)worker);
|
LOG_D("Client task %d killed.\n", (uint32_t)worker);
|
||||||
|
worker = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +146,14 @@ uint32_t ModbusClientRTU::pendingRequests() {
|
||||||
return requests.size();
|
return requests.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all pending request from queue
|
||||||
|
void ModbusClientRTU::clearQueue()
|
||||||
|
{
|
||||||
|
std::queue<RequestEntry> empty;
|
||||||
|
LOCK_GUARD(lockGuard, qLock);
|
||||||
|
std::swap(requests, empty);
|
||||||
|
}
|
||||||
|
|
||||||
// Base addRequest taking a preformatted data buffer and length as parameters
|
// Base addRequest taking a preformatted data buffer and length as parameters
|
||||||
Error ModbusClientRTU::addRequestM(ModbusMessage msg, uint32_t token) {
|
Error ModbusClientRTU::addRequestM(ModbusMessage msg, uint32_t token) {
|
||||||
Error rc = SUCCESS; // Return value
|
Error rc = SUCCESS; // Return value
|
||||||
|
|
|
@ -21,19 +21,19 @@ using std::queue;
|
||||||
|
|
||||||
class ModbusClientRTU : public ModbusClient {
|
class ModbusClientRTU : public ModbusClient {
|
||||||
public:
|
public:
|
||||||
// Constructor takes Serial reference and optional DE/RE pin and queue limit
|
// Constructor takes an optional DE/RE pin and queue limit
|
||||||
explicit ModbusClientRTU(int8_t rtsPin = -1, uint16_t queueLimit = 100);
|
explicit ModbusClientRTU(int8_t rtsPin = -1, uint16_t queueLimit = 100);
|
||||||
|
|
||||||
// Alternative Constructor takes Serial reference and RTS line toggle callback
|
// Alternative Constructor takes an RTS line toggle callback
|
||||||
explicit ModbusClientRTU(RTScallback rts, uint16_t queueLimit = 100);
|
explicit ModbusClientRTU(RTScallback rts, uint16_t queueLimit = 100);
|
||||||
|
|
||||||
// Destructor: clean up queue, task etc.
|
// Destructor: clean up queue, task etc.
|
||||||
~ModbusClientRTU();
|
~ModbusClientRTU();
|
||||||
|
|
||||||
// begin: start worker task
|
// begin: start worker task
|
||||||
void begin(Stream& serial, uint32_t baudrate, int coreID = -1);
|
void begin(Stream& serial, uint32_t baudrate, int coreID = -1, uint32_t userInterval = 0);
|
||||||
// Special variant for HardwareSerial
|
// Special variant for HardwareSerial
|
||||||
void begin(HardwareSerial& serial, int coreID = -1);
|
void begin(HardwareSerial& serial, int coreID = -1, uint32_t userInterval = 0);
|
||||||
|
|
||||||
// end: stop the worker
|
// end: stop the worker
|
||||||
void end();
|
void end();
|
||||||
|
@ -56,6 +56,9 @@ public:
|
||||||
// Return number of unprocessed requests in queue
|
// Return number of unprocessed requests in queue
|
||||||
uint32_t pendingRequests();
|
uint32_t pendingRequests();
|
||||||
|
|
||||||
|
// Remove all pending request from queue
|
||||||
|
void clearQueue();
|
||||||
|
|
||||||
// addBroadcastMessage: create a fire-and-forget message to all servers on the RTU bus
|
// addBroadcastMessage: create a fire-and-forget message to all servers on the RTU bus
|
||||||
Error addBroadcastMessage(const uint8_t *data, uint8_t len);
|
Error addBroadcastMessage(const uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
@ -84,7 +87,7 @@ protected:
|
||||||
ModbusMessage receive(const ModbusMessage request);
|
ModbusMessage receive(const ModbusMessage request);
|
||||||
|
|
||||||
// start background task
|
// start background task
|
||||||
void doBegin(uint32_t baudRate, int coreID);
|
void doBegin(uint32_t baudRate, int coreID, uint32_t userInterval);
|
||||||
|
|
||||||
void isInstance() { return; } // make class instantiable
|
void isInstance() { return; } // make class instantiable
|
||||||
queue<RequestEntry> requests; // Queue to hold requests to be processed
|
queue<RequestEntry> requests; // Queue to hold requests to be processed
|
||||||
|
|
|
@ -18,30 +18,48 @@ void ModbusServer::registerWorker(uint8_t serverID, uint8_t functionCode, MBSwor
|
||||||
|
|
||||||
// getWorker: if a worker function is registered, return its address, nullptr otherwise
|
// getWorker: if a worker function is registered, return its address, nullptr otherwise
|
||||||
MBSworker ModbusServer::getWorker(uint8_t serverID, uint8_t functionCode) {
|
MBSworker ModbusServer::getWorker(uint8_t serverID, uint8_t functionCode) {
|
||||||
|
bool serverFound = false;
|
||||||
|
LOG_D("Need worker for %02X-%02X : ", serverID, functionCode);
|
||||||
// Search the FC map associated with the serverID
|
// Search the FC map associated with the serverID
|
||||||
auto svmap = workerMap.find(serverID);
|
auto svmap = workerMap.find(serverID);
|
||||||
// Is there one?
|
// Is there one?
|
||||||
if (svmap != workerMap.end()) {
|
if (svmap != workerMap.end()) {
|
||||||
|
serverFound = true;
|
||||||
|
// No explicit serverID entry found, but we may have one for ANY_SERVER
|
||||||
|
} else {
|
||||||
|
svmap = workerMap.find(ANY_SERVER);
|
||||||
|
if (svmap != workerMap.end()) {
|
||||||
|
serverFound = true;
|
||||||
|
serverID = ANY_SERVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Did we find a serverID?
|
||||||
|
if (serverFound) {
|
||||||
// Yes. Now look for the function code in the inner map
|
// Yes. Now look for the function code in the inner map
|
||||||
|
bool functionCodeFound = false;
|
||||||
auto fcmap = svmap->second.find(functionCode);;
|
auto fcmap = svmap->second.find(functionCode);;
|
||||||
// Found it?
|
// Found it?
|
||||||
if (fcmap != svmap->second.end()) {
|
if (fcmap != svmap->second.end()) {
|
||||||
// Yes. Return the function pointer for it.
|
// Yes. Return the function pointer for it.
|
||||||
LOG_D("Worker found for %02X/%02X\n", serverID, functionCode);
|
functionCodeFound = true;
|
||||||
return fcmap->second;
|
|
||||||
// No, no explicit worker found, but may be there is one for ANY_FUNCTION_CODE?
|
// No, no explicit worker found, but may be there is one for ANY_FUNCTION_CODE?
|
||||||
} else {
|
} else {
|
||||||
fcmap = svmap->second.find(ANY_FUNCTION_CODE);;
|
fcmap = svmap->second.find(ANY_FUNCTION_CODE);;
|
||||||
// Found it?
|
// Found it?
|
||||||
if (fcmap != svmap->second.end()) {
|
if (fcmap != svmap->second.end()) {
|
||||||
// Yes. Return the function pointer for it.
|
// Yes. Return the function pointer for it.
|
||||||
LOG_D("Worker found for %02X/ANY\n", serverID);
|
functionCodeFound = true;
|
||||||
return fcmap->second;
|
functionCode = ANY_FUNCTION_CODE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (functionCodeFound) {
|
||||||
|
// Yes. Return the function pointer for it.
|
||||||
|
LOGRAW_D("Worker found for %02X/%02X\n", serverID, functionCode);
|
||||||
|
return fcmap->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// No matching function pointer found
|
// No matching function pointer found
|
||||||
LOG_D("No matching worker found\n");
|
LOGRAW_D("No matching worker found\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,16 +86,29 @@ bool ModbusServer::unregisterWorker(uint8_t serverID, uint8_t functionCode) {
|
||||||
return (numEntries ? true : false);
|
return (numEntries ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// isServerFor: if any worker function is registered for the given serverID, return true
|
// isServerFor: if a worker function is registered for the given serverID, return true
|
||||||
bool ModbusServer::isServerFor(uint8_t serverID) {
|
// functionCode defaults to ANY_FUNCTION_CODE and will yield true for any function code,
|
||||||
// Search the FC map for the serverID
|
// including ANY_FUNCTION_CODE :D
|
||||||
auto svmap = workerMap.find(serverID);
|
bool ModbusServer::isServerFor(uint8_t serverID, uint8_t functionCode) {
|
||||||
// Is it there? Then return true
|
// Check if there is a non-nullptr function for the given combination
|
||||||
if (svmap != workerMap.end()) return true;
|
if (getWorker(serverID, functionCode)) {
|
||||||
// No, serverID was not found. Return false
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isServerFor: short version to look up if the server is known at all
|
||||||
|
bool ModbusServer::isServerFor(uint8_t serverID) {
|
||||||
|
// Check if there is a non-nullptr function for the given combination
|
||||||
|
auto svmap = workerMap.find(serverID);
|
||||||
|
// Is there one?
|
||||||
|
if (svmap != workerMap.end()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// getMessageCount: read number of messages processed
|
// getMessageCount: read number of messages processed
|
||||||
uint32_t ModbusServer::getMessageCount() {
|
uint32_t ModbusServer::getMessageCount() {
|
||||||
return messageCount;
|
return messageCount;
|
||||||
|
@ -104,6 +135,7 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
|
||||||
uint8_t functionCode = msg.getFunctionCode();
|
uint8_t functionCode = msg.getFunctionCode();
|
||||||
LOG_D("Local request for %02X/%02X\n", serverID, functionCode);
|
LOG_D("Local request for %02X/%02X\n", serverID, functionCode);
|
||||||
HEXDUMP_V("Request", msg.data(), msg.size());
|
HEXDUMP_V("Request", msg.data(), msg.size());
|
||||||
|
messageCount++;
|
||||||
// Try to get a worker for the request
|
// Try to get a worker for the request
|
||||||
MBSworker worker = getWorker(serverID, functionCode);
|
MBSworker worker = getWorker(serverID, functionCode);
|
||||||
// Did we get one?
|
// Did we get one?
|
||||||
|
@ -129,6 +161,9 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HEXDUMP_V("Response", m.data(), m.size());
|
HEXDUMP_V("Response", m.data(), m.size());
|
||||||
|
if (m.getError() != SUCCESS) {
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
return m;
|
return m;
|
||||||
} else {
|
} else {
|
||||||
LOG_D("No worker found. Error response.\n");
|
LOG_D("No worker found. Error response.\n");
|
||||||
|
@ -140,11 +175,13 @@ ModbusMessage ModbusServer::localRequest(ModbusMessage msg) {
|
||||||
// No. Respond with "Invalid server ID"
|
// No. Respond with "Invalid server ID"
|
||||||
m.setError(serverID, functionCode, INVALID_SERVER);
|
m.setError(serverID, functionCode, INVALID_SERVER);
|
||||||
}
|
}
|
||||||
|
errorCount++;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
// We should never get here...
|
// We should never get here...
|
||||||
LOG_C("Internal problem: should not get here!\n");
|
LOG_C("Internal problem: should not get here!\n");
|
||||||
m.setError(serverID, functionCode, UNDEFINED_ERROR);
|
m.setError(serverID, functionCode, UNDEFINED_ERROR);
|
||||||
|
errorCount++;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,10 @@ public:
|
||||||
// Returns true if the worker was found and removed
|
// Returns true if the worker was found and removed
|
||||||
bool unregisterWorker(uint8_t serverID, uint8_t functionCode = 0);
|
bool unregisterWorker(uint8_t serverID, uint8_t functionCode = 0);
|
||||||
|
|
||||||
// isServerFor: if any worker function is registered for the given serverID, return true
|
// isServerFor: if a worker function is registered for the given serverID, return true
|
||||||
|
bool isServerFor(uint8_t serverID, uint8_t functionCode);
|
||||||
|
|
||||||
|
// isServerFor: short version to look up if the server is known at all
|
||||||
bool isServerFor(uint8_t serverID);
|
bool isServerFor(uint8_t serverID);
|
||||||
|
|
||||||
// getMessageCount: read number of messages processed
|
// getMessageCount: read number of messages processed
|
||||||
|
|
|
@ -64,32 +64,37 @@ ModbusServerRTU::~ModbusServerRTU() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start: create task with RTU server - general version
|
// start: create task with RTU server - general version
|
||||||
void ModbusServerRTU::begin(Stream& serial, uint32_t baudRate, int coreID) {
|
void ModbusServerRTU::begin(Stream& serial, uint32_t baudRate, int coreID, uint32_t userInterval) {
|
||||||
MSRserial = &serial;
|
MSRserial = &serial;
|
||||||
doBegin(baudRate, coreID);
|
doBegin(baudRate, coreID, userInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// start: create task with RTU server - HardwareSerial versions
|
// start: create task with RTU server - HardwareSerial versions
|
||||||
void ModbusServerRTU::begin(HardwareSerial& serial, int coreID) {
|
void ModbusServerRTU::begin(HardwareSerial& serial, int coreID, uint32_t userInterval) {
|
||||||
MSRserial = &serial;
|
MSRserial = &serial;
|
||||||
uint32_t baudRate = serial.baudRate();
|
uint32_t baudRate = serial.baudRate();
|
||||||
serial.setRxFIFOFull(1);
|
serial.setRxFIFOFull(1);
|
||||||
doBegin(baudRate, coreID);
|
doBegin(baudRate, coreID, userInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModbusServerRTU::doBegin(uint32_t baudRate, int coreID) {
|
void ModbusServerRTU::doBegin(uint32_t baudRate, int coreID, uint32_t userInterval) {
|
||||||
// Task already running? Stop it in case.
|
// Task already running? Stop it in case.
|
||||||
end();
|
end();
|
||||||
|
|
||||||
// Set minimum interval time
|
// Set minimum interval time
|
||||||
MSRinterval = RTUutils::calculateInterval(baudRate);
|
MSRinterval = RTUutils::calculateInterval(baudRate);
|
||||||
|
|
||||||
|
// If user defined interval is longer, use that
|
||||||
|
if (MSRinterval < userInterval) {
|
||||||
|
MSRinterval = userInterval;
|
||||||
|
}
|
||||||
|
|
||||||
// Create unique task name
|
// Create unique task name
|
||||||
char taskName[18];
|
char taskName[18];
|
||||||
snprintf(taskName, 18, "MBsrv%02XRTU", instanceCounter);
|
snprintf(taskName, 18, "MBsrv%02XRTU", instanceCounter);
|
||||||
|
|
||||||
// Start task to handle the client
|
// Start task to handle the client
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&serve, taskName, 4096, this, 8, &serverTask, coreID >= 0 ? coreID : NULL);
|
xTaskCreatePinnedToCore((TaskFunction_t)&serve, taskName, SERVER_TASK_STACK, this, 8, &serverTask, coreID >= 0 ? coreID : NULL);
|
||||||
|
|
||||||
LOG_D("Server task %d started. Interval=%d\n", (uint32_t)serverTask, MSRinterval);
|
LOG_D("Server task %d started. Interval=%d\n", (uint32_t)serverTask, MSRinterval);
|
||||||
}
|
}
|
||||||
|
@ -180,10 +185,12 @@ void ModbusServerRTU::serve(ModbusServerRTU *myServer) {
|
||||||
}
|
}
|
||||||
// Is it a broadcast?
|
// Is it a broadcast?
|
||||||
if (request[0] == 0) {
|
if (request[0] == 0) {
|
||||||
|
LOG_D("Broadcast!\n");
|
||||||
// Yes. Do we have a listener?
|
// Yes. Do we have a listener?
|
||||||
if (myServer->listener) {
|
if (myServer->listener) {
|
||||||
// Yes. call it
|
// Yes. call it
|
||||||
myServer->listener(request);
|
myServer->listener(request);
|
||||||
|
LOG_D("Broadcast served.\n");
|
||||||
}
|
}
|
||||||
// else we simply ignore it
|
// else we simply ignore it
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -32,8 +32,8 @@ public:
|
||||||
~ModbusServerRTU();
|
~ModbusServerRTU();
|
||||||
|
|
||||||
// begin: create task with RTU server to accept requests
|
// begin: create task with RTU server to accept requests
|
||||||
void begin(Stream& serial, uint32_t baudRate, int coreID = -1);
|
void begin(Stream& serial, uint32_t baudRate, int coreID = -1, uint32_t userInterval = 0);
|
||||||
void begin(HardwareSerial& serial, int coreID = -1);
|
void begin(HardwareSerial& serial, int coreID = -1, uint32_t userInterval = 0);
|
||||||
|
|
||||||
// end: kill server task
|
// end: kill server task
|
||||||
void end();
|
void end();
|
||||||
|
@ -64,7 +64,7 @@ protected:
|
||||||
inline void isInstance() { } // Make class instantiable
|
inline void isInstance() { } // Make class instantiable
|
||||||
|
|
||||||
// internal common begin function
|
// internal common begin function
|
||||||
void doBegin(uint32_t baudRate, int coreID);
|
void doBegin(uint32_t baudRate, int coreID, uint32_t userInterval);
|
||||||
|
|
||||||
static uint8_t instanceCounter; // Number of RTU servers created (for task names)
|
static uint8_t instanceCounter; // Number of RTU servers created (for task names)
|
||||||
TaskHandle_t serverTask; // task of the started server
|
TaskHandle_t serverTask; // task of the started server
|
||||||
|
|
|
@ -50,7 +50,7 @@ FCType FCT::getType(uint8_t functionCode) {
|
||||||
return table[functionCode & 0x7F];
|
return table[functionCode & 0x7F];
|
||||||
}
|
}
|
||||||
|
|
||||||
// setType: change the type of a function code.
|
// redefineType: change the type of a function code.
|
||||||
// This is possible only for the codes undefined yet and will return
|
// This is possible only for the codes undefined yet and will return
|
||||||
// the effective type
|
// the effective type
|
||||||
FCType FCT::redefineType(uint8_t functionCode, const FCType type) {
|
FCType FCT::redefineType(uint8_t functionCode, const FCType type) {
|
||||||
|
|
|
@ -84,6 +84,9 @@ enum Error : uint8_t {
|
||||||
UNDEFINED_ERROR = 0xFF // otherwise uncovered communication error
|
UNDEFINED_ERROR = 0xFF // otherwise uncovered communication error
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Readable expression for the "illegal" server ID of 0
|
||||||
|
#define ANY_SERVER 0x00
|
||||||
|
|
||||||
#ifndef MINIMAL
|
#ifndef MINIMAL
|
||||||
|
|
||||||
// Constants for float and double re-ordering
|
// Constants for float and double re-ordering
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
|
// #define LOCAL_LOG_LEVEL LOG_LEVEL_VERBOSE
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
|
#if HAS_FREERTOS
|
||||||
// calcCRC: calculate Modbus CRC16 on a given array of bytes
|
// calcCRC: calculate Modbus CRC16 on a given array of bytes
|
||||||
uint16_t RTUutils::calcCRC(const uint8_t *data, uint16_t len) {
|
uint16_t RTUutils::calcCRC(const uint8_t *data, uint16_t len) {
|
||||||
// CRC16 pre-calculated tables
|
// CRC16 pre-calculated tables
|
||||||
|
@ -463,3 +464,4 @@ const char RTUutils::ASCIIread[] = {
|
||||||
const char RTUutils::ASCIIwrite[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
const char RTUutils::ASCIIwrite[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||||
0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46
|
0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#define HAS_ETHERNET 1
|
#define HAS_ETHERNET 1
|
||||||
#define IS_LINUX 0
|
#define IS_LINUX 0
|
||||||
#define NEED_UART_PATCH 1
|
#define NEED_UART_PATCH 1
|
||||||
|
const unsigned int SERVER_TASK_STACK = 4096;
|
||||||
|
const unsigned int CLIENT_TASK_STACK = 4096;
|
||||||
|
|
||||||
/* === ESP8266 DEFINITIONS AND MACROS === */
|
/* === ESP8266 DEFINITIONS AND MACROS === */
|
||||||
#elif defined(ESP8266)
|
#elif defined(ESP8266)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue