In the first serie of tests this seems to work right.

This commit is contained in:
JeroenSt 2022-08-17 19:55:41 +02:00
parent 355e31ff2e
commit 96a1eb3ae5
2 changed files with 39 additions and 52 deletions

View File

@ -75,13 +75,12 @@ uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint1
frame[framepointer++] = function_code; frame[framepointer++] = function_code;
frame[framepointer++] = (uint8_t)(start_address >> 8); // MSB frame[framepointer++] = (uint8_t)(start_address >> 8); // MSB
frame[framepointer++] = (uint8_t)(start_address); // LSB frame[framepointer++] = (uint8_t)(start_address); // LSB
if ((function_code < 5) || (function_code == 15) || (function_code == 16)) if (function_code < 5)
{ {
frame[framepointer++] = (uint8_t)(register_count >> 8); // MSB frame[framepointer++] = (uint8_t)(register_count >> 8); // MSB
frame[framepointer++] = (uint8_t)(register_count); // LSB frame[framepointer++] = (uint8_t)(register_count); // LSB
} }
else if ((function_code == 5) || (function_code == 6))
if ((function_code == 5) || (function_code == 6))
{ {
if (registers == NULL) if (registers == NULL)
{ {
@ -96,9 +95,10 @@ uint8_t TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint1
frame[framepointer++] = (uint8_t)(registers[0] >> 8); // MSB frame[framepointer++] = (uint8_t)(registers[0] >> 8); // MSB
frame[framepointer++] = (uint8_t)(registers[0]); // LSB frame[framepointer++] = (uint8_t)(registers[0]); // LSB
} }
else if ((function_code == 15) || (function_code == 16))
if ((function_code == 15) || (function_code == 16))
{ {
frame[framepointer++] = (uint8_t)(register_count >> 8); // MSB
frame[framepointer++] = (uint8_t)(register_count); // LSB
frame[framepointer++] = register_count * 2; frame[framepointer++] = register_count * 2;
if (registers == NULL) if (registers == NULL)
{ {
@ -166,7 +166,7 @@ uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t data_count)
// 10 = Gateway Path Unavailable // 10 = Gateway Path Unavailable
// 11 = Gateway Target device failed to respond // 11 = Gateway Target device failed to respond
} }
if ((buffer[2] == 5) || (buffer[2] == 6) || (buffer[2] == 15) || (buffer[2] == 16)) header_length = 2; // Addr, Func if ((buffer[1] == 5) || (buffer[1] == 6) || (buffer[1] == 15) || (buffer[1] == 16)) header_length = 4; // Addr, Func, StartAddr
} }
} }

View File

@ -218,7 +218,7 @@ void ModbusBridgeHandle(void)
if (error) if (error)
{ {
AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR Driver error %d"), error); AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR Driver receive error %d"), error);
free(buffer); free(buffer);
return; return;
} }
@ -285,12 +285,21 @@ void ModbusBridgeHandle(void)
ResponseJsonEnd(); ResponseJsonEnd();
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED));
} }
else if ((buffer[1] > 0) && (buffer[1] < 5)) // Read Registers else if ((buffer[1] > 0) && (buffer[1] < 7)) // Read Registers
{ {
uint8_t dataOffset = 3;
Response_P(PSTR("{\"" D_JSON_MODBUS_RECEIVED "\":{")); Response_P(PSTR("{\"" D_JSON_MODBUS_RECEIVED "\":{"));
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_DEVICE_ADDRESS "\":%d,"), buffer[0]); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_DEVICE_ADDRESS "\":%d,"), buffer[0]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_FUNCTION_CODE "\":%d,"), buffer[1]); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_FUNCTION_CODE "\":%d,"), buffer[1]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), modbusBridge.startAddress); if (buffer[1] < 5)
{
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), modbusBridge.startAddress);
}
else
{
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), (buffer[2] << 8) + buffer[3]);
dataOffset = 4;
}
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_LENGTH "\":%d,"), tasmotaModbus->ReceiveCount()); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_LENGTH "\":%d,"), tasmotaModbus->ReceiveCount());
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_COUNT "\":%d,"), modbusBridge.count); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_COUNT "\":%d,"), modbusBridge.count);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_VALUES "\":[")); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_VALUES "\":["));
@ -301,10 +310,10 @@ void ModbusBridgeHandle(void)
if (modbusBridge.type == ModbusBridgeType::mb_float) if (modbusBridge.type == ModbusBridgeType::mb_float)
{ {
float value = 0; float value = 0;
((uint8_t *)&value)[3] = buffer[3 + (count * 4)]; // Get float values ((uint8_t *)&value)[3] = buffer[dataOffset + (count * 4)]; // Get float values
((uint8_t *)&value)[2] = buffer[4 + (count * 4)]; ((uint8_t *)&value)[2] = buffer[dataOffset + 1 + (count * 4)];
((uint8_t *)&value)[1] = buffer[5 + (count * 4)]; ((uint8_t *)&value)[1] = buffer[dataOffset + 2 + (count * 4)];
((uint8_t *)&value)[0] = buffer[6 + (count * 4)]; ((uint8_t *)&value)[0] = buffer[dataOffset + 3 + (count * 4)];
ext_snprintf_P(svalue, sizeof(svalue), "%*_f", 10, &value); ext_snprintf_P(svalue, sizeof(svalue), "%*_f", 10, &value);
} }
else else
@ -313,10 +322,10 @@ void ModbusBridgeHandle(void)
(modbusBridge.type == ModbusBridgeType::mb_uint32)) (modbusBridge.type == ModbusBridgeType::mb_uint32))
{ {
uint32_t value = 0; uint32_t value = 0;
((uint8_t *)&value)[3] = buffer[3 + (count * 4)]; // Get int values ((uint8_t *)&value)[3] = buffer[dataOffset + (count * 4)]; // Get int values
((uint8_t *)&value)[2] = buffer[4 + (count * 4)]; ((uint8_t *)&value)[2] = buffer[dataOffset + 1 + (count * 4)];
((uint8_t *)&value)[1] = buffer[5 + (count * 4)]; ((uint8_t *)&value)[1] = buffer[dataOffset + 2 + (count * 4)];
((uint8_t *)&value)[0] = buffer[6 + (count * 4)]; ((uint8_t *)&value)[0] = buffer[dataOffset + 3 + (count * 4)];
if (modbusBridge.type == ModbusBridgeType::mb_int32) if (modbusBridge.type == ModbusBridgeType::mb_int32)
snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d", value); snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d", value);
else else
@ -326,8 +335,8 @@ void ModbusBridgeHandle(void)
(modbusBridge.type == ModbusBridgeType::mb_uint16)) (modbusBridge.type == ModbusBridgeType::mb_uint16))
{ {
uint16_t value = 0; uint16_t value = 0;
((uint8_t *)&value)[1] = buffer[3 + (count * 2)]; ((uint8_t *)&value)[1] = buffer[dataOffset + (count * 2)];
((uint8_t *)&value)[0] = buffer[4 + (count * 2)]; ((uint8_t *)&value)[0] = buffer[dataOffset + 1 + (count * 2)];
if (modbusBridge.type == ModbusBridgeType::mb_int16) if (modbusBridge.type == ModbusBridgeType::mb_int16)
snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d", value); snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d", value);
else else
@ -335,7 +344,7 @@ void ModbusBridgeHandle(void)
} }
else if (modbusBridge.type == ModbusBridgeType::mb_bit) else if (modbusBridge.type == ModbusBridgeType::mb_bit)
{ {
uint8_t value = (uint8_t)(buffer[3 + count]); uint8_t value = (uint8_t)(buffer[dataOffset + count]);
snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d%d%d%d%d%d%d%d", ((value >> 7) & 1), ((value >> 6) & 1), ((value >> 5) & 1), ((value >> 4) & 1), ((value >> 3) & 1), ((value >> 2) & 1), ((value >> 1) & 1), (value & 1)); snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%d%d%d%d%d%d%d%d", ((value >> 7) & 1), ((value >> 6) & 1), ((value >> 5) & 1), ((value >> 4) & 1), ((value >> 3) & 1), ((value >> 2) & 1), ((value >> 1) & 1), (value & 1));
} }
} }
@ -350,37 +359,14 @@ void ModbusBridgeHandle(void)
if (errorcode == ModbusBridgeError::noerror) if (errorcode == ModbusBridgeError::noerror)
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED)); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED));
} }
else if ((buffer[1] == 5) || (buffer[1] == 6)) // Write Single Register else if ((buffer[1] == 15) || (buffer[1] == 16)) // Write Multiple Registers
{ {
Response_P(PSTR("{\"" D_JSON_MODBUS_RECEIVED "\":{")); Response_P(PSTR("{\"" D_JSON_MODBUS_RECEIVED "\":{"));
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_DEVICE_ADDRESS "\":%d,"), buffer[0]); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_DEVICE_ADDRESS "\":%d,"), buffer[0]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_FUNCTION_CODE "\":%d,"), buffer[1]); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_FUNCTION_CODE "\":%d,"), buffer[1]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), buffer[2] << 8 + buffer[3]); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), (buffer[2] << 8) + buffer[3]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_LENGTH "\":%d,"), tasmotaModbus->ReceiveCount()); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_LENGTH "\":%d,"), tasmotaModbus->ReceiveCount());
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_COUNT "\":%d,"), modbusBridge.count); ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_COUNT "\":%d"), (buffer[4] << 8) + buffer[5]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_VALUES "\":["));
char svalue[MBR_MAX_VALUE_LENGTH + 1] = "";
uint16_t value = 0;
((uint8_t *)&value)[1] = buffer[2];
((uint8_t *)&value)[0] = buffer[3];
// ToDo: make uint, int float etc.
snprintf(svalue, MBR_MAX_VALUE_LENGTH, "%u", value);
ResponseAppend_P(PSTR("]}"));
ResponseJsonEnd();
if (errorcode == ModbusBridgeError::noerror)
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_MODBUS_RECEIVED));
}
else if ((buffer[1] == 15) || (buffer[1] == 16)) // Write Single Register
{
Response_P(PSTR("{\"" D_JSON_MODBUS_RECEIVED "\":{"));
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_DEVICE_ADDRESS "\":%d,"), buffer[0]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_FUNCTION_CODE "\":%d,"), buffer[1]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_START_ADDRESS "\":%d,"), buffer[2] << 8 + buffer[3]);
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_LENGTH "\":%d,"), tasmotaModbus->ReceiveCount());
ResponseAppend_P(PSTR("\"" D_JSON_MODBUS_COUNT "\":%d,"), buffer[4] << 8 + buffer[5]);
ResponseAppend_P(PSTR("}")); ResponseAppend_P(PSTR("}"));
ResponseJsonEnd(); ResponseJsonEnd();
if (errorcode == ModbusBridgeError::noerror) if (errorcode == ModbusBridgeError::noerror)
@ -623,12 +609,12 @@ void CmndModbusBridgeSend(void)
errorcode = ModbusBridgeError::wrongtype; errorcode = ModbusBridgeError::wrongtype;
break; break;
case ModbusBridgeType::mb_int32: case ModbusBridgeType::mb_int32:
// TODO writeData[jsonDataArrayPointer++] = (int16_t)(jsonDataArray[jsonDataArrayPointer].getInt(0) >> 16);
errorcode = ModbusBridgeError::wrongtype; writeData[jsonDataArrayPointer] = (uint16_t)jsonDataArray[jsonDataArrayPointer].getInt(0);
break; break;
case ModbusBridgeType::mb_uint32: case ModbusBridgeType::mb_uint32:
// TODO writeData[jsonDataArrayPointer++] = (uint16_t)(jsonDataArray[jsonDataArrayPointer].getUInt(0) >> 16);
errorcode = ModbusBridgeError::wrongtype; writeData[jsonDataArrayPointer] = (uint16_t)jsonDataArray[jsonDataArrayPointer].getUInt(0);
break; break;
case ModbusBridgeType::mb_raw: case ModbusBridgeType::mb_raw:
writeData[jsonDataArrayPointer] = (uint8_t)jsonDataArray[jsonDataArrayPointer*2].getUInt(0) << 8 + (uint8_t)jsonDataArray[(jsonDataArrayPointer*2)+1].getUInt(0); writeData[jsonDataArrayPointer] = (uint8_t)jsonDataArray[jsonDataArrayPointer*2].getUInt(0) << 8 + (uint8_t)jsonDataArray[(jsonDataArrayPointer*2)+1].getUInt(0);
@ -642,7 +628,7 @@ void CmndModbusBridgeSend(void)
// Handle errorcode and exit function when an error has occured // Handle errorcode and exit function when an error has occured
if (errorcode != ModbusBridgeError::noerror) if (errorcode != ModbusBridgeError::noerror)
{ {
AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR Send Error %d"), (uint8_t)errorcode); AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR Send Error %u"), (uint8_t)errorcode);
free(writeData); free(writeData);
return; return;
} }
@ -651,7 +637,8 @@ void CmndModbusBridgeSend(void)
if ((modbusBridge.functionCode == ModbusBridgeFunctionCode::mb_writeSingleCoil) || (modbusBridge.functionCode == ModbusBridgeFunctionCode::mb_writeSingleRegister)) if ((modbusBridge.functionCode == ModbusBridgeFunctionCode::mb_writeSingleCoil) || (modbusBridge.functionCode == ModbusBridgeFunctionCode::mb_writeSingleRegister))
modbusBridge.dataCount = 1; modbusBridge.dataCount = 1;
tasmotaModbus->Send(modbusBridge.deviceAddress, (uint8_t)modbusBridge.functionCode, modbusBridge.startAddress, modbusBridge.dataCount, writeData); uint8_t error = tasmotaModbus->Send(modbusBridge.deviceAddress, (uint8_t)modbusBridge.functionCode, modbusBridge.startAddress, modbusBridge.dataCount, writeData);
if (error) AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR Driver send error %u"), error);
free(writeData); free(writeData);
ResponseCmndDone(); ResponseCmndDone();
} }