thingsboard / thingsboard-gateway

Open-source IoT Gateway - integrates devices connected to legacy and third-party systems with ThingsBoard IoT Platform using Modbus, CAN bus, BACnet, BLE, OPC-UA, MQTT, ODBC and REST protocols
https://thingsboard.io/docs/iot-gateway/what-is-iot-gateway/
Apache License 2.0
1.75k stars 845 forks source link

[BUG] Modbus: Reading bytes some times returns integer instead of string #591

Closed santiago-ruiz closed 3 years ago

santiago-ruiz commented 3 years ago

Describe the bug: I'm using Thingsboard-Gateway to read values from a Modbus device and send it to Thingsboard Cloud. Everything works fine but sometimes I receive a strange value. After looking in the receiving messages by the Rule Chain in the Cloud, I found that when reading values with the type bytes if the hexa value doesn't contain a character (a-f), the value in the JSON message is sent as a big integer. Example: I'm reading five Modbus registers at once. If the value of the register are [20,360,600,20,200] (in decimal) I receive:

{
    "value1": "1401680258001400c8"
}

That it's correct. BUT if the values are [20,360,600,20,20] (in decimal) I receive:

{
    "value1": 140168025800140014
}

This is a big problem for processing the data in the nodes. I've been trying to use .toString() to fix it, but for large values (like the one in the example) Javascript doesn't work (msg.values1.toString() returns "140168025800140020" in the second case)

Connector name: [Modbus TCP connector]

Configuration (modbus.json):

...
  {
    "tag": "value1",
    "type": "bytes",
    "functionCode": 4,
    "objectsCount": 5,
    "address": 1014
  }
...

Versions:

imbeacon commented 3 years ago

Hi @santiago-ruiz,

This issue is not related to the gateway. It sends data to ThingsBoard in the correct data format, but on cloud in configuration type_cast_enabled parameter is enabled, so it tries to convert data to number if it is possible. Possible workarounds are:

  1. Manual converting in rule chain transformation script rule node for example using the following function:

    
    longToByteArray = function(/*long*/long) {
    // we want to represent the input as a 8-bytes array
    var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
    
    for ( var index = 0; index < byteArray.length; index ++ ) {
        var byte = long & 0xff;
        byteArray [ index ] = byte;
        long = (long - byte) / 256 ;
    }
    
    return byteArray;
    };

2. Read data with a...f values (add one more register just for this purpose).