- 16 Feb 2022
- 11 Minutes to read
- Print
- PDF
Examples
- Updated on 16 Feb 2022
- 11 Minutes to read
- Print
- PDF
Parsing a JSON message
In this example, a subscriber received a message serialized in JSON, which then needed be parsed into a tag event collection, and the data saved to tags. In the below example, the following JSON message is used (this message represents weather data from a given location):
{
"ts": "2020-04-15T09:00:00.000Z",
"data": {
"Temperature": {
"value": 21.3,
"unit": "ºC"
},
"Humidity": {
"value": 31.1,
"unit": "%"
},
"Wind speed": {
"value": 2.3,
"unit": "m/s"
}
}
}
- Create both the connection and the subscriber that will be receiving the events. The encoding and compression must both match the settings on the publisher side. For example, if a publisher sends data compressed in GZip in base64 format, it must be decoded from base64 and uncompressed. In the below example, the following settings are used: Figure 28. JSON example subscriber settings
- Next, the parser script must be written. More information about the different utilities permitted for scripts can be found here. In order to correctly parse the message, the following script will be used:
$.logger.info("Parsing message: %j", $.input); var ts = Date.parse($.input.ts); $.logger.debug("Timestamp: %d", ts); for (var tag in $.input.data){ var ev = { tag: tag, value: $.input.data[tag].value, quality: 192, ts: ts }; $.logger.trace("Event: %j", ev); $.output.push(ev) }
- Once the script is finished, the tags for storing the saved data must be created. As scripts use the key values of each data point as the tag name, each tag alias should be named according to the corresponding name in the message. The below screenshot shows the configuration settings: Figure 29. JSON example tag settings
- If configuration is correct, the next time a packet arrives with a message, the tags will automatically be updated. See below screenshot for an example:
Figure 30. JSON example tag data
Parsing a Protocol Buffers message
This example shows how to parse a message encoded in protobuf format and then extract tag data from the message. The following .proto file will be used for this example:
syntax = "proto3";
import "google/protobuf/timestamp.proto";
message Message{
repeated TagEvent events = 1;
}
message TagEvent{
string tag = 1;
oneof valueType{
int32 Integer = 2;
double Double = 3;
string String = 4;
int64 Long = 5;
}
uint32 quality = 6;
google.protobuf.Timestamp googleTs = 7;
}
The next snippet shows the message used in this example. A message encoded with Protocol Buffer will be in binary format, however, the below example is shown in JSON format for clarity.
[{
"tag": "STATE",
"Integer": 5,
"quality": 192,
"ts": {
"seconds": 15869597100,
"nanos": 0
}
}, {
"tag": "P_GEN",
"Double": 7367.66,
"quality": 192,
"ts": {
"seconds": 15869597100,
"nanos": 0
}
}, {
"tag": "DATE",
"String": "Wed Apr 15 2020 16:08:30 GMT+0200 (Central European Summer Time)",
"quality": 192,
"ts": {
"seconds": 15869597100,
"nanos": 0
}
}, {
"tag": "ACTIVE_POWER",
"Long": 316677879202,
"quality": 192,
"ts": {
"seconds": 15869597100,
"nanos": 0
}
}]
- The first step is to create a new MqttClient connection and a subscriber to receive messages on a specified topic. Since protobuf is a binary format, encoding must be set to binary (unless the publisher is using a different encoding) and compression must match the data publisher. The following screenshot shows the configuration settings used in this example: Figure 31. Protobuf example subscriber configuration
- Next, the parsing script needs to be written. Since the serialization settings are set to Protocol Buffers, data will automatically be converted to a JavaScript object. This example uses both oneof, googleTimestamp and int64 fields, which are special cases for protobuf messages.
- oneof: When present, this field will show a string to indicate which of the oneof fields is being used.
- googleTimestamp: This is a timestamp format used by Google in protobuf messages. It’s similar to the C timespec format, as it uses one field for seconds, and another field for nanoseconds.
- int64/uint64: Since JavaScript numbers are Double, conversion from int64 and uint64 could result in a loss of precision. As such, these values are encoded as a Long object containing high, low, and sign fields, as well as a .toNumber() method in order to convert the result into a JavaScript Number.
var events = $.input.events;
$.logger.info("Parsing message: %j", events);
for(var i = 0; i<events.length; ++i){
var event = {
tag: events[i].tag,
quality: events[i].quality,
ts: googleTsToEpoch(events[i].ts)
};
switch(events[i].valueType){
case "Integer":
event.value = events[i].Integer;
break;
case "Double":
event.value = events[i].Double;
break;
case "String":
event.value = events[i].String;
break;
case "Long":
event.value = events[i].Long.toNumber();
break;
}
$.logger.trace("Tag event: %j", event);
$.output.push(event);
}
//Converts from google ts to epoch
function googleTsToEpoch(googleTs){
return googleTs.seconds.toNumber() * 1000 + googleTs.nanos / 1000000;
}
3. Once the script has finished, all necessary tags must be created. Since the script uses the tag name from the message as the tag path, each tag must have an alias that points to the tag name used in the message. See below screenshot for the configuration settings for one of the tags used in this example:
Figure 32. Protobuf example tag configuration
Figure 33. Protobuf example tag data
Parsing a custom format
In this example, a message with a custom format (neither JSON nor protobuf) will be parsed. This example will use the following message format:
TAGNAME|VALUE|QUALITY|TS\r\n
An example message using this custom format is shown in the following code snippet:
Product_Count|3412|192|1586938995000\r\n
Remaining|1588|192|1586938995000\r\n
Uptime|441235|192|1586938980000\r\n
- First, an MqttConnection must be created and its settings should be applied according to the desired message. Since this message uses a completely custom deserializer and parser, the serializer must be set to “None” in order to pass the raw message directly to the parser. The configuration settings will be as follows: Figure 34. Custom format subscriber example
- After configuration is complete, the parsing script must be prepared. In this example, as there is no deserializer, the input data will be the raw Buffer received from the broker. More information about Buffers can be found at Node.js Buffer. The code used in this example is as follows:
var message = $.input.toString(); $.logger.info("Parsing message: %j", message); var events = message.split("\r\n"); for (var i = 0; i<events.length; ++i){ //Skip empty lines if(events[i] === "") continue; var event = events[i].split("|"); var ev = { tag: event[0], value: Number(event[1]), quality: Number(event[2]), ts: Number(event[3]) }; $.logger.trace("Event: %j", ev); $.output.push(ev) }
- Finally, the tags must be created and the tag alias for each tag must be set to the same name as the tag in the message. This is required in order to match the tag name in the message to the tag in the tag model. See below screenshot for an example of the configuration settings for these tags: Figure 35. Custom format tag configuration
- If configuration is correct, tags will automatically update the next time a message is received on the topic of the subscriber. See an example in the below screenshot:
Figure 36. Custom format tag configuration