Downlink using Codec - Encode

Hello All,

I am trying to schedule a downlink to NKE Intenso device to configure thresholds and report alarm. I developed a Javascript Encoder that takes Fport and obj and returns a decimal array.
You can find the Javascript codec here
function hex_to_dec_array(hexString) {
var hexArray = new Array();
var decArray = new Array();
var newString = new String();
var lengthHexString = hexString.length;
for (var i = 0; i < lengthHexString; i++) {
if (i % 2 == 1) {
var newString = hexString.charAt(i - 1) + hexString.charAt(i)
hexArray.push(“0x” + newString);
}
}
var lengthHexArray = hexArray.length;
for (var i = 0; i < lengthHexArray; i++) {
decArray.push(parseInt(hexArray[i]));
}
return decArray;
}
//Function to convert a floating point number to hexadecimal number//
function Float2Hex(a){
const getHex = i => (‘00’ + i.toString(16)).slice(-2);
var view = new DataView(new ArrayBuffer(4)),
result;
view.setFloat32(0, a);
result = Array
.apply(null, { length: 4 })
.map((_, i) => getHex(view.getUint8(i)))
.join(’’);
return result
}

//
function Encode(fPort, obj) {
//obj = JSON.parse(obj);
// console.log("JSON parsed OBJ is "+obj);
var count = Object.keys(obj).length;
//console.log("length is "+ count);
//choose between Threshold and reportable change payload//
if (count == 3){
obj.defaultDownlink_Delta = “3106000c00005539”;
var Min_Value_Decimal = obj.Min_interval;
//console.log(Min_Value_Decimal);
var Min_Value_Dec2Int = parseInt(Min_Value_Decimal);
var Min_Value_Hex = Min_Value_Dec2Int.toString(16);
//console.log("Min value in decimal " + Min_Value_Decimal);
//console.log("Min value in HEX decimal " + Min_Value_Hex);
//Convert the Min_Value_Hex to NKE Watteco Min_interval in minutes//
var minutes = “8”;
var Min_length = Min_Value_Hex.length;
if (Min_length < 3){
var Shift_min = 3 - Min_length;
//console.log("shift cells in Min time are "+ Shift_min);
for (let i = Shift_min ; i > 0; i–) {
Min_Value_Hex = “0”+Min_Value_Hex;
}
Min_Value_Hex= “8”+ Min_Value_Hex;
}
var Max_Value_Decimal = obj.Max_interval;
var Max_Value_Dec2Int = parseInt(Max_Value_Decimal);
var Max_Value_Hex = Max_Value_Dec2Int.toString(16);
//console.log("Max value in decimal " + Max_Value_Decimal);
//console.log("Max value in HEX decimal " + Max_Value_Hex);
var Max_length = Max_Value_Hex.length;
if (Max_length < 3){
var Shift_max = 3 - Max_length;
//console.log("shift cells in Min time are "+ Shift_max);
for (let i = Shift_max ; i > 0; i–) {
Max_Value_Hex = “0”+ Max_Value_Hex;
}
Max_Value_Hex= “8”+ Max_Value_Hex;
}

//convert the reportable change to Hexadecimal//
var Delta = Float2Hex(obj.Reportable_change);
//console.log("Reportable change is " + Delta);
var downlink = “”;
downlink = obj.defaultDownlink_Delta + Min_Value_Hex + Max_Value_Hex + Delta;
console.log("downlink is " + downlink);
downlink = hex_to_dec_array(downlink);
return downlink;

}
else if(count == 6){

obj.defaultDownlink_Threshold = “3106000cd8005539”;
// convert the time entered by user in to hexdecimal value//
//console.log(obj);
//Min value from JSON - Convert String to Int and convert Int to Hexdecimal//
Min_Value_Decimal = obj.Min_interval;
//console.log(Min_Value_Decimal);
Min_Value_Dec2Int = parseInt(Min_Value_Decimal);
Min_Value_Hex = Min_Value_Dec2Int.toString(16);
//console.log("Min value in decimal " + Min_Value_Decimal);
//console.log("Min value in HEX decimal " + Min_Value_Hex);
//Convert the Min_Value_Hex to NKE Watteco Min_interval in minutes//
minutes = “8”;
Min_length = Min_Value_Hex.length;
if (Min_length < 3){
Shift_min = 3 - Min_length;
//console.log("shift cells in Min time are "+ Shift_min);
for (let i = Shift_min ; i > 0; i–) {
Min_Value_Hex = “0”+Min_Value_Hex;
}
Min_Value_Hex= “8”+ Min_Value_Hex;
}
//console.log("min interval is " + Min_Value_Hex);
//console.log("min_value length is "+Min_length);
//Convert the Max_Value_Hex to NKE Watteco Max_interval in minutes//

//Max value from JSON - Convert String to Int and convert Int to Hexdecimal//
Max_Value_Decimal = obj.Max_interval;
Max_Value_Dec2Int = parseInt(Max_Value_Decimal);
Max_Value_Hex = Max_Value_Dec2Int.toString(16);
//console.log("Max value in decimal " + Max_Value_Decimal);
//console.log("Max value in HEX decimal " + Max_Value_Hex);
Max_length = Max_Value_Hex.length;
if (Max_length < 3){
Shift_max = 3 - Max_length;
//console.log("shift cells in Min time are "+ Shift_max);
for (let i = Shift_max ; i > 0; i–) {
Max_Value_Hex = “0”+Max_Value_Hex;
}
Max_Value_Hex= “8”+ Max_Value_Hex;
}
//console.log("max interval is " + Max_Value_Hex);
//console.log("max_value length is "+Max_length);

//Convert Upper Threshold value from Float to hexadecimal. Because the current value (amps) can be declared in floating values//
var Upper_Threshold_Identifier = “d1”;
var Upper_Threshold = Float2Hex(obj.Upper_Threshold);
var Upper_Hysterisis = Float2Hex(obj.Hysterisis_UpperThreshold);
var Upper_Threshold_downlink = Upper_Threshold_Identifier + Upper_Threshold + Upper_Hysterisis;

//Convert Lower Threshold value from Float to hexadecimal. Because the current value (amps) can be declared in floating values//
var Lower_Threshold_Identifier = “b0”;
var Lower_Threshold = Float2Hex(obj.Lower_Threshold);
var Lower_Hysterisis = Float2Hex(obj.Hysterisis_LowerThreshold);
var Lower_Threshold_downlink = Lower_Threshold_Identifier + Lower_Threshold + Lower_Hysterisis;
//console.log("Upper Threshold value is "+Lower_Threshold_downlink);
var Occurance = “01”;
var downlink = “”;
downlink = obj.defaultDownlink_Threshold + Min_Value_Hex + Max_Value_Hex + Upper_Threshold_downlink + Lower_Threshold_downlink + Occurance;
downlink = downlink.toUpperCase();
console.log("downlink is " + downlink);
downlink = hex_to_dec_array(downlink);
return downlink
}
}

Unfortunately I could not successfully forward a downlink using the JSON Object = {“Min_interval”:“000”,“Max_interval”:“005”,"Reportable_change:“2”}

I receive “Undefined:code(undefined)” error while trying to send from End-device UI.
I receive error 502 BAD GAteway while try from Chirpstack API using
{
“deviceQueueItem”: {
“confirmed”: true,
“devEUI”: “************”,
“fPort”: 125,
“data”: “”,
“jsonObject”: “{“Min_interval”:“000”,“Max_interval”:“005”,“Reportable_change”:“2”}”
}

Can some one let me know in which format do we need to return downlink from Codec? and do we need to parse the JSON object while using external API?

Best regards,
Chay

If you enqueue a downlink with a JSON object, then this object will be used as input by the encoder function. This encoder function must return an array of bytes.

hi @brocaar, I am currently using ** {“Min_interval”:“10”,“Max_interval”:“20”, “Upper_Threshold”:“4.0”, “Hysterisis_UpperThreshold”:“0.5”, “Lower_Threshold”:“2”, “Hysterisis_LowerThreshold”:“0.5”}** as input(obj) to encoder and Encoder returns
Decimal array [49,6,0,12,216,0,85,57,128,10,128,20,209,64,128,0,0,63,0,0,0,176,64,0,0,0,63,0,0,0,1] for the hexadecimal downlink : 3106000CD8005539800A8014D1408000003F000000B0400000003F00000001.
on Javascript editor(Codepen)

Where as after uploading the Encoder to Device profile, I receive an error on UI “undefined:Code undefined”.

Which data type should the Encoder return, is Decimal array or Hexadecimal array or Base64 array?

Hello all,
I found the root cause of issue, it is due to ES5 and ES6 Javascript compatability issue. Every time after developing an endoder/decoder runit with Otto engine and check for compatability issues with Chirpstack.
BR,
Chay

1 Like