Cumulocity IoT Tips and Tricks - Getting non-standard Modbus structures translated with Cumulocity

There are many ways that PLC designers help themselves to transfer data structures over the limitations of fieldbus protocols like Modbus. While Cloud Fieldbus covers the most common ones, such as bit fields and enumeration types, it cannot model all thinkable encodings on top of 16 Bits. However, you can use real-time event processing to calculate the encodings: Collect all required registers and coils in your device database model, then use an event processing statement to calculate the decoded data on top of the registers and coils.

Here is an example of how to convert IEEE floating point numbers modelled on top of a pair of Modbus registers. Assume that you collect two Modbus registersĀ  as measurements of type "raw" and series "Temperature0" and "Temperature1". These two 16 Bit registers contain a floating point temperature value.

This is the event processing statement to create a new temperature value from the raw data:

insert into CreateMeasurement
select
  m.measurement.source as source,
  current_timestamp().toDate() as time,
  "my_decodedValues" as type,
  {
    "c8y_Temperature.T.value",
      decodeIEEE754Value(
        getNumber(m, "raw.Temperature0.value"),
        getNumber(m, "raw.Temperature1.value"), 2),
    "c8y_Temperature.T.unit", "Ā°C"
  } as fragments
from MeasurementCreated m
where getObject(m, "raw") is not null;

Note that it used a function "decodeIEEE754Value()", which we have not defined yet. This is a JavaScript function that converts the raw data to a float value:

create expression float decodeIEEE754Value(part2, part1, precision) [
  var decm = part2 * Math.pow(16, 4) + part1;
  var sgn = decm / Math.pow(2,31);
  if(sgn >= 1) {
    sgn = -1;
  } else {
    sgn = 1;
  }
  decm = decm % Math.pow(2,31); 
  var exponent = Math.floor(decm / Math.pow(2,23));
  exponent = exponent - 127;
  var mantissa = decm % Math.pow(2,23);
  mantissa = mantissa / Math.pow(2,23);
  var result = sgn * Math.pow(2, exponent) * (1 + mantissa);
  parseFloat(result.toFixed(precision))
];