Add support for acting as Modbus server (#4874)

Co-authored-by: Jeroen van Oort <jeroen.vanoort@webparking.nl>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Jeroen van Oort
2024-05-22 16:17:32 +12:00
committed by GitHub
co-authored by Jeroen van Oort Jesse Hills
parent 76abf2200c
commit 1ca7c2d7dd
7 changed files with 203 additions and 21 deletions
+19 -8
View File
@@ -77,7 +77,13 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
ESP_LOGD(TAG, "Modbus user-defined function %02X found", function_code);
} else {
// the response for write command mirrors the requests and data startes at offset 2 instead of 3 for read commands
// data starts at 2 and length is 4 for read registers commands
if (this->role == ModbusRole::SERVER && (function_code == 0x3 || function_code == 0x4)) {
data_offset = 2;
data_len = 4;
}
// the response for write command mirrors the requests and data starts at offset 2 instead of 3 for read commands
if (function_code == 0x5 || function_code == 0x06 || function_code == 0xF || function_code == 0x10) {
data_offset = 2;
data_len = 4;
@@ -123,6 +129,9 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
// Ignore modbus exception not related to a pending command
ESP_LOGD(TAG, "Ignoring Modbus error - not expecting a response");
}
} else if (this->role == ModbusRole::SERVER && (function_code == 0x3 || function_code == 0x4)) {
device->on_modbus_read_registers(function_code, uint16_t(data[1]) | (uint16_t(data[0]) << 8),
uint16_t(data[3]) | (uint16_t(data[2]) << 8));
} else {
device->on_modbus_data(data);
}
@@ -164,16 +173,18 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address
std::vector<uint8_t> data;
data.push_back(address);
data.push_back(function_code);
data.push_back(start_address >> 8);
data.push_back(start_address >> 0);
if (function_code != 0x5 && function_code != 0x6) {
data.push_back(number_of_entities >> 8);
data.push_back(number_of_entities >> 0);
if (this->role == ModbusRole::CLIENT) {
data.push_back(start_address >> 8);
data.push_back(start_address >> 0);
if (function_code != 0x5 && function_code != 0x6) {
data.push_back(number_of_entities >> 8);
data.push_back(number_of_entities >> 0);
}
}
if (payload != nullptr) {
if (function_code == 0xF || function_code == 0x10) { // Write multiple
data.push_back(payload_len); // Byte count is required for write
if (this->role == ModbusRole::SERVER || function_code == 0xF || function_code == 0x10) { // Write multiple
data.push_back(payload_len); // Byte count is required for write
} else {
payload_len = 2; // Write single register or coil
}