Handling complex json

MQTT script engine supports complex JSON payload where there are multiple compound levels. MQTT device can send multiple resources in a single payload.

When the device publish a complex JSON format payload which has multiple level of resources, the script will decode the payload which comes from the device. Notifications will be sent for all those resources for which the client application has subscribed to in a single notification.

For sample payload, see Sample payload.

For sample script, see Codec scripts.

Sample payload

{
   "s":"urn:lo:nsid:1114_TEST_BE:123456789011121",
   "ts":"2018-01-01T12:01:20.0Z",
   "m":"init_model",
   "loc":[
      "47.2113",
      "-0.06054"
   ],
   "v":{
      "temperature":{
         "value":"26",
         "unit":"degC"
      },
      "battery":{
         "value":"3.99",
         "unit":"V",
         "remaining":"0"
      },
      "gps":{
         "validPosition":"1",
         "speed":{
            "value":"0.0",
            "unit":"Kmh"
         },
         "onMove":"17"
      },
      "network":{
         "rsrp":"10",
         "rsrq":"12"
      }
   },
   "t":[
      "Ercogener",
      "Saumur"
   ]
}

Codec scripts

ercogener_codec script

var utils = Java.type('com.nokia.adapter.transformation.utils.TranformerUtil');

function ErcogenerCodec() {
	
	const TEMPERATURE_VALUE = 'temperature/0/value';
	const TEMPERATURE_UNIT = 'temperature/0/unit';
	const BATTERY_VALUE = 'battery/0/value';
	const BATTERY_UNIT = 'battery/0/unit';
	const BATTERY_REMAINING = 'battery/0/remaining';
	const GPS_VALID_POSITION = 'GPS/0/validPosition';
	const GPS_ON_MOVE = 'GPS/0/onMove';
	const GPS_VALUE = 'GPS/0/value';
	const GPS_UNIT = 'GPS/0/unit';
	const NETWORK_RSRP = 'Network/0/rsrp';
	const NETWORK_RSRQ = 'Network/0/rsrq';
	const TOPICS_T_0 = 'topics/0/t/0';
	const TOPICS_T_1 = 'topics/0/t/1';
	const MANUFACTURER = 'device/0/manufacturer';
	const MODEL = 'device/0/model';
	const FIRMWARE_VERSION = 'device/0/firmwareVersion';
    
    this.encode = function (impactRequest) {
        console.log(impactRequest, typeof(impactRequest), impactRequest.toString());
        throw new Error('downlink encoding not implemeted');
    }

    this.decode = function (decodeCtx) {
		var bytes = decodeCtx.getUplinkMessage();

        var request = bytes2String(bytes);
        console.log("input to decoder", request);
		
		var json = JSON.parse(request);
		var payload = JSON.parse(json.payload);
		var vitals = payload.v;
		var resources = {};
		if(payload.v){
			
			console.log("***** Inside vitals********");
			
		if(vitals.temperature){
			resources[TEMPERATURE_VALUE] = vitals.temperature.value;
			resources[TEMPERATURE_UNIT] = vitals.temperature.unit;
		}
		if(vitals.battery){
			resources[BATTERY_VALUE] = vitals.battery.value;
			resources[BATTERY_UNIT] = vitals.battery.unit;
			resources[BATTERY_REMAINING] = vitals.battery.remaining;
		}
		if(vitals.gps){
			resources[GPS_VALID_POSITION] = vitals.gps.validPosition;
			resources[GPS_ON_MOVE] = vitals.gps.onMove;
			resources[GPS_VALUE] = vitals.gps.speed.value;
			resources[GPS_UNIT] = vitals.gps.speed.unit;
		}
		if(vitals.network){
			resources[NETWORK_RSRP] = vitals.network.rsrp;
			resources[NETWORK_RSRQ] = vitals.network.rsrq;
		}
		
		resources[TOPICS_T_0] = payload.t[0];
		resources[TOPICS_T_1] = payload.t[1];
		var notifyResponse = {type: 'NOTIFY', resources: resources};

        return formImpactNotifyFromJson(decodeCtx, notifyResponse);
		}
		else {
			console.log("***** Inside registration request********");
			var regResources = constructResourceMapping(json);
			var regResponse = {type: 'NOTIFY', resources: regResources};

        return formImpactNotifyFromJson(decodeCtx, regResponse);
		}	
		
    }
	
	function constructResourceMapping(json) {
	
        var payload = JSON.parse(json.payload);
		console.log("Resource mapping--- ", payload);
		console.log("Manufacturer mapping--- ", payload.manufacturer);
        var response = {};
        if (payload.manufacturer) {
            response[MANUFACTURER] = payload.manufacturer;
        }

        if (payload.model) {
            response[MODEL] = payload.model;
        }

        if (payload.firmwareVersion) {
            response[FIRMWARE_VERSION] = payload.firmwareVersion;
        }
        return response;
    }

}

var codec = new ErcogenerCodec();

(codec);

ercogener_utils.js script

var utils = Java.type('com.nokia.adapter.transformation.utils.TranformerUtil');

// utility functions
function bytes2String(bytes, offset=0) {
    if (offset < 0) { 
		offset = 0; 
	}
    var result = "";
    for (var i = offset; i < bytes.length; i++) {
        result += String.fromCharCode(bytes[i]);
    }
    return result;
}

function formImpactNotifyFromJson(decodeCtx, resources) {    
    console.log('sending notify response ' + JSON.stringify(resources));
    return utils.createMqttDecodeResponse(JSON.stringify(resources));
}