Arduino MQTT Client: decoding subscribe message.

Hello.

I have managed to get an Arduino MQTT Client to work and work well. I now want to decode the data in the message (payload) of the subscribed topic.

Here is the associated piece of code:

Here is the output from the IDE -

Using board 'mega' from platform in folder: C:\Users\johno\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Using core 'arduino' from platform in folder: C:\Users\johno\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Detecting libraries used...
"C:\Users\johno\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\Users\johno\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3\cores\arduino" "-IC:\Users\johno\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3\variants\mega" "C:\Users\johno\AppData\Local\Temp\arduino-sketch-AAB4E1EA55727EB640A0AF04A530CE7B\sketch\sketch_apr5_v9.0.ino.cpp" -o nul
Alternatives for LMIC.h:
ResolveLibrary(LMIC.h)
-> candidates:
Compilation error: Error: 2 UNKNOWN: exit status 1

Could anyone suggest where I'm going wrong, please. Many thanks.

Hello, again.

Got no idea what happened to my code so here it goes -

/*
  Arduino MQTT Client v9.0
  Extracting DHT22 data from payload.

  Arduino Mega + genuine Arduino Ethernet Shield2
  Subscribes to topic "application/+/device/+/+"
  IPaddress RAK7249 in-built server  192.168.1.227 (Barn) or 192.168.1.250
  (Network Room) Arduino ethernet shield MAC address is A8:61:0A:AE:6A:0B

  https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/

*/

//#include <Adafruit_Sensor.h>
//#include "DHT.h"
#include <LMIC.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <string.h>

// float temperature;
// float humidity;
int data[5];
int dataStart;
int dataEnd;
float rawTemp;
float rawHumid;
int i;

byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x6A, 0x0B};              //  MAC address Arduino Ethernet Shield MQTT client
IPAddress ip(192, 168, 1, 51);                                  //  Static IP address Arduino MQTT client
IPAddress server(192, 168, 1, 227);                             //  Static IP address RAK7249 built-in LoRa server Barn

void callback(char *topic, byte *payload, unsigned int length) 
{
  Serial.print("\nMessage arrived\nTopic\n  [");
  Serial.print(topic);                                          // Print topic
  Serial.print("]\n");
  Serial.print("Payload\n  "); 
  for (int i = 0; i < length; i++) 
  {
    Serial.print((char)payload[i]);                             // Print payload
  }  
  Serial.print("\n");

  if (strstr(payload, "01f3b8fb5a1c1050"))                      // DTH22 environment message?  Search for devEUI.
  {                     
    dataStart = int(strchr(payload, 'data":"'));                // point to the start of the environment data
    dataEnd = int(strchr(payload, 'data_encode') - 14);         // point to the end of the environment data
    for (i = dataStart; i < dataEnd; i++) 
    {
      data[i] = payload[i];                                     // extract the environment data to a new string
    }

    // isolate temperature
    rawTemp = data[0] + data[1] * 256;  
    // float -> int: this uses the sflt16 datum (https://github.com/mcci-catena/arduino-lmic#sflt16)
    uint16_t payloadTemp = f2sflt16(rawTemp) * 100;     //alt code: temperature = sflt162f(rawTemp) * 100;
    // isolate humidity
    rawHumid = data[2] + data[3] * 256;                          
    uint16_t payloadHumid = f2sflt16(rawHumid)* 100;         //humidity = sflt162f(rawHumid) * 100;
        
    Serial.print("\n    Environment:  ");
    Serial.print("Temperature: ");
    Serial.print(payloadTemp);
    Serial.print("° C");
    Serial.print("  Humidity: ");
    Serial.print(payloadHumid);
    Serial.print("% rH");
  }
}

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

void reconnect() 
{
  while (!mqttClient.connected())                                 // Loop until we're reconnected  
  {                                
    Serial.print("\nAttempting MQTT connection...");

    if (mqttClient.connect("arduinoClient9"))                     // Attempt to connect
    {                        
      Serial.print("\nThe client is connected.");
      mqttClient.subscribe("application/+/device/+/+");
      }
      else 
      {
      Serial.print("\nFailed, rc = ");
      Serial.print(mqttClient.state());
      Serial.print("\nTry again in 5 seconds.");
      delay(5000);}                                               // Wait 5 seconds before retrying
   }  
}

void setup() 
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip);
  delay(5000);                                                    // Allow the hardware to sort itself out
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
}

void loop() 
{
  if (!mqttClient.connected()) 
  {
    reconnect();
  }  
  mqttClient.loop();
}

It looks like you're missing the LMIC library (whatever that is).

Just for completeness, there were a number of issues, all down to my coding. Here’s the offending bit -

if (strstr(payload, “01f3b8fb5a1c1050”)) // DTH22 environment message? Search for devEUI.
{
dataStart = int(strchr(payload, ‘data":"’)); // point to the start of the environment data
dataEnd = int(strchr(payload, ‘data_encode’) - 14); // point to the end of the environment data
for (i = dataStart; i < dataEnd; i++)
{
data = payload*; // extract the environment data to a new string*
* }*
At the very least, the last line of code should look like this -
_ data[i-dataStart] = payload*;*
Yes, LMIC library wasn’t present however that’s sorted too. Thank you.
I think I shld apologise for my post. I’m a great believer that most issues can be solved by resting your brain for a while, then double-double check your code, line by line. I’m also a great believer that the more you read and research the more you learn about Arduino and coding. When ur at ur whits end you’re actually not.
Thanks for ur help._

Well, I hope I’m not shooting myself in the foot!! Wondered if someone familiar with ArduinoJson v6 cld advise me about the following code. It is from my Arduino MQTT Client which I have had working really well. I have even managed to isolate the “data” and print it out.

I want to have a go at deserializing the payload message using ArduinoJson. You will recognise the code below. It works - complies, loads and runs - but the value of the message is 0, zero in both node-cases. It should be “Hello xxxxx” in one and 8-bytes temp/humid in the other. Certainly not 0.

Here’s the code -

void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("\nMessage arrived\nTopic\n [");
Serial.print(topic); // Print topic
Serial.print("]\n");
Serial.print("Payload\n ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload*); // Print payload*

  • } *
  • Serial.print("\n");*
  • StaticJsonDocument<512> doc;*
  • deserializeJson(doc, payload, length);*
  • // use the JsonDocument as usual…*
  • int val = doc[“data”];*
  • // Node 4 - Hello*
  • if (strstr(topic, “007e47c0ac6183b2/rx”)) // “Hello” message? *
  • Search for devEUI.*
  • {*
  • Serial.print("Node 4: \n ");*
  • Serial.println(val);*
  • }*
  • // Node 5 - DHT22*
  • if (strstr(topic, “01f3b8fb5a1c1050/rx”)) // DTH22 environment*
  • message? Search for devEUI.*
  • {*
  • Serial.print("Node 5: \n ");*
  • Serial.println(val);*
  • }*
    }

I apologise for the layout mess in my last 2 posts.

repost the well formatted code in code tags.

Their should not be so much processing of the received info in the MQTT callback. Instead collect the information, tell the loop() function with set bool that is has a message to process, and get out.

Here is the code I use for the mqtt call back

void IRAM_ATTR mqttCallback(char* topic, byte * payload, unsigned int length)
{
  memset( x_message.payload, '\0', payloadSize ); // clear payload char buffer
  x_message.topic = ""; //clear topic string buffer
  x_message.topic = topic; //store new topic
  int i = 0; // extract payload
  for ( i; i < length; i++)
  {
    x_message.payload[i] = ((char)payload[i]);
  }
  x_message.payload[i] = '\0';
  xQueueOverwrite( xQ_Message, (void *) &x_message );// send data to queue
}

Full code

  memset( x_message.payload, '\0', payloadSize ); // clear payload char buffer
  x_message.topic = ""; //clear topic string buffer

Clears the last info received in the callback.

x_message.topic = topic; //store new topic

  int i = 0; // extract payload
  for ( i; i < length; i++)
  {
    x_message.payload[i] = ((char)payload[i]);
  }
  x_message.payload[i] = '\0';

Extracts the payload and topic.

 xQueueOverwrite( xQ_Message, (void *) &x_message );// send data to queue

Notifies/send the parser the new received message.

Idaowalker: you are fantastic. Thank you. I print out your pieces and paste then into a spiral-bound hard-covered A4 note book which is my workbook. Then I implement your advice into my code and and slave away until it works. It’s amazing what you learn with a few pointers and Google. So I’m very grateful. I want to use ArduinoJson to deserialise the payload so once I get your code to work, I’ll have a go at implementing JSON. Thanks again.

Hi again

I have managed to get this code to work. It goes really well, but after an hour or so, it slows down. Any suggestions as to why. Can I decode the data within the void callback()?

Thanks.

void callback(char *topic, byte *payload, unsigned int length)
{
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, payload, length); // Deserialize the JSON document

if (error) // Test if parsing succeeds.
{
Serial.print(F(“deserializeJson() failed: “));
Serial.println(error.f_str());
return;
}
const char* data = doc[“data”]; // Fetch values.
const char* devEUI = doc[“devEUI”];
Serial.print (”\ndevEUI = “);
Serial.print (devEUI);
Serial.print (” data = “);
Serial.print (data);
Serial.print (”\n”);
}

Without the rest of the code the guess as to why your thingy slows down may remain a mystery.

In the interest of speed, why serial print in a ISR. Your not using a ESP32, which would easily handle some serial prints from a ISR, but still not the best code practice.

In your ISR all needs be is preserve the payload, preserve the topic, and signal the loop(), if using it, that a thingy has arrived and parse.

void mqttcallback( things )
{
placePyaLoadDataHere;
placeTopicDataHere;
TimeToParse = true;
}

TimeToparse is a Boolean that gets set to true by the ISR

In loop(), if you are using loop(), you’d do a

if( TimeToParse)
{
getPayload
gettopic
parse payload and topic
do the things
TimeToParse = false
}
}

Hello, again. Idahowalker, thank you for your response. I had figured that that was exactly what I had to a couple of weeks ago, but I just cldn’t get it to work. So, I’ve started again and hopefully, followed your prescription.

I have had this code working by parsing strings, but I was trying to reduce the amount of code within the ISR. I’m quite keen to make it work with AtduinoJson.

I’ve take out the Serial.print statements to reduce the amount of code to publish here. I’ve managed to get the code tags to work. so here is the code. I get absolutely nothing printed. In earlier attempts, I got two successful loops then nothing.

Would appreciate any insights. Thanks.

#include <Ethernet.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <String.h>

StaticJsonDocument<1024> doc;
boolean TimeToParse = false;
char data[32] = "";
char devEUI[32] = "";

byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x6A, 0x0B};                          //  MAC address Arduino Ethernet Shield MQTT client
IPAddress    ip(192, 168, 1, 51);                                           //  Static IP address Arduino MQTT client
IPAddress    server(192, 168, 1, 227);                                      //  Static IP address RAK7249 built-in LoRa server Barn

void callback(char* topic, byte* payload, unsigned int length)              //  ISR
{ 
  if (topic == "application/+/device/+/rx")                                 // "join" message carries no "data". only deserialize "rx"
    {
    deserializeJson(doc, payload, length);                                  // Deserialize the JSON document    
    TimeToParse = true;                                                     // set flag for loop to parse payload
  }
}

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

void reconnect() 
{
  while (!mqttClient.connected())                                         // Loop until reconnected  
  {                                
    if (mqttClient.connect("arduinoClient9"))                             // Attempt to connect
      {                        
      mqttClient.subscribe("application/+/device/+/+");
      }
      else 
      {
      delay(5000);                                                        // Wait 5 seconds before retrying
      } 
  }
}

void setup() 
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip);
  delay(5000);                                                            // Allow the hardware to sort itself out
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
}

void loop()
{ 
  if (!mqttClient.connected()) 
    {
      reconnect();
    }
  mqttClient.loop();

  if (TimeToParse)                                                       // if true, then there's data to be parsed from the ISR
  { 
     // get payload_parse payload    
      strlcpy(data, doc["data"] | "default", sizeof(data));
      strlcpy(devEUI, doc["devEUI"] | "default", sizeof(devEUI));

     // IdahoWalker:- do the things - This will come later, once the basic deserialization code is working.
     // For the moment, just Serial.print the devEUI and the associated data
     if (devEUI == "01f3b8fb5a1c1050")
      { 
        Serial.print ("\n 01f3b8fb5a1c1050 devEUI = ");
        Serial.print (devEUI);        
      } 
     if (devEUI == "007e47c0ac6183b2")
      { 
        Serial.print ("\n 007e47c0ac6183b2 data = ");
        Serial.print (data);
      } 
    TimeToParse = false;            
  }    
}

Hi, again. Gotta tell you, Idahowalker, im having a ball.

I thought a bit more and you will see from the following code, I commented out various code, in partic if (devIDE = blahblah “join”) then skip the loop. Suddeenly it started to work. So right now, Its workin albeit messy!! Here’s the sode -

/*
  Arduino MQTT Client v16.2
  IdahoWalker advice 
  De-serialization
  all Serial.print have been removed

  Arduino Mega + genuine Arduino Ethernet Shield2
  Subscribes to topic "application/+/device/+/+"
  IPaddress RAK7249 in-built server  192.168.1.227 (Barn) or 192.168.1.250
  (Network Room) Arduino ethernet shield MAC address is A8:61:0A:AE:6A:0B

  https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/

  https://github.com/bblanchon/ArduinoJson

*/

#include <Ethernet.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <String.h>

StaticJsonDocument<1024> doc;
boolean TimeToParse = false;
char data[32] = "";
char devEUI[32] = "";

byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x6A, 0x0B};                          //  MAC address Arduino Ethernet Shield MQTT client
IPAddress    ip(192, 168, 1, 51);                                           //  Static IP address Arduino MQTT client
IPAddress    server(192, 168, 1, 227);                                      //  Static IP address RAK7249 built-in LoRa server Barn

void callback(char* topic, byte* payload, unsigned int length)              //  ISR
{ 
  //if (topic == "application/+/device/+/rx")                                 // "join" message carries no "data". only deserialize "rx"
  //  {
     Serial.print("\nMessage arrived\nTopic\n  [");
     Serial.print(topic);
     Serial.print("]\n");
     Serial.print("Payload\n  ");
     for (int i=0;i<length;i++) 
       {
         Serial.print((char)payload[i]);
       }
    Serial.println();
    deserializeJson(doc, payload, length);                                  // Deserialize the JSON document    
    TimeToParse = true;                                                     // set flag for loop to parse payload
  //}
}

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

void reconnect() 
{
  while (!mqttClient.connected())                                         // Loop until reconnected  
  {                                
    if (mqttClient.connect("arduinoClient9"))                             // Attempt to connect
      {                        
      mqttClient.subscribe("application/+/device/+/+");
      }
      else 
      {
      delay(5000);                                                        // Wait 5 seconds before retrying
      } 
  }
}

void setup() 
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip);
  delay(5000);                                                            // Allow the hardware to sort itself out
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
}

void loop()
{ 
  if (!mqttClient.connected()) 
    {
      reconnect();
    }
  mqttClient.loop();

  if (TimeToParse)                                                       // if true, then there's data to be parsed from the ISR
  { 

    Serial.print ("Time to parse!\n");
     // get payload_parse payload    
      strlcpy(data, doc["data"] | "default", sizeof(data));
      strlcpy(devEUI, doc["devEUI"] | "default", sizeof(devEUI));

      if (data != NULL)
{
     // IdahoWalker:- do the things - This will come later, once the basic deserialization code is working.
     // For the moment, just Serial.print the devEUI and the associated data
    // if (devEUI == "01f3b8fb5a1c1050")
      //{ 
      //  Serial.print ("\n 01f3b8fb5a1c1050 devEUI = ");
        Serial.print (devEUI); 
        Serial.print("\n"); 
        Serial.print (data); 
        Serial.print("\n");     
      } 
     //if (devEUI == "007e47c0ac6183b2")
     // { 
     //   Serial.print ("\n 007e47c0ac6183b2 data = ");
     //   Serial.print (data);
     // } 
    TimeToParse = false;  
    Serial.print (TimeToParse); 
    Serial.print ("\n");        
  }    
}

Working perfectly. Thank you for all your help. Regards

#include <Ethernet.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <String.h>

StaticJsonDocument < 1024 > doc;
boolean TimeToParse = false;
char data[32] = "";
char devEUI[32] = "";

byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x6A, 0x0B };                          //  MAC address Arduino Ethernet Shield MQTT client
IPAddress ip(192, 168, 1, 51);                                                //  Static IP address Arduino MQTT client
IPAddress server(192, 168, 1, 227);                                           //  Static IP address RAK7249 built-in LoRa server Barn

void callback(char * topic, byte * payload, unsigned int length)              //  ISR
{
  if (strstr(topic, "rx"))                                                    // "join" message carries no "data". only deserialize "rx"
  {
  deserializeJson(doc, payload, length);                                     // Deserialize the JSON document    
  TimeToParse = true;                                                        // set flag for loop to parse payload
  }
}

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

void reconnect() 
{
  while (!mqttClient.connected())                                              // Loop until reconnected  
  {
    if (mqttClient.connect("arduinoClient9"))                                  // Attempt to connect
    {
      mqttClient.subscribe("application/+/device/+/+");
    } else {
      delay(5000);                                                             // Wait 5 seconds before retrying
    }
  }
}

void setup() 
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip);
  delay(5000);                                                                // Allow the hardware to sort itself out
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
}

void loop() 
{
  if (!mqttClient.connected()) 
  {
    reconnect();
  }
  mqttClient.loop();

  if (TimeToParse)                                                            // if true, then there's data to be parsed from the ISR
  {
             
    strlcpy(devEUI, doc["devEUI"], sizeof(devEUI));                           // parse payload 
    strlcpy(data, doc["data"], sizeof(data));
    {
      Serial.print ("\ndevEUI - ");
      Serial.print(devEUI);
      Serial.print("  data = ");
      Serial.print(data);
      Serial.print("\n");
    }
    TimeToParse = false;                                                      // turn off the flag
    }
}
1 Like

Oh, dear. Now here’s the bad news. I discovered that Arduino IDE Pro v2 is now at Beta 5, so I downloaded it, installed, and ran it with the above code.

The Serial.print monitor took off like a rocket. Just a blur. Incredible increase in speed over Beta 4, it would seem. The I noticed that the HelloWorld count was not increasing by one on each new line. Also, the Arduino MQTT screen was going a million times faster than the LoRa Packet Logger on my RAK7249 Gateway. The count does eventually change, but not at 10 seconds that the Node is sending at.

I don want to blame Pro 2 Beta 5. However, any ideas, anyone?

Ok! I’ve sorted that problem. In the euphoria of success, I set up another Arduino Mega MQTT client using exactly the same sketch. That meant I used exactly the same client ID. I’ve read that that practice causes havoc, and indeed it does. Changed one of the IDs and everything works fine.

I have a feeling that the slowing is contributed to, if not the cause by, the “Hello World” node adding a counter to the packet. Given that it is sending every 10 seconds (for this trial), and it has been going for months continuously, the packet has gotten very large. I reset the Mega, the deserialised payload got considerably smaller, and the performance speed increased.

The next step is to decode the payloads, eg, temperature and humidity, then put the proven concept into smart agriculture on the farm.

Thank you again for your help. Regards.

I read the mac address, I combine mac[0] and mac[4] to form a client id as part of the MQTT log in.

void connectToMQTT()
{
  MQTTclient.setKeepAlive( 90 ); // needs be made before connecting
  byte mac[5];
  WiFi.macAddress(mac);
  String clientID = String(mac[0]) + String(mac[4]) ; // use mac address to create clientID
  while ( !MQTTclient.connected() )
  {
    // boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
    MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password, NULL , 1, true, NULL );
    vTaskDelay( 250 );
  }
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( topicOK );
} // void connectToMQTT()

I’ve seen code for creating a random ID but I cldn’t get it to go. However, your approach is much simpler and will always produce a unique ID. I’ll implement that. Many thanks. Regards

Hello again. As I said, I have managed to get my Arduino MQTT to do pretty well. So having managed to parse the payload, now I want to decode the parsed payload, in partic DHT22 temp and humidity. So here's my code -

#include <Ethernet.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <String.h>
#include <lmic.h>
//#include <math.h>

StaticJsonDocument < 512 > doc;
boolean TimeToParse = false;
char data[20] = "";
char devEUI[17] = "";
char node5[] = { "01f3b8fb5a1c1050" };                                        // Node 5 devEUI
char node4[] = { "007e47c0ac6183b2" };                                        // Node 4 devEUI
float temperature;
float humidity;
float rawTemp;
float rawHumid;

var decoded = {};

byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x6a, 0x0b };                          //  (grey) MAC address Arduino Ethernet Shield MQTT client
IPAddress ip(192, 168, 1, 51);                                                //  associated static IP address Arduino MQTT client

// byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x64, 0x3a };                       //  (red) MAC address Arduino Ethernet Shield MQTT client
// IPAddress ip(192, 168, 1, 52);                                             //  associated static IP address Arduino MQTT client

IPAddress server(192, 168, 1, 227);                                           //  Static IP address RAK7249 built-in LoRa server Barn
// IPAddress server(192, 168, 1, 250);                                        //  Static IP address RAK7249 built-in LoRa server network room

void callback(char *topic, byte *payload, unsigned int length)                //  ISR
{
  deserializeJson(doc, payload, length);                                      // Deserialize the JSON document    
  TimeToParse = true;                                                         // set flag for loop to parse payload
}

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);
String clientID = String(mac[4]) + String(mac[5]) ;                           // use mac address to create clientID
  
void reconnect() 
{
  while (!mqttClient.connected())                                              // Loop until reconnected  
  {
    if (mqttClient.connect(clientID.c_str()))                                  // Attempt to connect
    {
      mqttClient.subscribe("application/+/device/+/rx");
    } else {
      delay(5000);                                                             // Wait 5 seconds before retrying
    }
  }
}

void setup() 
{
  Serial.begin(115200);
  Ethernet.begin(mac, ip);
  delay(5000);                                                                // Allow the hardware to sort itself out
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
}

void loop() 
{
  if (!mqttClient.connected()) 
  {
    reconnect();
  }
  mqttClient.loop();

  if (TimeToParse)                                                            // if true, then there's data to be parsed from the ISR
  {           
    strlcpy(devEUI, doc["devEUI"], sizeof(devEUI));                           // parse payload 
    strlcpy(data, doc["data"], sizeof(data));    

    if (strcmp(devEUI, node4) == 0)                                           // Hello, world 
    {
      Serial.print ("\nNode 4  devEUI  =  ");
      Serial.print(devEUI);
      Serial.print("  data = ");
      Serial.print(data);
      Serial.print("\n"); 
    } 
    
    if (strcmp(devEUI, node5) == 0 )                                          // DHT22
    { 
      // temperature 
      rawTemp = data[0] + data[1] * 256;
      decoded.temperature = sflt162f(rawTemp) * 100;
  
      // humidity 
      rawHumid = data[2] + data[3] * 256;
      decoded.humidity = sflt162f(rawHumid) * 100;

      Serial.print ("\nNode 5  devEUI  =  ");
      Serial.print (devEUI);
      Serial.print ("  data = ");
      Serial.print (data);
      Serial.print ("  temperature = ");
      Serial.print (temperature);
      Serial.print ("° C  Humidity = ");
      Serial.print (humidity);
      Serial.print ("% RHC");
      Serial.print ("\n"); 
    } 
    TimeToParse = false;                                                      // turn off the parsing flag       
 }
}

function sflt162f(rawSflt16)
{
	// rawSflt16 is the 2-byte number decoded from wherever;
	// it's in range 0..0xFFFF
	// bit 15 is the sign bit
	// bits 14..11 are the exponent
	// bits 10..0 are the the mantissa. Unlike IEEE format, 
	// 	the msb is transmitted; this means that numbers
	//	might not be normalized, but makes coding for
	//	underflow easier.
	// As with IEEE format, negative zero is possible, so
	// we special-case that in hopes that JavaScript will
	// also cooperate.
	//
	// The result is a number in the open interval (-1.0, 1.0);
	// 
	
	// throw away high bits for repeatability.
	rawSflt16 &= 0xFFFF;

	// special case minus zero:
	if (rawSflt16 == 0x8000)
		return -0.0;

	// extract the sign.
	var sSign = ((rawSflt16 & 0x8000) != 0) ? -1 : 1;
	
	// extract the exponent
	var exp1 = (rawSflt16 >> 11) & 0xF;

	// extract the "mantissa" (the fractional part)
	var mant1 = (rawSflt16 & 0x7FF) / 2048.0;

	// convert back to a floating point number. We hope 
	// that Math.pow(2, k) is handled efficiently by
	// the JS interpreter! If this is time critical code,
	// you can replace by a suitable shift and divide.
	var f_unscaled = sSign * mant1 * Math.pow(2, exp1 - 15);

	return f_unscaled;
	}

The relevant output from the compiler is this -

c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino:40:1: error: 'var' does not name a type
var decoded = {};
^~~
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino:130:1: error: 'function' does not name a type; did you mean 'union'?
function sflt162f(rawSflt16)
^~~~~~~~
union
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino: In function 'void loop()':
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino:109:7: error: 'decoded' was not declared in this scope
decoded.temperature = sflt162f(rawTemp) * 100;
^~~~~~~
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino:109:29: error: 'sflt162f' was not declared in this scope
decoded.temperature = sflt162f(rawTemp) * 100;
^~~~~~~~
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino: At global scope:
c:\Users\johno\Documents\Arduino\sketch_may13a v20.0\sketch_may13a v20.0.ino:130:1: error: 'function' does not name a type; did you mean 'union'?
function sflt162f(rawSflt16)
^~~~~~~~
union

I have taken the basic decoder from arduino-lmic/ttn-otaa-feather-us915-dht22.ino at master · mcci-catena/arduino-lmic · GitHub

Can anyone please help me with these errors. Many thanks.

var decoded = {};

As the error message says, var is not a data type. What data type should decoded be ?