I am using Heltec WiFi ESP32 LoRa board and a TTGO LoRa board and the code involves Tx sending 8 packets of data with a suitable delay and then Rx combines into a json and then send it to the cloud.
RX CODE:
#include “heltec.h”
#include <ArduinoJson.h>
#include <WiFi.h>
#include <HTTPClient.h>
#define Central_ID 1
#define FIXEDTXCOUNT 9
#define BAND 433E6 //you can set band here directly,e.g. 868E6,915E6
#include “DHT.h”
#define DHTPIN 13
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int csPin = 18; // LoRa radio chip select
const int resetPin = 14; // LoRa radio reset
const int irqPin = 26; // change for your board; must be a hardware interrupt pin
String dataReceived;
const char* ssid = “abcdefghi”;
const char* password = “***********”;
const char* host = “https://firetracker.online/index.php”;
byte localAddress = 0; // address of this device
byte destination = 0; // destination to send to
long lastSendTime = 0; // last send time
unsigned long interval = 5000; // interval between sends
int NodeID_Flag[FIXEDTXCOUNT];
// ---------------------------------
// Flags
int flagPacketProcessed = 1;
int flagDataAvailable = 0;
void setup()
{
Serial.begin(9600); // initialize serial
pinMode(4,INPUT);
dht.begin();
//WIFI Kit series V1 not support Vext control
Heltec.begin(true /DisplayEnable Enable/, true /Heltec.LoRa Disable/, true /Serial Enable/, true /PABOOST Enable/, BAND /long BAND/);
LoRa.setPins(csPin, resetPin, irqPin);
LoRa.onReceive(onReceive);
LoRa.receive();
for (int ii = 0; ii < FIXEDTXCOUNT; ii++)
{
NodeID_Flag[ii] = 0;
}
Serial.println(ssid);
// WiFi.begin(ssid, password);
// while (WiFi.status() != WL_CONNECTED) {
// delay(500);
// Serial.print(".");
// }
Serial.println("");
Serial.println(“WiFi connected”);
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
StaticJsonDocument<400> DeserializeReceive;
StaticJsonDocument<1600> doc;
JsonObject Central = doc.createNestedObject(“Central node”);
JsonObject Data = Central.createNestedObject(“Data”);
void loop()
{
if ((millis() - lastSendTime > interval) || flagPacketProcessed == 1)
{
destination = destination + 1;
String message = String (destination); // send a message
if (destination <= 8)
{ sendMessage(message);
Serial.println("Sending " + message);
}
lastSendTime = millis(); // timestamp the message
// interval = 3000;
flagPacketProcessed = 0; //flag set so that no new data is sent till a packet is received
// interval = 5000;
if (destination > 9)
{
destination = 0;
}
LoRa.receive(); // go back into receive mode
}
Central[“id”] = Central_ID;
if (flagDataAvailable == 1)
{
String dataReceivedCopy = dataReceived;
Central[“id”] = Central_ID;
//////////////////////////////////////////////////////////////////
/Deserialize incoming data to check Node ID/
//////////////////////////////////////////////////////////////////
DeserializationError error1 = deserializeJson(DeserializeReceive, dataReceived);
// Test if parsing succeeds.
if (error1) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error1.c_str());
return;
}
/////////////////////////////////////////////////////////
/*Extract Node ID and make object key with same name */
////////////////////////////////////////////////////////
char buf[50];
String b = "Node";
long testID = DeserializeReceive["NODE_ID"];
sprintf(buf, "%lu", testID);
String a = b + buf;
Data[a] = serialized(dataReceivedCopy);
/////////////////////////////////////////////////////////
/* raise flags for packets from received nodes */
/////////////////////////////////////////////////////////
if (testID >= 0)
{
NodeID_Flag[testID] = 1;
}
flagPacketProcessed = 1;
flagDataAvailable = 0;
}
/***********************************************************************
counter to check send message/destination counts
***********************************************************************/
if (destination == 9)
{ ///////////////////////////////////////////////////////////////
// embedd entries for data from non receiving nodes //
///////////////////////////////////////////////////////////////
for (int ii = 1; ii < FIXEDTXCOUNT; ii++)
{
if (NodeID_Flag[ii] == 0)
{ String d = “Node” + String(ii);
Data[d] = “\0”;
}
}
///////////////////////////////////////////////////////////////
// data from central Node //
//////////////////////////////////////////////////////////////
JsonObject CentralNode = Data.createNestedObject(“Central”);
CentralNode[“Node_ID”] = 0;
CentralNode[“Temperature”] = dht.readTemperature();
CentralNode[“Humidity”] = dht.readHumidity();
CentralNode[“Smoke”] = digitalRead(4);
CentralNode[“Rain”] = 1;
////////////////////////////////////////////////////////////////////////////
// data from special sensors at central node to be duplicated for all Node /
////////////////////////////////////////////////////////////////////////////
JsonObject Combined = Data.createNestedObject("Combined");
Combined["CO2"] = 667;
Combined["PM 2.5"] = 876;
Combined["PM 10"] = 343;
Combined["NO2"] = 745;
Combined["NH3"] = 233;
Combined["CO"] = 988;
Combined["Wind Direction"] = "NW"; //
// char dir[8]={"NW","N","NE","E","SE","S","SW',"W"}
Combined["Wind Speed"] = 343;
String wifidata = "";
serializeJson(doc, wifidata); //Final Json to be sent
Serial.println(wifidata);
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(host);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String url = "&value=";
url += wifidata;
Serial.print("Requesting URL: ");
Serial.println(url);
int httpResponseCode = http.POST(url);
if (httpResponseCode > 0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode); }
// Free resources
http.end();
}
else {
Serial.println("WiFi Disconnected");
}
//Send an HTTP POST request every 3 seconds
// delay(60000);
for (int ii = 1; ii < FIXEDTXCOUNT; ii++) // Clear all Flags for nodes
{
NodeID_Flag[ii] = 0;
}
doc.clear();
//clear JsonDocument else data will be repeated
JsonObject Central = doc.createNestedObject("Central node");
JsonObject Data = Central.createNestedObject("Data");
flagPacketProcessed = 1;
}
}
void sendMessage(String outgoing)
{
LoRa.beginPacket(); // start packet
LoRa.write(destination); // add destination address
LoRa.write(localAddress); // add sender address
LoRa.write(outgoing.length()); // add payload length
LoRa.print(outgoing); // add payload
LoRa.endPacket(); // finish packet and send it
}
void onReceive(int packetSize)
{
if (packetSize == 0) return; // if there’s no packet, return
// read packet header bytes:
int recipient = LoRa.read(); // recipient address
byte sender = LoRa.read(); // sender address
byte incomingLength = LoRa.read(); // incoming msg length
String incoming = “”; // payload of packet
while (LoRa.available()) // can’t use readString() in callback
{
incoming += (char)LoRa.read(); // add bytes one by one
}
if (incomingLength != incoming.length()) // check length for error
{
Serial.println(“error: message length does not match length”);
return; // skip rest of function
}
// if the recipient isn’t this device or broadcast,
if (recipient != localAddress || sender != destination)
{
Serial.println(“This message is not for me.”);
return; // skip rest of function
}
// if message is for this device, or broadcast, print details:
Serial.println(“Received from: 0x” + String(sender, HEX));
Serial.println(“Sent to: 0x” + String(recipient, HEX));
Serial.println("Message length: " + String(incomingLength));
Serial.println("Message: " + incoming);
Serial.println("RSSI: " + String(LoRa.packetRssi()));
Serial.println("Snr: " + String(LoRa.packetSnr()));
Serial.println();
flagDataAvailable = 1;
dataReceived = incoming;
}
Tx code :
#include “heltec.h”
#include <ArduinoJson.h>
#define BAND 433E6 //you can set band here directly,e.g. 868E6,915E6
#include “DHT.h”
#define DHTPIN 22
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
byte localAddress = 1; // address of this device
byte destination = 0; // destination to send to
const int csPin = 18; // LoRa radio chip select
const int resetPin = 14; // LoRa radio reset
const int irqPin = 26;
boolean dataAvailableFlag=0;
void setup()
{
//WIFI Kit series V1 not support Vext control
Heltec.begin(true /DisplayEnable Enable/, true /Heltec.LoRa Disable/, true /Serial Enable/, true /PABOOST Enable/, BAND /long BAND/);
Serial.begin(9600); // initialize serial
pinMode(4,INPUT);
dht.begin();
LoRa.setPins(csPin, resetPin, irqPin);
LoRa.onReceive(onReceive);
LoRa.receive();
}
void loop()
{
if (dataAvailableFlag==1)
{
StaticJsonDocument<200>doc;
String testJson1;
doc[“NODE_ID”] =localAddress;
doc[“Temperature”] = dht.readTemperature();
doc[“Humidity”] = dht.readHumidity();
doc[“Smoke”] = digitalRead(4);
doc[“Rain”] = “0”;
serializeJson(doc, testJson1);
sendMessage(testJson1);
Serial.println("Sending " + testJson1);
localAddress=localAddress+1;
if (localAddress>8)
{localAddress=1;}
dataAvailableFlag=0;
LoRa.receive();
}
}
void sendMessage(String outgoing)
{
LoRa.beginPacket(); // start packet
LoRa.write(destination); // add destination address
LoRa.write(localAddress); // add sender address
LoRa.write(outgoing.length()); // add payload length
LoRa.print(outgoing); // add payload
LoRa.endPacket(); // finish packet and send it
}
void onReceive(int packetSize)
{
if (packetSize == 0)
{return ; // if there’s no packet, return
}
// read packet header bytes:
byte recipient = LoRa.read(); // recipient address
byte sender = LoRa.read(); // sender address
byte incomingLength = LoRa.read(); // incoming msg length
String incoming = “”; // payload of packet
while (LoRa.available()) // can’t use readString() in callback
{
incoming += (char)LoRa.read(); // add bytes one by one
}
// if the recipient isn’t this device or broadcast,
if (recipient != localAddress or sender != destination)
{
Serial.println(“This message is not for me.”);
return ; // skip rest of function
}
if (incomingLength != incoming.length()) // check length for error
{
Serial.println(“error: message length does not match length”);
return; // skip rest of function
}
// if message is for this device, or broadcast, print details:
Serial.println(“Received from: 0x” + String(sender, HEX));
Serial.println(“Sent to: 0x” + String(recipient, HEX));
Serial.println("Message length: " + String(incomingLength));
Serial.println("Message: " + incoming);
Serial.println("RSSI: " + String(LoRa.packetRssi()));
Serial.println("Snr: " + String(LoRa.packetSnr()));
Serial.println();
dataAvailableFlag=1;
}