Skip to main content
Version: v5.1

Normalization script

Create a normalization script to take raw IoT data and output the data in the data structure for readings on the platform.

Output data structure​

Your normalization script must transform the raw IoT data to the following format:

{​
"readings": [​
{​
// IoT reading data goes here​
"_ts": "",​
"_tsMetadata": {​
"_sourceId": ""​
}​
}​
]​
}
PropertyTypeDescriptionRequired
"readings"Array of ObjectsContains an array of reading objects, which also contain a timestamp and metadata.Required
"_ts"StringA timestamp you createRequired
"_tsMetadata"ObjectCreate an object that contains a "_sourceId" property.Required
"_sourceId"StringContains the source id of the sensor that takes the reading.Required

Input and output data examples​

Raw IoT input data​

{
"type": "text",
"messageId": "ID:activemq-39563-1689584032552-5:4:-1:1:1",
"correlationId": null,
"destination": {
"type": "queue",
"name": "Consumer.<ANY_STRING>.VirtualTopic.lnt_RfmbfrED"
},
"replyTo": null,
"priority": 4,
"expiration": 0,
"timestamp": 1689584797284,
"redelivered": false,
"properties": {
"ActiveMQ.MQTT.QoS": {
"type": "integer",
"boolean": null,
"byte": null,
"short": null,
"integer": 0,
"long": null,
"float": null,
"double": null,
"string": null
}
},
"payloadText": "{\"from\":\"BLE\",\"mac\":\"30:ae:7b:e1:f5:28\",\"to\":\"GATEWAY\",\"time\":1689584797,\"deviceCode\":\"01012354-ad7d-4a0a-91db-a08435b7c9e3\", \"type\":\"reportAttribute\",\"data\":{\"value\":{\"device_list\":[{\"data\":\"0201061AFF5B07050305730073005E27D80085018E04AA023A079B0C000011079ECADC240EE5A9E093F3A3B50100406E09094869626F75414952\",\"modelstr\":\"HibouAIRe\",\"scan_rssi\":-51,\"Board_id\":\"5d9f693f-6f95-4ea5-a610-5fe7bf061f40\",\"ble_addr\":\"E8:E5:ED:BE:5E:D9\",\"addr_type\":1,\"scan_time\":1684043612,\"CO2\":0,\"HibouType\":\"PM\",\"dev_name\":\"HibouAIR\",\"ALS\":115,\"PM1.0\":\"68.200\",\"PM2.5\":\"185.000\",\"Pressure\":\"1007.800\",\"PM10\":\"322.700\",\"Temperature\":\"21.600\",\"Humidity\":\"38.900\",\"VOC\":1166,\"connectable\":1}]},\"attribute\":\"mod.device_list\",\"mac\":\"30:ae:7b:e1:f5:28\"},\"count\":1,\"name\":\"kafka-telemetry-1_sXrwGTdXah_timeseries\",\"id\":\"1-1\",\"csv\":\"execution7.csv\"}"
}

Normalized data output​

{
"readings": [
{
"data": "0201061AFF5B07050305730073005E27D80085018E04AA023A079B0C000011079ECADC240EE5A9E093F3A3B50100406E09094869626F75414952",
"modelstr": "HibouAIRe",
"scan_rssi": -51,
"Board_id": "5d9f693f-6f95-4ea5-a610-5fe7bf061f40",
"ble_addr": "E8:E5:ED:BE:5E:D9",
"addr_type": 1,
"scan_time": 1684043612,
"CO2": 0,
"HibouType": "PM",
"dev_name": "HibouAIR",
"ALS": 115,
"PM1.0": "68.200",
"PM2.5": "185.000",
"Pressure": "1007.800",
"PM10": "322.700",
"Temperature": "21.600",
"Humidity": "38.900",
"VOC": 1166,
"connectable": 1,
"_ts": "2023-05-14T05:53:32.000Z",
"_tsMetadata": {
"_sourceId": "5d9f693f-6f95-4ea5-a610-5fe7bf061f40"
}
}
]
}

Creating a normalization script​

The following procedure creates the script that transforms the raw IoT input data to the normalized output in the previous example:

Important: Only use the var keyword to create variables, do not use const or let.

Important: Do not use console logging functions in your script.

Note: You can use arrow functions.

To skip to the final script, see Script example.

  1. Create a functions object to contain your constructReadings and normalize methods.

    var functions = {

    }
  2. In the functions object, create a normalize method that takes a string message as its parameter.

    ...
    normalize: function(strMessage) {​

    }​
  3. In the normalize method, parse the string message parameter.

    ...
    var message = JSON.parse(strMessage);​
    var payloadText = message.payloadText;​
    var payload = JSON.parse(payloadText);​
    var data = payload.data.value.device_list;
  4. Create a readings array to push normalized readings to.

    ...
    var readings = [];​
  5. Construct a readings object for each device using a constructReadings method you define later, then push the object to the readings array.

    ...
    data.forEach(d => {
    var readingsObj = {...d, ...this.constructReadings(d.Board_id, d.scan_time)};
    readings.push(readingsObj)
    });
  6. Declare a constructReadings method that takes the reading's source id and timestamp as parameters.

    ...
    constructReadings: (sourceId, ts) => {

    }
  7. In the constructReadings method, create a new Date object based on the timestamp parameter multiplied by 1000.

    ...
    var date = new Date(ts*1000);

  8. In the constructReadings function, construct a readings object with "_ts", "_tsMetadata", and "_tsMetadata._sourceId" properties, then return that object.

    ...
    var readingsObj = {
    "_ts": date.toISOString(),
    "_tsMetadata":{
    "_sourceId":sourceId
    }
    };
    return readingsObj;

Script example​


var functions = {
normalize: function(strMessage){
var message = JSON.parse(strMessage);
var payloadText=message.payloadText;
var payload = JSON.parse(payloadText);
if (typeof payload === 'string') {
payload = JSON.parse(payload);
}
var data = payload.data.value.device_list;


var readings = [];

data.forEach(d => {
var readingsObj = {...d, ...this.constructReadings(d.Board_id, d.scan_time)};
readings.push(readingsObj)
});

var result = {readings};
return JSON.stringify(result);
},
constructReadings: (sourceId, ts) => {
var date = new Date(ts*1000);
var readingsObj = {
"_ts": date.toISOString(),
"_tsMetadata":{
"_sourceId":sourceId
}
};
return readingsObj;
}
}

Normalization script invocation​


let s = {"type":"text","messageId":"ID:activemq-39563-1689584032552-5:4:-1:1:1","correlationId":null,"destination":{"type":"queue","name":"Consumer.<ANY_STRING>.VirtualTopic.lnt_RfmbfrED"},"replyTo":null,"priority":4,"expiration":0,"timestamp":1689584797284,"redelivered":false,"properties":{"ActiveMQ.MQTT.QoS":{"type":"integer","boolean":null,"byte":null,"short":null,"integer":0,"long":null,"float":null,"double":null,"string":null}},"payloadText":"{\"from\":\"BLE\",\"mac\":\"30:ae:7b:e1:f5:28\",\"to\":\"GATEWAY\",\"time\":1689584797,\"deviceCode\":\"01012354-ad7d-4a0a-91db-a08435b7c9e3\",\"type\":\"reportAttribute\",\"data\":{\"value\":{\"device_list\":[{\"data\":\"0201061AFF5B07050305730073005E27D80085018E04AA023A079B0C000011079ECADC240EE5A9E093F3A3B50100406E09094869626F75414952\",\"modelstr\":\"HibouAIRe\",\"scan_rssi\":-51,\"Board_id\":\"5d9f693f-6f95-4ea5-a610-5fe7bf061f40\",\"ble_addr\":\"E8:E5:ED:BE:5E:D9\",\"addr_type\":1,\"scan_time\":1684043612,\"CO2\":0,\"HibouType\":\"PM\",\"dev_name\":\"HibouAIR\",\"ALS\":115,\"PM1.0\":\"68.200\",\"PM2.5\":\"185.000\",\"Pressure\":\"1007.800\",\"PM10\":\"322.700\",\"Temperature\":\"21.600\",\"Humidity\":\"38.900\",\"VOC\":1166,\"connectable\":1}]},\"attribute\":\"mod.device_list\",\"mac\":\"30:ae:7b:e1:f5:28\"},\"count\":1,\"name\":\"kafka-telemetry-1_sXrwGTdXah_timeseries\",\"id\":\"1-1\",\"csv\":\"execution7.csv\"}","payloadMap":null,"payloadBytes":null};

let res = functions.normalize(JSON.stringify(s));
console.log(res);