GenericSensor_codec Scripts

GenericSensor_codec.js script

This is a sample script for handling the topic mapping and payload processing.

The script supports encode and decode functions. Encode function is for mapping the topics for the downlink request like read or write and the decode function is for processing the uplink request from the devices.

In the Encode function, the first task is to check if the request is for read or write. For write requests, a payload is sent by the application, and a topic mapping is created in the Resource. The topic you specify in the Resource will be the topic mapped in the script. Payload will be the value sent to the device and this could be a JSON (var payload = {value: impactRequest.getValue()) or a simple string (var payload = <string value to be sent to the device>).

Similarly, for a read request, the payload parameter will be the Payload sent to the device and the mapping created for the resource will be the topic name.

The decode function is used to process the uplink request. The device sends the response for a read or write request by appending a response to the topic. Payload is parsed to check whether the topic includes that response string in it and specify whether it is a write or read response. Payload is sent back to the MQTT adapter to send a notification to the callback server.

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

function GenericSensorCodec() {
	
	const MANUFACTURER = 'device/0/manufacturer';
	const MODEL = 'device/0/model';
	const FIRMWARE_VERSION = 'device/0/firmwareVersion';
	const TEMPERATURE = 'sensor/0/temperature';
    
    this.encode = function (impactRequest) {
        console.log(impactRequest, typeof(impactRequest), impactRequest.toString());
      var requestType = utils.getRequestType(impactRequest);
      console.log('request type is ' + requestType);
      switch(requestType) {
          case "WRITE":
          	var payload = {value: impactRequest.getValue(),	correlatorId: impactRequest.getCorrelatorId(), type: 'write'};
			var response = {resource: 'devices/'+impactRequest.getSerialNumber()+"/"+TEMPERATURE, payload: JSON.stringify(payload)};
		return constructImpactWriteRequest(response);
          case "READ":
          	var payload = {correlatorId: impactRequest.getCorrelatorId(), type: 'read'};
			var response = {resource: 'devices/'+impactRequest.getSerialNumber()+"/"+TEMPERATURE, payload: JSON.stringify(payload)};
		return constructImpactWriteRequest(response);
          default:
			throw "invalid request type provided";
      }
    }

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

        var request = bytes2String(bytes);
        console.log("input to WriteRequestCodec decoder", request);
		var json = JSON.parse(request);
		if(json.topic.includes("response")){
          var payload = JSON.parse(json.payload);
          console.log('response type is ' + payload.type);
			var res = {};
          if(payload.type == "write"){	
            	res[payload.topic] = payload.value;
				var writeResponse = {type: 'WRITE_RESPONSE', resources: res, correlatorid: payload.correlatorId, status: 200};
				return formImpactNotifyFromJson(decodeCtx, writeResponse);
          } else if(payload.type == "read"){
          		res[payload.topic] = payload.value;


            	var readResponse = {type: 'READ_RESPONSE', resources: res, correlatorid: payload.correlatorId, status: 200};
            	return formImpactNotifyFromJson(decodeCtx, readResponse);
          }
		}		
		var resources = {};
		if (json.topic.includes("temperature")) {
			console.log("mapping topic to: "+ TEMPERATURE);
            resources[TEMPERATURE] = json.payload;
        }else {
			resources = constructResourceMapping(json);
		}		
		var notifyResponse = {type: 'NOTIFY', resources: resources};

        return formImpactNotifyFromJson(decodeCtx, notifyResponse);
    }
	
	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;
        }

        if (payload.temperature) {
            response[TEMPERATURE] = payload.temperature;
        }
        return response;
    }

}

var codec = new GenericSensorCodec();

(codec);

GenericSensorUtils.js script

To avoid complexity, scripts are separated into core codec functions and helper/utility functions as two separate script files. When a codec function script is executed, the associated utility script is preloaded. Below is an example of utility script.

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

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 ascii2bytes(val) {
	var respArr = new Int8Array(val.length);
	for(var i = 0; i < val.length; i++) {
		respArr[i] = val.charCodeAt(i);
	}
	return respArr;
}

function constructImpactWriteRequest(resp) {
    var response = JSON.stringify(resp);
    console.log('sending write request ' + response);
    return utils.createMqttEncodeResponse(response);
}

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