diff --git a/src/Modbus.h b/src/Modbus.h index 93f4220..44a404c 100644 --- a/src/Modbus.h +++ b/src/Modbus.h @@ -173,16 +173,22 @@ class Modbus { struct frame_arg_t { bool to_server; union { - uint8_t slaveId; + // For RTU + struct { + uint8_t slaveId; + bool validFrame; + }; + // For TCP struct { uint8_t unitId; uint32_t ipaddr; uint16_t transactionId; }; }; - frame_arg_t(uint8_t s, bool m = false) { - slaveId = s; - to_server = m; + frame_arg_t(uint8_t _slaveId, bool _to_server = false, bool _validFrame = true) { + slaveId = _slaveId; + to_server = _to_server; + validFrame = _validFrame; }; frame_arg_t(uint8_t u, uint32_t a, uint16_t t, bool m = false) { unitId = u; diff --git a/src/ModbusRTU.cpp b/src/ModbusRTU.cpp index a00d609..fbcee8c 100644 --- a/src/ModbusRTU.cpp +++ b/src/ModbusRTU.cpp @@ -269,13 +269,14 @@ void ModbusRTUTemplate::task() { //_port->readBytes(_frame, _len); uint16_t frameCrc = ((_frame[_len - 2] << 8) | _frame[_len - 1]); // Last two byts = crc _len = _len - 2; // Decrease by CRC 2 bytes - if (frameCrc != crc16(address, _frame, _len)) { // CRC Check - goto cleanup; - } + bool crcError = frameCrc != crc16(address, _frame, _len); + valid_frame = valid_frame && !crcError; _reply = EX_PASSTHROUGH; if (_cbRaw) { - frame_arg_t header_data = { address, !isMaster }; - _reply = _cbRaw(_frame, _len, (void*)&header_data); + if (!crcError || _cbRawIncludeCrcErrors) { + frame_arg_t header_data = { address, !isMaster, valid_frame }; + _reply = _cbRaw(_frame, _len, (void*)&header_data); + } } if (!valid_frame && _reply != EX_FORCE_PROCESS) { goto cleanup; @@ -326,4 +327,9 @@ bool ModbusRTUTemplate::cleanup() { return true; } return false; -} \ No newline at end of file +} + +bool ModbusRTUTemplate::onRaw(cbRaw cb, bool includeCrcErrors) { + _cbRawIncludeCrcErrors = includeCrcErrors; + return Modbus::onRaw(cb); +} diff --git a/src/ModbusRTU.h b/src/ModbusRTU.h index ce54348..d052715 100644 --- a/src/ModbusRTU.h +++ b/src/ModbusRTU.h @@ -30,6 +30,7 @@ class ModbusRTUTemplate : public Modbus { TAddress _sentReg = COIL(0); uint16_t maxRegs = MODBUS_MAX_WORDS; uint8_t address = 0; + bool _cbRawIncludeCrcErrors = false; uint16_t send(uint8_t slaveId, TAddress startreg, cbTransaction cb, uint8_t unit = MODBUSIP_UNIT, uint8_t* data = nullptr, bool waitResponse = true); // Prepare and send ModbusRTU frame. _frame buffer and _len should be filled with Modbus data @@ -61,6 +62,8 @@ class ModbusRTUTemplate : public Modbus { uint8_t server() { return _slaveId; } inline uint8_t slave() { return server(); } uint32_t eventSource() override {return address;} + // Overload + bool onRaw(cbRaw cb = nullptr, bool includeCrcErrors = false); }; template