Where is the Mdot-box data (temp, press,light,etc... )?

Hello, it is my first post:
I have installed Loraserver system, and I have connected the MDOT-BOX with MUlTECH conduit (forward mode) with LoraServer system (lora-gateway, lora-app-server,loraServer).

I have also connected mosquitto topic with the command: “mosquitto_sub -v -t “application/3/node/008000000000XXXX/rx” -v -u someuser -P somepassword”.
This command provides the following information:

“application/3/node/008000000000db13/rx {“applicationID”:“3",“applicationName”:“Lantia_App”,“deviceName”:“MDOT-BOX”,“devEUI”:“008000000000db13",“rxInfo”:[{“mac”:“00800000a000060e”,“rssi”:-24,“loRaSNR”:11.8,“name”:“00800000a000060e”,“latitude”:0,“longitude”:0,“altitude”:0}],“txInfo”:{“frequency”:868300000,“dataRate”:{“modulation”:“LORA”,“bandwidth”:125,“spreadFactor”:12},“adr”:false,“codeRate”:“4/5"},“fCnt”:206,“fPort”:1,“data”:“Dgb/DggGTPEFA24LAZ0=“}”

For each JSON generated by Mosquitto, I have decripted it with Lora-packet and got this:


decoding from Base64: Dgb/DggGTPEFA24LAZ0=
Decoded packet

      Message Type = Join Request
        PHYPayload = 0E06FF0E08064CF105036E0B019D

    ( PHYPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] | MIC[4] )
            AppEUI = 05F14C06080EFF06
            DevEUI = 9D010B6E03
          DevNonce =
               MIC = 6E0B019D

application/3/node/008000000000db13/rx {“applicationID”:“3”,“applicationName”:“Lantia_App”,“deviceName”:“MDOT-BOX”,“devEUI”:“008000000000db13”,“rxInfo”:[{“mac”:“00800000a000060e”,“rssi”:-24,“loRaSNR”:8.8,“name”:“00800000a000060e”,“latitude”:0,“longitude”:0,“altitude”:0}],“txInfo”:{“frequency”:868500000,“dataRate”:{“modulation”:“LORA”,“bandwidth”:125,“spreadFactor”:12},“adr”:false,“codeRate”:“4/5”},“fCnt”:207,“fPort”:1,“data”:“Dgb/DggGTOsFA4gLAZ0=“}

decoding from Base64: Dgb/DggGTOsFA4gLAZ0=
Decoded packet

      Message Type = Join Request
        PHYPayload = 0E06FF0E08064CEB0503880B019D

    ( PHYPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] | MIC[4] )
            AppEUI = 05EB4C06080EFF06
            DevEUI = 9D010B8803
          DevNonce =
               MIC = 880B019D

application/3/node/008000000000db13/rx {“applicationID”:“3",“applicationName”:“Lantia_App”,“deviceName”:“MDOT-BOX”,“devEUI”:“008000000000db13",“rxInfo”:[{“mac”:“00800000a000060e”,“rssi”:-24,“loRaSNR”:12.2,“name”:“00800000a000060e”,“latitude”:0,“longitude”:0,“altitude”:0}],“txInfo”:{“frequency”:868300000,“dataRate”:{“modulation”:“LORA”,“bandwidth”:125,“spreadFactor”:12},“adr”:false,“codeRate”:“4/5"},“fCnt”:208,“fPort”:1,“data”:“Dgb/DggGTNkFA48LAZ0=“}
decoding from Base64: Dgb/DggGTNkFA48LAZ0=
Decoded packet

      Message Type = Join Request
        PHYPayload = 0E06FF0E08064CD905038F0B019D

    ( PHYPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] | MIC[4] )
            AppEUI = 05D94C06080EFF06
            DevEUI = 9D010B8F03
          DevNonce =
               MIC = 8F0B019D

All the Json messages are JoinRequest type.

I would want to get the MDOT sensor data, i. e., temperature, pression, light, gps, but I don´t know how do this.

Best regard
Antonio

It is in the base64 encoded data field of the ...../rx topic. You need to decode the base64 encoded payload to bytes and then decode these based on the encoding of the mDot temperature, press ion, light, gps, … Please refer to the the MDot box documentation for the encoding of these fields.

Sorry, I would like to explain it better.

This is the message I got from MDOT-BOX:

application/3/node/008000000000db13/rx {“applicationID”:“3",“applicationName”:“Lantia_App”,“deviceName”:“MDOT-BOX”,“devEUI”:“008000000000db13",“rxInfo”:[{“mac”:“00800000a000060e”,“rssi”:-24,“loRaSNR”:12.2,“name”:“00800000a000060e”,“latitude”:0,“longitude”:0,“altitude”:0}],“txInfo”:{“frequency”:868300000,“dataRate”:{“modulation”:“LORA”,“bandwidth”:125,“spreadFactor”:12},“adr”:false,“codeRate”:“4/5"},“fCnt”:208,“fPort”:1,“data”:“Dgb/DggGTNkFA48LAZ0=“}

I select the “data” field, that is: “Dgb/DggGTNkFA48LAZ0=” from “”data”:“Dgb/DggGTNkFA48LAZ0=”
and apply this decrypter “https://lorawan-packet-decoder-0ta6puiniaut.runkit.sh.”

That site returns me this:

Message Type = Join Request
AppEUI = 0500000008000000
DevEUI = 0E020B0000
DevNonce =
MIC = 000B020E

The payload always is Join Request type. Should I send a downlink message to Mdot in order to accept the connection ?

The data field is not a LoRaWAN frame. It contains the decrypted FRMPayload field of a LoRaWAN frame, thus the payload sent by your mDot. I don’t think that the https://lorawan-packet-decoder-0ta6puiniaut.runkit.sh decoder knows anything about how to decode this back to temp, gps, etc… For this you need to refer to the documentation of the mDot box.

With the mDot you configure your own data packet structure when you program it using the Mbed software.

For example in my program, after I join the network this is how I send data from a tank level sensor and battery voltage reading:

    uint16_t tank = TankPin.read_u16();
    tx_data.push_back((tank >> 8) & 0xFF);
    tx_data.push_back(tank & 0xFF);

    uint16_t battery = BatPin.read_u16();
    tx_data.push_back((battery >> 8) & 0xFF);
    tx_data.push_back(battery & 0xFF);
    logInfo("bat: %lu [0x%04X] tank: %lu [0x%04X]", battery, battery, tank, tank);

Then in Node-red to decompile this message I use:

//extract Mdot info
var raw_tank_lvl = parseInt(msg.data.substring(0,4), 16); 
var raw_battery = parseInt(msg.data.substring(4,8), 16);

//apply scaling factor, round to integer
var tank_lvl = Math.round((raw_tank_lvl-12770)/203);  //12850 = 0%, 33175 = 100%, ~203 per %     
var battery = Math.round((raw_battery/5142.58)*100); //5142.58 per volt, x 100 to round to 2 decimal places when passing ints\n\n    

//setup node-red messages
msgBat = {};
msgBat.payload = {};
msgBat.payload.value = [battery];
msgLvl = {}; 
msgLvl.payload = {};
msgLvl.payload.value = [tank_lvl];

Hope this helps

i have succesfuly decoded the data from the MBOX using the following functions in the:
Organizations > LoRa Server > Applications > Application configuration > Payload decoder function:

function Decode(fPort, bytes) {
var s =‘0x’;
bytes.forEach(function(byte) {
s += (‘0’ + (byte & 0xFF).toString(16)).slice(-2);
});

  string=autoCase(s);

return string;

}

function autoCase(hex){

if (hex.substr(0,2)==‘0x’){
new_hex=preatyHex(hex);
}
else {
new_hex=hex;
}
console.log(new_hex);

// console.log(new_hex.substr(0,2)==00);
// console.log(new_hex.substr(4,2)==00);

hexLength=new_hex.length;
// console.log(new_hex.substr(hexLength-2,2));

// console.log(hexLength);

if (hexLength ==28 && new_hex.substr(0,2)==‘0e’) {
console.log(‘LoraDemo’)
string=DecodeLoraDemo(new_hex);

}
else if ((new_hex.substr(0,2)==‘1d’ && new_hex.substr(hexLength-2,2)==‘1d’) && hexLength>=26) {
console.log(‘SurveySweep’)
string=DecodeSurveySweep(new_hex);
}

else if (hexLength>=22 && (new_hex.substr(0,2)==‘00’ && new_hex.substr(4,2)==‘00’)){
console.log(‘SurveyGPS’)

  // new_hex=new_hex+'00000000000000000000';
  string=DecodeSurveyGPS(new_hex);

}

return string;
}

function DecodeLoraDemo(hex){

var xAc=parseInt(hex.substr(2,2),16)*0.0625;
var yAc=parseInt(hex.substr(4,2),16)*0.0625;
var zAc=parseInt(hex.substr(6,2),16)*0.0625;
var presure=parseInt(hex.substr(10,6),16)*0.25/1000;
var lux=parseInt(hex.substr(18,4),16)*0.25;
var temperature=parseInt(hex.substr(24,4),16)*0.0625;

return {“acceleration_X”:xAc, “acceleration_Y”:yAc, “acceleration_Z”:zAc, “presure”:presure, “lux”:lux,“temperature”:temperature}
}

function DecodeSurveyGPS(hex){

var temperature=parseInt(hex.substr(2,2),16);
var lat=parseInt(hex.substr(6,8),16)/(Math.pow(2,31)-1)*90;
var long=parseInt(hex.substr(14,8),16)/(Math.pow(2,31)-1)*180;

if (long > 180) {
long=(360-long)*(-1)
}
return {“temperature”:temperature, “LatitudeGPS”:lat, “LongitudeGPS”:long}
}

function DecodeSurveySweep (hex){

var QosUpLink = hex.substr(2,10); //4 bytes
var NumberOfGateways = parseInt(QosUpLink.substr(2,4),16);
var Margin=parseInt(QosUpLink.substr(6,2),16);
var TxPower=parseInt(QosUpLink.substr(8,2),16);

var QosDownLink = hex.substr(12,8); //3 bytes
var RSSI=parseInt(QosDownLink.substr(2,4),16);
var SNR=parseInt(QosDownLink.substr(6,2),16);

var LockStatus =parseInt(hex.substr(22,2),16).toString(2); //1 byte
var gpsStatus=checkgpsStatus(LockStatus.substr(0,4));
var numberOfSatelit = parseInt(LockStatus.substr(4,4),2);

var LatitudeGPS = hex.substr(24,10); //4 bytes
var LongitudeGPS =hex.substr(34,12); //5 bytes

return {“10_qosUpLink”: QosUpLink,
“11_numberOfGateways”: NumberOfGateways,
“12_margin”: Margin,
“13_txPower”: TxPower,
“20_qosDownLink”: QosDownLink,
“21_rSSI”: RSSI,
“22_SNR”: SNR,
“30_LockStatus”: LockStatus,
“31_gpsStatus”: gpsStatus,
“32_numberOfSatelit”: numberOfSatelit,
“40_LatitudeGPS”: LatitudeGPS,
“50_LongitudeGPS”: LongitudeGPS}
}

function checkgpsStatus(byteString){
/**
0 No GPS device detected.
1 No fix
2 2D fix – only latitude, longitude, and time are valid
3 3D fix – all data valid

ex: 1100
**/

resultat=‘’;

if (byteString.substr(0,1)==0){
resultat += 'No GPS device detected, ';
}
else if (byteString.substr(0,1)==1){
resultat += 'GPS device detected, ';
}

if (byteString.substr(1,1)==1){
resultat += 'No Fix ';
}
else if (byteString.substr(2,1)==1) {
resultat += '2DFix ';
}
else if (byteString.substr(3,1)==1) {
resultat += '3DFix ';
}

return resultat;
}

function preatyHex(hex){
if (hex.substr(0,2)==‘0x’){
hex=hex.substr(2,hex.length);
}
return hex;
}

best regards

Hi…

I tried the above but had issues getting it to work with my mbox (2…1.2) and loraserver (2.4.1). It kept throwing a an error about defining the var s variable.

I was however to get decode my mbox using the following code, so thought I’d share back with the community.

// Decode decodes an array of bytes into an object.
//  - fPort contains the LoRaWAN fPort number
//  - bytes is an array of bytes, e.g. [225, 230, 255, 0]
// The function must return an object, e.g. {"temperature": 22.5}

function Decode(fPort, bytes) {
var evb_sensors = {};
var EVB_TYPE = {
  none: 0,
  led_1: 1,
  led_2: 2,
  lux_max: 3,
  lux_min: 4,
  lux: 5,
  barometer_max: 6,
  barometer_min: 7,
  barometer: 8,
  temperature_max: 9,
  temperature__min: 10,
  temperature: 11,
  accelerometer_max: 12,
  accelerometer_min: 13,
  accelerometer: 14,
  tx_interval: 15,
  amps_max: 16,
  amps_min: 17,
  amps: 18,
  m2x_device: 19,
  m2x_key: 20,
};

/*
 * Process the EVB LoRa payload.
 *
 * EVB payload contains one or more TLV fields.
 *
 * [<type: accelerometer><length: 6><x-high><x-low><y-high><y-low><z-high><z-low>]
 * [<type: barometer><length: 3><byte2><byte1><byte0>]
 * [<type: temperature><length: 2><byte-high><byte-low>]
 * 
 */
for (var index = 0; index < bytes.length; ) {
  var type = bytes[index++];
//   var length = bytes[index++];
  var value;
  console.log("type: " + type + " length: " );

  switch (type) {
  case EVB_TYPE.lux:
    if (typeof(evb_sensors.light) == "undefined") {
      evb_sensors.light = {};
    }

    value = bytes[index++] << 8;
    value |= bytes[index++];
    value = value * 0.24;

    evb_sensors.light.lux = value;
    break;
  case EVB_TYPE.barometer:
    if (typeof(evb_sensors.barometer) == "undefined") {
      evb_sensors.barometer = {};
    }

    value = bytes[index++] << 16;
    value |= bytes[index++] << 8;
    value |= bytes[index++];
    value = value * 0.00025;

    evb_sensors.barometer.pa = value;
    break;
  case EVB_TYPE.temperature:
    if (typeof(evb_sensors.temperature) == "undefined") {
    evb_sensors.temperature = {};
      }

    value = (bytes[index++] << 24) >> 16;
    value |= bytes[index++];
    value = value * 0.0625;

    evb_sensors.temperature.c = value;
    evb_sensors.temperature.f =  value * 9 / 5 + 32; 
      
      break;
  case EVB_TYPE.accelerometer:
    if (typeof(evb_sensors.accelerometer) == "undefined") {
    evb_sensors.accelerometer = {};
      }
      // evb_sensors.accelerometer.x = (bytes[index++] << 24) >> 16;
      var x1 = evb_sensors.accelerometer.x = bytes[index++] ;
      // x1 = ~x1 ; 
      // x1 = ( x1 + 1 ) % 256; 
      evb_sensors.accelerometer.x = x1 * 0.0625//; / 15;
      // evb_sensors.accelerometer.y = (bytes[index++] << 24) >> 16;
      var y1 = evb_sensors.accelerometer.y = bytes[index++] ;
      // y1 = ~ y1 ; 
      // y1 = ( y1 + 1 ) % 256;
        
      var y1 = evb_sensors.accelerometer.y = y1 * 0.0625 ; // / 15 ;

        // evb_sensors.accelerometer.z = (bytes[index++] << 24) >> 16;
      var z1 = evb_sensors.accelerometer.z = bytes[index++] ;
      // z1 = ~ z1 ; 
      // z1 = ( z1 + 1 ) % 256; 
      // z1 = z1 - 128;
      var z1 = evb_sensors.accelerometer.z = z1 * 0.0625; // / 15;
      break;      
      }
  }
  return {
    temp_c: evb_sensors.temperature.c,
    temp_f: evb_sensors.temperature.f,
    moisture: evb_sensors.barometer.pa,
    lux: evb_sensors.light.lux,
    x_acc: evb_sensors.accelerometer.x,
    y_acc: evb_sensors.accelerometer.y,
    z_acc: evb_sensors.accelerometer.z
  }
}

Please format your code the next time (I’ve edited your post for JS highlighting) :slight_smile: