Parsing Lora Packet

Hello,

I am trying to parse a Lora package into 3 separate data points. The data comes in like this:

1000.0000000, 1000.000000, 12.34

where the data points represent longitude, latitude, altitude respectively. The data comes in as a string and I would like to separate the them into their own float values. I have tried sending them each on their own line and using getline() to put them into substrings then into floats but I have been unsuccessful. Could anyone please explain where I am going wrong.

Receiver parsing code:

#include "heltec.h" 
#include "images.h"
#include<iostream>
#include <string> 
using namespace std;
#define BAND    433E6  //you can set band here directly,e.g. 868E6,915E6
String rssi = "RSSI --";
String packSize = "--";
String packet, substr, slat, slon;
float lati, lon;

void LoRaData(){
  Heltec.display->clear();
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);
  Heltec.display->setFont(ArialMT_Plain_10);
  Heltec.display->drawString(0 , 15 , "Received "+ packSize + " bytes");
  Heltec.display->drawStringMaxWidth(0 , 26 , 128, packet);
  Heltec.display->drawString(0, 0, rssi);  
  Heltec.display->display();
}

void cbk(int packetSize) {
  packet ="";
  packSize = String(packetSize,DEC);
  for (int i = 0; i < packetSize; i++) { packet += (char) LoRa.read(); }
  rssi = "RSSI " + String(LoRa.packetRssi(), DEC) ;
  LoRaData();
}

void setup() { 
   //WIFI Kit series V1 not support Vext control
  Heltec.begin(true /*DisplayEnable Enable*/, true /*Heltec.Heltec.Heltec.LoRa Disable*/, true /*Serial Enable*/, true /*PABOOST Enable*/, BAND /*long BAND*/);
 
  Heltec.display->init();
  Heltec.display->flipScreenVertically();  
  Heltec.display->setFont(ArialMT_Plain_10);
  
  Heltec.display->drawString(0, 0, "Heltec.LoRa Initial success!");
  Heltec.display->drawString(0, 10, "Wait for incoming data...");
  Heltec.display->display();
  delay(1000);
  //LoRa.onReceive(cbk);
  LoRa.receive();
}

void loop() {
  int i = 0;
  int packetSize = LoRa.parsePacket();
  if (packetSize) { cbk(packetSize);  }
while(getline(packet, substr){
  if (i==0){
    slat = substr;
    Serial.println("slat=", slat)
    i++;
  } else if(i==1{
    slon=substr;
    Serial.println("slon=", slon)
    i++
  }else{
    salti = substr;
}
        
  }
          delay(100);
}

For this example I had the Data coming in as:

1000.000000
1000.000000
12.34

It is not separating the values into their respective strings properly.
Thank you.

Are you using an Arduino to transmit the packets? What does the TX side look like?

If you're TX is an Arduino, consider using a proven serial transfer library that will automatically handle all the necessary packetizing and parsing for you.

I am Using the Heltec ESP32 LoRa wifi v2 module. It Has its own Lora Library but unfortunately Nothing to parse it. Here is my transmitter code:

#include <heltec.h>
#include <SPI.h>
#include <SD.h>
#include <TinyGPS.h>
#include "FS.h"
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"

//SD Card
#define SD_CS 23
#define SD_SCK 17
#define SD_MOSI 12
#define SD_MISO 13
SPIClass sd_spi(HSPI);
Adafruit_BMP3XX bmp; // I2C

File main_folder; // initialize folder for saving
File dataFile; // initialize sd file
const int chipSelect = 10; // CS pin on sd card module
int prev_file_indx = 0; // used for file naming
String fileName = "000";

int ass=0;
  long lat, lon;
  float flat, flon;
  unsigned long age, date, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  char sz[32];
  bool newData= false;

HardwareSerial GPS_Serial(2);
float baseline;
float pres;
float alti;

#define BAND    433E6  //you can set band here directly,e.g. 868E6,915E6


void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
    file.close();
}





TinyGPS gps;

void setup() {
   Serial.begin(9600);
Heltec.begin(false /*DisplayEnable Enable*/, true /*Heltec.Heltec.Heltec.LoRa Disable*/, true /*Serial Enable*/, true /*PABOOST Enable*/, BAND /*long BAND*/);

  
sd_spi.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
delay(500);
if (!SD.begin(SD_CS, sd_spi))
  Serial.println("SD Card: mounting failed.");
else
  Serial.println("SD Card: mounted.");
  writeFile(SD, "/DATA.txt", "Date, Time, Lat, Lon, pressure, altitude\n");

   delay(1000);
   
  delay(1000);
    if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP3 sensor, check wiring!");
    while (1);
  } 
 bmp.setPressureOversampling(BMP3_OVERSAMPLING_32X);
 bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
 delay(500);
GPS_Serial.begin(9600, SERIAL_8N1, 4, 2);
}

void loop() {

  gps.f_get_position(&flat, &flon, &age);
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  sprintf(sz, "%02d/%02d/%02d, %02d:%02d:%02d", month, day, year, hour - 4, minute, second);
    while (GPS_Serial.available())
    {
      char c = GPS_Serial.read();
       //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  if (! bmp.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
pres = (bmp.pressure/100.0);
alti = (getaltitude());
appendFile(SD, "/DATA.txt");
Serial.print(alti);
Serial.print(" ");
Serial.print(pres);
LoRa.beginPacket();
LoRa.setTxPower(20,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print(flat,6);
LoRa.print(",");
LoRa.print(flon,6);
LoRa.print(",");
LoRa.println(alti);
LoRa.endPacket();
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

float getaltitude()
{
  
if(ass <=2){
  baseline = (bmp.pressure / 100);
  ass = ass+1;
}
  delay(500);
  float alti;

  double pressure = bmp.pressure / 100.0;

  alti = (3.28084 * (44330 * (1.0 - pow(pressure / baseline, 0.190394957))));

  return alti;
}
  
void appendFile(fs::FS &fs, const char * path){
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("Failed to open file for appending");
        return;
    }
if(file){
file.print(sz);
file.print(", ");
file.print(flat,6);
file.print(", ");
file.print(flon,6);
file.print(", ");
file.print(pres);
file.print(", ");
file.println(alti);

        Serial.println("Message appended");
    } else {
        Serial.println("Append failed");
    }
    file.close();
}

I will give the Serial Library a try. Thank you.

If the Lora library already packetizes and parses the packet, why not just access the bytes of the packet directly?

TBH, I've never used Lora modules, so somebody else might be more equipped to help you