How can I decode my hexadecimal payload from The Things Stack in Ubidots?

I am trying to send the distance measurements from my RAK Wisblock 4630 (which is connected to the RAK 12007 ultrasonic sensor) over LoRaWAN to The Things Stack and then to Ubidots. I am able to send a payload as a hexadecimal to The Things Stack but Ubidots is unable to decode the hexadecimal as a variable. Any help would be greatly appreciated. Thanks!

Welcome to RAK forum @EngGuy :slight_smile:

With Ubidots, you can do the payload decoding on TTS or on Ubidots itself. Maybe you can share how you format the payload in your source code? From there we can see how we can decode the payload.

Here is the source code. The var mm is the distance measurement taken by the ultrasonic sensor. I am trying to send that distance as the payload.

#include <Arduino.h>

#include <LoRaWan-RAK4630.h> //

#include "LoRaWAN_functs.h" /**< Go here to provide the OTAA keys & change the LoRaWAN settings. */

#include "OTAA_keys.h"      /**< Go here to set the OTAA keys (See README). */

#include <string.h>

#include <string>

#include <Wire.h>

#include <Adafruit_GFX.h>   //Click here to get the library: http://librarymanager/All#Adafruit_GFX

#include <Adafruit_SSD1306.h>   //Click here to get the library: http://librarymanager/All#Adafruit_SSD1306

#ifdef RAK4630

  #define BOARD "RAK4631 "

  #define  RAK4631_BOARD true  

#else    

  #define  RAK4631_BOARD false            

#endif

 

#define TRIG WB_IO6

#define ECHO WB_IO4

#define PD   WB_IO5   //power done control (=1 power done,=0 power on)

#define TIME_OUT  24125 //max measure distance is 4m,the velocity of sound is 331.6m/s in 0℃,TIME_OUT=4*2/331.6*1000000=24215us

float ratio = 346.6/1000/2;   //velocity of sound =331.6+0.6*25℃(m/s),(Indoor temperature about 25℃)

long int duration_time();  //measure high level

// App payload interval value in [ms] = 30 seconds.

const int lorawan_app_interval = 30000;

/**

 * @brief Setup code runs once on reset/startup.

 */

void setup() {

   

    // Initialize built in green LED

    pinMode(LED_BUILTIN, OUTPUT);

    digitalWrite(LED_BUILTIN, HIGH);

    // Initialize Serial for debug output

    Serial.begin(115200);

    // Wait for USB Serial to be ready or terminal to be connected

    time_t timeout = millis(); // Timeout in case the system runs on its own

    // Waiting for Serial

    while (!Serial)

    {

        if ((millis() - timeout) < 5000)

        {

            // Blink the LED to show that we are alive

            delay(100);

            digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

        }

        else

        {

            // Timeout while waiting for USB Serial

            break;

        }

    }

        pinMode(ECHO, INPUT);   // Echo Pin of Ultrasonic Sensor is an Input

        pinMode(TRIG, OUTPUT);  // Trigger Pin of Ultrasonic Sensor is an Output

        pinMode(PD, OUTPUT);    // power done control pin is an Output

        digitalWrite(TRIG,LOW);

        digitalWrite(PD,LOW);

        pinMode(LED_BLUE, OUTPUT);   // The LED is an Output  

        Serial.println("\n=================================");

        Serial.println("Welcome to Simple LoRaWAN Example");

        Serial.println("\n=================================");

    // Init LoRaWAN

    if (!initLoRaWAN(OTAA_KEY_APP_EUI, OTAA_KEY_DEV_EUI, OTAA_KEY_APP_KEY)) {

        delay(1000);

        return;

    }

    // Attempt to join the network

    startLoRaWANJoinProcedure();

}

/**

 * @brief Loop code runs repeated after setup().

 */

void loop()

{

    // Buffer that payload data is placed in.

    delay(lorawan_app_interval);

    long int duration, mm;

    digitalWrite(LED_BLUE,HIGH);

    duration = duration_time();

    if(duration > 0)

    {

      mm = duration*ratio; //Test distance = (high level time×velocity of sound (340M/S) / 2,

      digitalWrite(LED_BLUE,LOW);    

      Serial.print(mm);

      Serial.print("mm");

      Serial.println();

   }

   else

   {

      Serial.println("Out of range");  

   }

  delay(100);

}

long int duration_time()

{

   long int respondTime;

   pinMode(TRIG, OUTPUT);

   digitalWrite(TRIG, HIGH);

   delayMicroseconds(12);   //pull high time need over 10us

   digitalWrite(TRIG, LOW);  

   pinMode(ECHO, INPUT);

   respondTime = pulseIn(ECHO, HIGH); // microseconds

   delay(33);

   if(RAK4631_BOARD)

   {

     respondTime = respondTime*0.7726; // Time calibration factor is 0.7726,to get real time microseconds for 4631board

   }

   Serial.printf("respond time is %d\r\n",respondTime);

   if((respondTime>0)&&(respondTime < TIME_OUT))  //ECHO pin max timeout is 33000us according it's datasheet

   {

    return respondTime;

   }

   else

   {

     return -1;  

   }  

}

    // every lorawan_app_interval milliseconds check if the device is connected

    //std::string pp = std::to_string(mm);

    uint8_t payload_buffer[PAYLOAD_BUFFER_SIZE] = mm;

       // Struct that passes the payload data for a LoRaWAN frame.

    lmh_app_data_t lorawan_payload = {

      payload_buffer, 4, 1, 0, 0,

    };

    if (isLoRaWANConnected()) {

        Serial.println("Send payload");

        // send sendLoRaWANFrame will do nothing if not connected anyway, but it's best practice to check

        sendLoRaWANFrame(&lorawan_payload);

    } else {

        // else log that it's not connected

        Serial.println("LoRaWAN not connected. Try again later.");

    }

}

I prefer to do decoding in TTN instead of Ubidots so that if you want to integration to other platforms, it is already decoded.

You can use this TTN decoder (assuming you are sending in fport 1)

To use this decoder in Ubidots you need to change the default plugin. Since the default do not use TTN decoder. You just need to uncomment 1 line and also comment another line.

Thanks so much! My ubidots is finally receiving decoded distance data! However, it isn’t the correct number. If my arduino IDE code sends a string “500”, Ubidots receives it as 53. How can I fix this? Also ideally I would like to send the distance data but the ultrasonic sensor calculates distance as a long integer and my code won’t run when the payload contains data of this type. How can I convert the long integer into a string?
Thanks again!

Hi @EngGuy ,

A single byte can only allow you to transmit value maximum 255. You need to use 2-bytes to cover your 500 value.

Pseudo-code

uint16_t mm = 500;

m_lora_app_data.buffer[i++] = mm >> 8;
m_lora_app_data.buffer[i++] = mm ;
m_lora_app_data.buffsize = i;

On the TTS decoder side,

function Decoder(bytes, port) 
{
  var decoded = {};
  
  if (port === 1) //assuming you are sending at port 1
  {
      decoded.distance =  (bytes[0] << 8) | (bytes[1]);
      // add other sensors if you have.
      return decoded;
  }
}