From b2e9515d44d681b77dc14ea4e356fa8144430c09 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 6 Aug 2025 20:23:31 +0100 Subject: [PATCH 1/3] Fix invalid C++ in eModbus (0xff in a char[]) --- Software/src/lib/eModbus-eModbus/RTUutils.cpp | 2 +- Software/src/lib/eModbus-eModbus/RTUutils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/src/lib/eModbus-eModbus/RTUutils.cpp b/Software/src/lib/eModbus-eModbus/RTUutils.cpp index c92d0ffd..fc4eaadf 100644 --- a/Software/src/lib/eModbus-eModbus/RTUutils.cpp +++ b/Software/src/lib/eModbus-eModbus/RTUutils.cpp @@ -440,7 +440,7 @@ ModbusMessage RTUutils::receive(uint8_t caller, Stream& serial, uint32_t timeout } // Lower 7 bit ASCII characters - all invalid are set to 0xFF -const char RTUutils::ASCIIread[] = { +const uint8_t RTUutils::ASCIIread[] = { /* 00-07 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* 08-0F */ 0xFF, 0xFF, 0xF2, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, // LF + CR /* 10-17 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, diff --git a/Software/src/lib/eModbus-eModbus/RTUutils.h b/Software/src/lib/eModbus-eModbus/RTUutils.h index e3f41be3..2306d4a4 100644 --- a/Software/src/lib/eModbus-eModbus/RTUutils.h +++ b/Software/src/lib/eModbus-eModbus/RTUutils.h @@ -60,7 +60,7 @@ static void prepareHardwareSerial(HardwareSerial& s, uint16_t bufferSize = 260) protected: // Printable characters for ASCII protocol: 012345678ABCDEF static const char ASCIIwrite[]; - static const char ASCIIread[]; + static const uint8_t ASCIIread[]; RTUutils() = delete; From 9eac0a90b54bf49ee37694c0ad85a918f7c37191 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 6 Aug 2025 20:25:57 +0100 Subject: [PATCH 2/3] Refactor Modbus inverter handling into superclass, use std::map instead of static array --- Software/src/inverter/BYD-MODBUS.cpp | 36 +--- Software/src/inverter/BYD-MODBUS.h | 14 ++ .../src/inverter/ModbusInverterProtocol.cpp | 181 +++++++++++++++++- .../src/inverter/ModbusInverterProtocol.h | 29 ++- .../src/lib/eModbus-eModbus/scripts/README.md | 1 - .../eModbus-eModbus/scripts/mbServerFCs.cpp | 173 ----------------- .../lib/eModbus-eModbus/scripts/mbServerFCs.h | 9 - 7 files changed, 219 insertions(+), 224 deletions(-) delete mode 100644 Software/src/lib/eModbus-eModbus/scripts/README.md delete mode 100644 Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.cpp delete mode 100644 Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.h diff --git a/Software/src/inverter/BYD-MODBUS.cpp b/Software/src/inverter/BYD-MODBUS.cpp index 980d4b78..4bf36747 100644 --- a/Software/src/inverter/BYD-MODBUS.cpp +++ b/Software/src/inverter/BYD-MODBUS.cpp @@ -2,22 +2,9 @@ #include "../datalayer/datalayer.h" #include "../devboard/hal/hal.h" #include "../devboard/utils/events.h" -#include "../lib/eModbus-eModbus/RTUutils.h" -#include "../lib/eModbus-eModbus/scripts/mbServerFCs.h" // For modbus register definitions, see https://gitlab.com/pelle8/inverter_resources/-/blob/main/byd_registers_modbus_rtu.md -#define HISTORY_LENGTH 3 // Amount of samples(minutes) that needs to match for register to be considered stale -static unsigned long previousMillis60s = 0; // will store last time a 60s event occured -static uint32_t user_configured_max_discharge_W = 0; -static uint32_t user_configured_max_charge_W = 0; -static uint32_t max_discharge_W = 0; -static uint32_t max_charge_W = 0; -static uint16_t register_401_history[HISTORY_LENGTH] = {0}; -static uint8_t history_index = 0; -static uint8_t bms_char_dis_status = STANDBY; -static bool all_401_values_equal = false; - void BydModbusInverter::update_values() { verify_temperature(); verify_inverter_modbus(); @@ -41,14 +28,20 @@ void BydModbusInverter::handle_static_data() { static uint16_t i = 100; for (uint8_t arr_idx = 0; arr_idx < sizeof(data_array_pointers) / sizeof(uint16_t*); arr_idx++) { uint16_t data_size = data_sizes[arr_idx]; - memcpy(&mbPV[i], data_array_pointers[arr_idx], data_size); + for (int j = 0; j < data_size / sizeof(uint16_t); j++) { + mbPV[i + j] = data_array_pointers[arr_idx][j]; + } i += data_size / sizeof(uint16_t); } static uint16_t init_p201[13] = {0, 0, 0, MAX_POWER, MAX_POWER, 0, 0, 53248, 10, 53248, 10, 0, 0}; - memcpy(&mbPV[200], init_p201, sizeof(init_p201)); + for (int i = 0; i < sizeof(init_p201) / sizeof(uint16_t); i++) { + mbPV[200 + i] = init_p201[i]; + } static uint16_t init_p301[24] = {0, 0, 128, 0, 0, 0, 0, 0, 0, 2000, 0, 2000, 75, 95, 0, 0, 16, 22741, 0, 0, 13, 52064, 230, 9900}; - memcpy(&mbPV[300], init_p301, sizeof(init_p301)); + for (int i = 0; i < sizeof(init_p301) / sizeof(uint16_t); i++) { + mbPV[300 + i] = init_p301[i]; + } } void BydModbusInverter::handle_update_data_modbusp201_byd() { @@ -150,10 +143,8 @@ bool BydModbusInverter::setup(void) { // Performs one time setup at startup ove // Init Static data to the RTU Modbus handle_static_data(); -#if HAS_FREERTOS // Init Serial2 connected to the RTU Modbus RTUutils::prepareHardwareSerial(Serial2); -#endif auto rx_pin = esp32hal->RS485_RX_PIN(); auto tx_pin = esp32hal->RS485_TX_PIN(); @@ -163,16 +154,9 @@ bool BydModbusInverter::setup(void) { // Performs one time setup at startup ove } Serial2.begin(9600, SERIAL_8N1, rx_pin, tx_pin); -#if HAS_FREERTOS - // Register served function code worker for server - MBserver->registerWorker(MBTCP_ID, READ_HOLD_REGISTER, &FC03); - MBserver->registerWorker(MBTCP_ID, WRITE_HOLD_REGISTER, &FC06); - MBserver->registerWorker(MBTCP_ID, WRITE_MULT_REGISTERS, &FC16); - MBserver->registerWorker(MBTCP_ID, R_W_MULT_REGISTERS, &FC23); // Start ModbusRTU background task - ((ModbusServerRTU*)MBserver)->begin(Serial2, esp32hal->MODBUS_CORE()); -#endif + MBserver.begin(Serial2, esp32hal->MODBUS_CORE()); return true; } diff --git a/Software/src/inverter/BYD-MODBUS.h b/Software/src/inverter/BYD-MODBUS.h index e9559e51..a51010c5 100644 --- a/Software/src/inverter/BYD-MODBUS.h +++ b/Software/src/inverter/BYD-MODBUS.h @@ -5,10 +5,12 @@ #define SELECTED_INVERTER_CLASS BydModbusInverter #endif +#include "../devboard/utils/types.h" #include "ModbusInverterProtocol.h" class BydModbusInverter : public ModbusInverterProtocol { public: + BydModbusInverter() : ModbusInverterProtocol(21) {} const char* name() override { return Name; } bool setup() override; void update_values(); @@ -23,6 +25,18 @@ class BydModbusInverter : public ModbusInverterProtocol { //BYD Modbus specific value const uint16_t MAX_POWER = 40960; + + static const int HISTORY_LENGTH = + 3; // Amount of samples(minutes) that needs to match for register to be considered stale + unsigned long previousMillis60s = 0; // will store last time a 60s event occured + uint32_t user_configured_max_discharge_W = 0; + uint32_t user_configured_max_charge_W = 0; + uint32_t max_discharge_W = 0; + uint32_t max_charge_W = 0; + uint16_t register_401_history[HISTORY_LENGTH] = {0}; + uint8_t history_index = 0; + uint8_t bms_char_dis_status = STANDBY; + bool all_401_values_equal = false; }; #endif diff --git a/Software/src/inverter/ModbusInverterProtocol.cpp b/Software/src/inverter/ModbusInverterProtocol.cpp index 97c64f38..b669f955 100644 --- a/Software/src/inverter/ModbusInverterProtocol.cpp +++ b/Software/src/inverter/ModbusInverterProtocol.cpp @@ -1,10 +1,181 @@ #include "ModbusInverterProtocol.h" +#include "../devboard/utils/logging.h" #include "../lib/eModbus-eModbus/ModbusServerRTU.h" -static const int MB_RTU_NUM_VALUES = 13100; -uint16_t mbPV[MB_RTU_NUM_VALUES]; // Process variable memory +// Creates a ModbusRTU server instance with 2000ms timeout +ModbusInverterProtocol::ModbusInverterProtocol(int serverId) : MBserver(2000) { + _serverId = serverId; -ModbusInverterProtocol::ModbusInverterProtocol() { - mbPV = ::mbPV; - MBserver = new ModbusServerRTU(2000); + MBserver.registerWorker(_serverId, READ_HOLD_REGISTER, + [this](ModbusMessage request) -> ModbusMessage { return FC03(request); }); + MBserver.registerWorker(_serverId, WRITE_HOLD_REGISTER, + [this](ModbusMessage request) -> ModbusMessage { return FC06(request); }); + MBserver.registerWorker(_serverId, WRITE_MULT_REGISTERS, + [this](ModbusMessage request) -> ModbusMessage { return FC16(request); }); + MBserver.registerWorker(_serverId, R_W_MULT_REGISTERS, + [this](ModbusMessage request) -> ModbusMessage { return FC23(request); }); +} + +ModbusInverterProtocol::~ModbusInverterProtocol() { + MBserver.unregisterWorker(_serverId, READ_HOLD_REGISTER); + MBserver.unregisterWorker(_serverId, WRITE_HOLD_REGISTER); + MBserver.unregisterWorker(_serverId, WRITE_MULT_REGISTERS); + MBserver.unregisterWorker(_serverId, R_W_MULT_REGISTERS); +} + +// Server function to handle FC 0x03 +ModbusMessage ModbusInverterProtocol::FC03(ModbusMessage request) { + ModbusMessage response; // The Modbus message we are going to give back + uint16_t addr = 0; // Start address + uint16_t words = 0; // # of words requested + request.get(2, addr); // read address from request + request.get(4, words); // read # of words from request + + // Address overflow? + if ((addr + words) > MBPV_MAX) { + // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); +#ifdef DEBUG_LOG + logging.printf("Modbus FC03 error: illegal request addr=%d words=%d\n", addr, words); +#endif + return response; + } + + // Set up response + response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(words * 2)); + for (uint8_t i = 0; i < words; ++i) { + // send increasing data values + response.add((uint16_t)(mbPV[addr + i])); + } + + // #ifdef DEBUG_LOG + // logging.printf("Modbus FC03 response: %d %d\n", addr, mbPV[addr]); + // #endif + + return response; +} + +// Server function to handle FC 0x06 +ModbusMessage ModbusInverterProtocol::FC06(ModbusMessage request) { + ModbusMessage response; // The Modbus message we are going to give back + uint16_t addr = 0; // Start address + uint16_t val = 0; // value to write + request.get(2, addr); // read address from request + request.get(4, val); // read # of words from request + + // Address overflow? + if ((addr) > MBPV_MAX) { + // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); +#ifdef DEBUG_LOG + logging.printf("Modbus FC06 error: illegal request addr=%d val=%d\n", addr, val); +#endif + return response; + } + + // Do the write + mbPV[addr] = val; + + // Set up response + response.add(request.getServerID(), request.getFunctionCode(), mbPV[addr]); + return response; +} + +// Server function to handle FC 0x10 (FC16) +ModbusMessage ModbusInverterProtocol::FC16(ModbusMessage request) { + ModbusMessage response; // The Modbus message we are going to give back + uint16_t addr = 0; // Start address + uint16_t words = 0; // total words to write + uint8_t bytes = 0; // # of data bytes in request + uint16_t val = 0; // value to be written + request.get(2, addr); // read address from request + request.get(4, words); // read # of words from request + request.get(6, bytes); // read # of data bytes from request (seems redundant with # of words) + + // # of registers proper? + if ((bytes != (words * 2)) // byte count in request must match # of words in request + || (words > 123)) // can't support more than this in request packet + { // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE); +#ifdef DEBUG_LOG + logging.printf("Modbus FC16 error: bad registers addr=%d words=%d bytes=%d\n", addr, words, bytes); +#endif + return response; + } + // Address overflow? + if ((addr + words) > MBPV_MAX) { + // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); +#ifdef DEBUG_LOG + logging.printf("Modbus FC16 error: overflow addr=%d words=%d\n", addr, words); +#endif + return response; + } + + // Do the writes + for (uint8_t i = 0; i < words; ++i) { + request.get(7 + (i * 2), val); //data starts at byte 6 in request packet + mbPV[addr + i] = val; + } + + // Set up response + response.add(request.getServerID(), request.getFunctionCode(), addr, words); + return response; +} + +// Server function to handle FC 0x17 (FC23) +ModbusMessage ModbusInverterProtocol::FC23(ModbusMessage request) { + ModbusMessage response; // The Modbus message we are going to give back + uint16_t read_addr = 0; // Start address for read + uint16_t read_words = 0; // # of words requested for read + uint16_t write_addr = 0; // Start address for write + uint16_t write_words = 0; // total words to write + uint8_t write_bytes = 0; // # of data bytes in write request + uint16_t write_val = 0; // value to be written + request.get(2, read_addr); // read address from request + request.get(4, read_words); // read # of words from request + request.get(6, write_addr); // read address from request + request.get(8, write_words); // read # of words from request + request.get(10, write_bytes); // read # of data bytes from request (seems redundant with # of words) + + // ERROR CHECKS + // # of registers proper? + if ((write_bytes != (write_words * 2)) // byte count in request must match # of words in request + || (write_words > 121) // can't fit more than this in the packet for FC23 + || (read_words > 125)) // can't fit more than this in the response packet + { // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE); +#ifdef DEBUG_LOG + logging.printf("Modbus FC23 error: bad registers write_addr=%d write_words=%d write_bytes=%d read_words=%d\n", + write_addr, write_words, write_bytes, read_words); +#endif + return response; + } + // Address overflow? + if (((write_addr + write_words) > MBPV_MAX) || + ((read_addr + read_words) > MBPV_MAX)) { // Yes - send respective error response + response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); +#ifdef DEBUG_LOG + logging.printf("Modbus FC23 error: overflow write_addr=%d write_words=%d read_addr=%d read_words=%d\n", write_addr, + write_words, read_addr, read_words); +#endif + return response; + } + + //WRITE SECTION - write is done before read for FC23 + // Do the writes + for (uint8_t i = 0; i < write_words; ++i) { + request.get(11 + (i * 2), write_val); //data starts at byte 6 in request packet + mbPV[write_addr + i] = write_val; + } + + // READ SECTION + // Set up response + response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(read_words * 2)); + for (uint8_t i = 0; i < read_words; ++i) { + // send increasing data values + response.add((uint16_t)(mbPV[read_addr + i])); + } + + return response; } diff --git a/Software/src/inverter/ModbusInverterProtocol.h b/Software/src/inverter/ModbusInverterProtocol.h index c77104a4..a56913c3 100644 --- a/Software/src/inverter/ModbusInverterProtocol.h +++ b/Software/src/inverter/ModbusInverterProtocol.h @@ -1,12 +1,14 @@ #ifndef MODBUS_INVERTER_PROTOCOL_H #define MODBUS_INVERTER_PROTOCOL_H -#include -#include -#include "../lib/eModbus-eModbus/ModbusServer.h" +#include "../lib/eModbus-eModbus/ModbusMessage.h" +#include "../lib/eModbus-eModbus/ModbusServerRTU.h" #include "InverterProtocol.h" -extern uint16_t mbPV[]; +#include + +#include +#include // The abstract base class for all Modbus inverter protocols class ModbusInverterProtocol : public InverterProtocol { @@ -14,15 +16,22 @@ class ModbusInverterProtocol : public InverterProtocol { InverterInterfaceType interface_type() { return InverterInterfaceType::Modbus; } protected: - // Create a ModbusRTU server instance with 2000ms timeout - ModbusInverterProtocol(); + ModbusInverterProtocol(int serverId); + ~ModbusInverterProtocol(); - static const int MB_RTU_NUM_VALUES = 13100; + ModbusMessage FC03(ModbusMessage request); + ModbusMessage FC06(ModbusMessage request); + ModbusMessage FC16(ModbusMessage request); + ModbusMessage FC23(ModbusMessage request); - // Modbus register file - uint16_t* mbPV; + // The highest Modbus register we allow reads/writes from + static const int MBPV_MAX = 30000; + // The Modbus server ID we respond to + int _serverId; + // The Modbus registers themselves + std::map mbPV; - ModbusServer* MBserver; + ModbusServerRTU MBserver; }; #endif diff --git a/Software/src/lib/eModbus-eModbus/scripts/README.md b/Software/src/lib/eModbus-eModbus/scripts/README.md deleted file mode 100644 index 9028391d..00000000 --- a/Software/src/lib/eModbus-eModbus/scripts/README.md +++ /dev/null @@ -1 +0,0 @@ -The scripts in this folder originate from [eModbus discussion 147](https://github.com/eModbus/eModbus/discussions/147). diff --git a/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.cpp b/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.cpp deleted file mode 100644 index aac77929..00000000 --- a/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "mbServerFCs.h" -#include "../Logging.h" - -//modbus register memory - declared in main.cpp - -extern uint16_t mbPV[MBPV_MAX]; - -// Server function to handle FC 0x03 -ModbusMessage FC03(ModbusMessage request) { - //Serial.println(request); - ModbusMessage response; // The Modbus message we are going to give back - uint16_t addr = 0; // Start address - uint16_t words = 0; // # of words requested - request.get(2, addr); // read address from request - request.get(4, words); // read # of words from request - char debugString[1000]; - - LOG_D("FC03 received: read %d words @ %d\r\n", words, addr); - - // Address overflow? - if ((addr + words) > MBPV_MAX) { - // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); - LOG_D("ERROR - ILLEGAL DATA ADDRESS\r\n"); - return response; - } - - // Set up response - response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(words * 2)); - sprintf(debugString, "Read : "); - for (uint8_t i = 0; i < words; ++i) { - // send increasing data values - response.add((uint16_t)(mbPV[addr + i])); - sprintf(debugString + strlen(debugString), "%i ", mbPV[addr + i]); - } - LOG_V("%s\r\n", debugString); - - return response; -} - -// Server function to handle FC 0x06 -ModbusMessage FC06(ModbusMessage request) { - //Serial.println(request); - ModbusMessage response; // The Modbus message we are going to give back - uint16_t addr = 0; // Start address - uint16_t val = 0; // value to write - request.get(2, addr); // read address from request - request.get(4, val); // read # of words from request - - LOG_D("FC06 received: write 1 word @ %d\r\n", addr); - - // Address overflow? - if ((addr) > MBPV_MAX) { - // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); - LOG_D("ERROR - ILLEGAL DATA ADDRESS\r\n"); - return response; - } - - // Do the write - mbPV[addr] = val; - LOG_V("Write : %i", val); - - // Set up response - response.add(request.getServerID(), request.getFunctionCode(), mbPV[addr]); - return response; -} - -// Server function to handle FC 0x10 (FC16) -ModbusMessage FC16(ModbusMessage request) { - //Serial.println(request); - ModbusMessage response; // The Modbus message we are going to give back - uint16_t addr = 0; // Start address - uint16_t words = 0; // total words to write - uint8_t bytes = 0; // # of data bytes in request - uint16_t val = 0; // value to be written - request.get(2, addr); // read address from request - request.get(4, words); // read # of words from request - request.get(6, bytes); // read # of data bytes from request (seems redundant with # of words) - char debugString[1000]; - - LOG_D("FC16 received: write %d words @ %d\r\n", words, addr); - - // # of registers proper? - if ((bytes != (words * 2)) // byte count in request must match # of words in request - || (words > 123)) // can't support more than this in request packet - { // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE); - LOG_D("ERROR - ILLEGAL DATA VALUE\r\n"); - return response; - } - // Address overflow? - if ((addr + words) > MBPV_MAX) { - // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); - LOG_D("ERROR - ILLEGAL DATA ADDRESS\r\n"); - return response; - } - - // Do the writes - sprintf(debugString, "Write : "); - for (uint8_t i = 0; i < words; ++i) { - request.get(7 + (i * 2), val); //data starts at byte 6 in request packet - mbPV[addr + i] = val; - sprintf(debugString + strlen(debugString), "%i ", mbPV[addr + i]); - } - LOG_V("%s\r\n", debugString); - - // Set up response - response.add(request.getServerID(), request.getFunctionCode(), addr, words); - return response; -} - -// Server function to handle FC 0x17 (FC23) -ModbusMessage FC23(ModbusMessage request) { - //Serial.println(request); - ModbusMessage response; // The Modbus message we are going to give back - uint16_t read_addr = 0; // Start address for read - uint16_t read_words = 0; // # of words requested for read - uint16_t write_addr = 0; // Start address for write - uint16_t write_words = 0; // total words to write - uint8_t write_bytes = 0; // # of data bytes in write request - uint16_t write_val = 0; // value to be written - request.get(2, read_addr); // read address from request - request.get(4, read_words); // read # of words from request - request.get(6, write_addr); // read address from request - request.get(8, write_words); // read # of words from request - request.get(10, write_bytes); // read # of data bytes from request (seems redundant with # of words) - char debugString[1000]; - - LOG_D("FC23 received: write %d @ %d, read %d @ %d\r\n", write_words, write_addr, read_words, read_addr); - - // ERROR CHECKS - // # of registers proper? - if ((write_bytes != (write_words * 2)) // byte count in request must match # of words in request - || (write_words > 121) // can't fit more than this in the packet for FC23 - || (read_words > 125)) // can't fit more than this in the response packet - { // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE); - LOG_D("ERROR - ILLEGAL DATA VALUE\r\n"); - return response; - } - // Address overflow? - if (((write_addr + write_words) > MBPV_MAX) || - ((read_addr + read_words) > MBPV_MAX)) { // Yes - send respective error response - response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS); - LOG_D("ERROR - ILLEGAL DATA ADDRESS\r\n"); - return response; - } - - //WRITE SECTION - write is done before read for FC23 - // Do the writes - sprintf(debugString, "Write: "); - for (uint8_t i = 0; i < write_words; ++i) { - request.get(11 + (i * 2), write_val); //data starts at byte 6 in request packet - mbPV[write_addr + i] = write_val; - sprintf(debugString + strlen(debugString), "%i ", mbPV[write_addr + i]); - } - LOG_V("%s\r\n", debugString); - - // READ SECTION - // Set up response - sprintf(debugString, "Read: "); - response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(read_words * 2)); - for (uint8_t i = 0; i < read_words; ++i) { - // send increasing data values - response.add((uint16_t)(mbPV[read_addr + i])); - sprintf(debugString + strlen(debugString), "%i ", mbPV[read_addr + i]); - } - LOG_V("%s\r\n", debugString); - - return response; -} diff --git a/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.h b/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.h deleted file mode 100644 index a261d579..00000000 --- a/Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "../ModbusServerRTU.h" - -#define MBTCP_ID 21 // modbus TCP server ID -#define MBPV_MAX 30000 - -ModbusMessage FC03(ModbusMessage request); -ModbusMessage FC06(ModbusMessage request); -ModbusMessage FC16(ModbusMessage request); -ModbusMessage FC23(ModbusMessage request); From 55d8a24f55a08602463d96a539ebf2f8e93ea5a6 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 6 Aug 2025 20:28:55 +0100 Subject: [PATCH 3/3] Add more Arduino/FreeRTOS test stubs so that eModbus builds in ESP32 mode. --- test/CMakeLists.txt | 10 +++++++--- test/emul/Arduino.cpp | 11 +++++++++++ test/emul/Arduino.h | 9 +++++++++ test/emul/HardwareSerial.h | 11 ++++++++++- test/emul/Print.h | 9 ++++++++- test/emul/Stream.h | 8 +++++++- test/emul/freertos/FreeRTOS.cpp | 10 ++++++++++ test/emul/freertos/FreeRTOS.h | 21 +++++++++++++++++++++ test/emul/freertos/task.h | 2 ++ test/emul/serial.cpp | 2 +- test/safety_tests.cpp | 1 - test/tests.cpp | 3 --- 12 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 test/emul/freertos/FreeRTOS.cpp create mode 100644 test/emul/freertos/FreeRTOS.h create mode 100644 test/emul/freertos/task.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5aa74ad9..d945a8c0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -62,7 +62,7 @@ include_directories("${source_dir}/googletest/include" include_directories(emul) # For eModBus -add_compile_definitions(__linux__ HW_LILYGO NISSAN_LEAF_BATTERY) +add_compile_definitions(ESP32 HW_LILYGO NISSAN_LEAF_BATTERY) # add the executable add_executable(tests @@ -74,9 +74,12 @@ add_executable(tests ../Software/src/devboard/utils/events.cpp ../Software/src/datalayer/datalayer.cpp ../Software/src/datalayer/datalayer_extended.cpp - ../Software/src/lib/eModbus-eModbus/ModbusMessage.cpp - ../Software/src/lib/eModbus-eModbus/ModbusTypeDefs.cpp ../Software/src/lib/eModbus-eModbus/Logging.cpp + ../Software/src/lib/eModbus-eModbus/ModbusMessage.cpp + ../Software/src/lib/eModbus-eModbus/ModbusServer.cpp + ../Software/src/lib/eModbus-eModbus/ModbusServerRTU.cpp + ../Software/src/lib/eModbus-eModbus/ModbusTypeDefs.cpp + ../Software/src/lib/eModbus-eModbus/RTUutils.cpp # ../Software/src/lib/eModbus-eModbus/scripts/mbServerFCs.cpp ../Software/USER_SETTINGS.cpp ../Software/src/battery/BATTERIES.cpp @@ -90,6 +93,7 @@ add_executable(tests emul/time.cpp emul/serial.cpp emul/Arduino.cpp + emul/freertos/FreeRTOS.cpp ) target_link_libraries(tests diff --git a/test/emul/Arduino.cpp b/test/emul/Arduino.cpp index b2b85522..1f6940df 100644 --- a/test/emul/Arduino.cpp +++ b/test/emul/Arduino.cpp @@ -1,5 +1,16 @@ #include "Arduino.h" +void delay(unsigned long ms) {} +void delayMicroseconds(unsigned long us) {} +int digitalRead(uint8_t pin) { + return 0; +} +void digitalWrite(uint8_t pin, uint8_t val) {} +unsigned long micros() { + return 0; +} +void pinMode(uint8_t pin, uint8_t mode) {} + int max(int a, int b) { return (a > b) ? a : b; } diff --git a/test/emul/Arduino.h b/test/emul/Arduino.h index c3ae2da7..8024518d 100644 --- a/test/emul/Arduino.h +++ b/test/emul/Arduino.h @@ -1,7 +1,13 @@ #ifndef ARDUINO_H #define ARDUINO_H +#include #include +#include +#include + +#include "HardwareSerial.h" +#include "Print.h" #include "esp-hal-gpio.h" @@ -9,10 +15,13 @@ void pinMode(uint8_t pin, uint8_t mode); void digitalWrite(uint8_t pin, uint8_t val); int digitalRead(uint8_t pin); +unsigned long micros(); // Can be previously declared as a macro in stupid eModbus #undef millis unsigned long millis(); +void delay(unsigned long ms); +void delayMicroseconds(unsigned long us); int max(int a, int b); #endif diff --git a/test/emul/HardwareSerial.h b/test/emul/HardwareSerial.h index 3145d322..e20000a2 100644 --- a/test/emul/HardwareSerial.h +++ b/test/emul/HardwareSerial.h @@ -2,6 +2,8 @@ #define HARDWARESERIAL_H #include +#include +#include "Print.h" #include "Stream.h" enum SerialConfig { @@ -33,11 +35,18 @@ enum SerialConfig { class HardwareSerial : public Stream { public: + int available() { return 0; } + uint32_t baudRate() { return 9600; } void begin(unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 120) {} + int read() { return 0; } + void setTxBufferSize(uint16_t size) {} + void setRxBufferSize(uint16_t size) {} + bool setRxFIFOFull(uint8_t fifoBytes) { return false; } + size_t write(uint8_t) { return 0; } }; -extern HardwareSerial Serial0; +extern HardwareSerial Serial; extern HardwareSerial Serial1; extern HardwareSerial Serial2; diff --git a/test/emul/Print.h b/test/emul/Print.h index 4a4d7edc..eb715272 100644 --- a/test/emul/Print.h +++ b/test/emul/Print.h @@ -1,6 +1,13 @@ #ifndef PRINT_H #define PRINT_H -class Print {}; +class Print { + public: + virtual void flush() {} + void printf(const char* format, ...) {} + virtual size_t write(uint8_t) = 0; + virtual size_t write(const char* s) { return 0; } + virtual size_t write(const uint8_t* buffer, size_t size) { return 0; } +}; #endif diff --git a/test/emul/Stream.h b/test/emul/Stream.h index bd9b3b5f..c1847603 100644 --- a/test/emul/Stream.h +++ b/test/emul/Stream.h @@ -1,6 +1,12 @@ #ifndef STREAM_H #define STREAM_H -class Stream {}; +#include "Print.h" + +class Stream : public Print { + public: + virtual int available() = 0; + virtual int read() = 0; +}; #endif diff --git a/test/emul/freertos/FreeRTOS.cpp b/test/emul/freertos/FreeRTOS.cpp new file mode 100644 index 00000000..6c5e9e58 --- /dev/null +++ b/test/emul/freertos/FreeRTOS.cpp @@ -0,0 +1,10 @@ +#include "FreeRTOS.h" + +extern "C" { +BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pxTaskCode, const char* const pcName, const uint32_t ulStackDepth, + void* const pvParameters, UBaseType_t uxPriority, TaskHandle_t* const pxCreatedTask, + const BaseType_t xCoreID) { + return 0; +} +void vTaskDelete(TaskHandle_t xTaskToDelete) {} +} diff --git a/test/emul/freertos/FreeRTOS.h b/test/emul/freertos/FreeRTOS.h new file mode 100644 index 00000000..9cd492ef --- /dev/null +++ b/test/emul/freertos/FreeRTOS.h @@ -0,0 +1,21 @@ +#ifndef _FREERTOS_H_ +#define _FREERTOS_H_ + +#include "task.h" + +#include + +typedef int BaseType_t; +typedef unsigned int UBaseType_t; + +const BaseType_t tskNO_AFFINITY = -1; + +extern "C" { +BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pxTaskCode, const char* const pcName, const uint32_t ulStackDepth, + void* const pvParameters, UBaseType_t uxPriority, TaskHandle_t* const pxCreatedTask, + const BaseType_t xCoreID); + +void vTaskDelete(TaskHandle_t xTaskToDelete); +} + +#endif diff --git a/test/emul/freertos/task.h b/test/emul/freertos/task.h new file mode 100644 index 00000000..7462b68d --- /dev/null +++ b/test/emul/freertos/task.h @@ -0,0 +1,2 @@ +typedef void* TaskHandle_t; +typedef void (*TaskFunction_t)(void*); diff --git a/test/emul/serial.cpp b/test/emul/serial.cpp index 254416a4..4a551ba6 100644 --- a/test/emul/serial.cpp +++ b/test/emul/serial.cpp @@ -1,5 +1,5 @@ #include "HardwareSerial.h" -HardwareSerial Serial0; +HardwareSerial Serial; HardwareSerial Serial1; HardwareSerial Serial2; diff --git a/test/safety_tests.cpp b/test/safety_tests.cpp index d79d80a7..d6f5b55f 100644 --- a/test/safety_tests.cpp +++ b/test/safety_tests.cpp @@ -3,7 +3,6 @@ #include "../Software/src/datalayer/datalayer.h" #include "../Software/src/devboard/safety/safety.h" #include "../Software/src/devboard/utils/events.h" -#include "../Software/src/inverter/ModbusInverterProtocol.h" TEST(SafetyTests, ShouldSetEventWhenTemperatureTooHigh) { init_events(); diff --git a/test/tests.cpp b/test/tests.cpp index c37b1b55..29cf7241 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -4,7 +4,6 @@ #include "../Software/src/datalayer/datalayer.h" #include "../Software/src/devboard/safety/safety.h" #include "../Software/src/devboard/utils/events.h" -#include "../Software/src/inverter/ModbusInverterProtocol.h" int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); @@ -12,5 +11,3 @@ int main(int argc, char** argv) { } void store_settings_equipment_stop(void) {} - -ModbusInverterProtocol::ModbusInverterProtocol() {}