how to extract text, int and float from a string with all these?

String LoRaData contains Counter: 579 Data1: 579.55 Data2: 579.55 with RSSI -28

How do I extract the integer and float values?

Read up on strtok() it'll bust up the string for you into "chunks". Then you can, checking the chunks, see what they are. IE The chunk after the "Data2:" chunk will be its value.

That should get you started anyway.

-jim lee

Have a look at the parse example in Serial Input Basics. It extracts a string, an int and a float from a message

...R

Or as it is probably well formatted and always the same, sscanf() can probably make your life easy (esp. if you are on an esp32 to parse a float).

Many thanks to all of you for your excellent replies; I will try them all out today.
Kind regards,
Erik

here is a quick example with sscanf() if you are on an ESP architecture (on AVR platforms sscanf () does not know how to parse a float)

char loraBuffer[100];

bool receiveLora()
{
  // fake reception
  strcpy(loraBuffer, "Counter: 579 Data1: 123.456 Data2: 78.9 with RSSI -28");
  return true;
}

void setup() {
  Serial.begin(115200);
  if (receiveLora()) {
    long counter, rssi;
    float data1, data2;
    int n = sscanf(loraBuffer, "Counter:%ld Data1:%f Data2:%f with RSSI%ld", &counter, &data1, &data2, &rssi);
    if (n == 4) {
      Serial.print(F("Counter = ")); Serial.println(counter);
      Serial.print(F("Data1 = ")); Serial.println(data1, 4);  // 4 decimal digits, just to show it's a float
      Serial.print(F("Data2 = ")); Serial.println(data2);     // defaults to 2 decimal digits otherwise
      Serial.print(F("RSSI = ")); Serial.println(rssi);
    } else {
      Serial.print(F("Error parsing buffer, could only decode "));
      Serial.print(n);
      Serial.println(F(" parameter(s)."));
    }
  }
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

[color=purple]
Counter = 579
Data1 = 123.4560
Data2 = 78.90
RSSI = -28
[/color]

which matches what was put in the buffer

J-M-L:
here is a quick example with sscanf() if you are on an ESP architecture (on AVR platforms sscanf () does not know how to parse a float)

(...)

Thanks, a lot, but I need it to work on AVR, and on ESP8266 (may I guess this would be identical to ESP32 for your proposal?).

Robin2:
Have a look at the parse example in Serial Input Basics. It extracts a string, an int and a float from a message

...R

Thanks for that suggestion. I run however in the issue that the SandeepMistry LORA library there already is an instruction LoRa.parsePacket() and Lora.readString.
The problem I run into is that when I translate the statements in example 5 toward this LORA setup, then when executing recvWithStartEndMarkers() I need to know the size ndx of the array. And I do not know that size because the library already has read the entire received string into a string variable (example: String LoRaData = LoRa.readString() ).
So I made an attempt at both TX and RX: see below. I used index size 64. It compiles, but I am not sure if I correctly apply the concept from example 5 into a LORA setup (using the SandeepMistry library).
TX

/* Originally from LORA library examples

   Adapted from: https://www.electronics-lab.com/project/introduction-lora-send-data-two-arduino-using-lora/
   Adapted from: https://forum.arduino.cc/index.php?topic=396450.0

  LoRa aansluitingen: Arduino en ESP8266
            1. Arduino:           2. ESP8266
  MOSI            11             13 declare as output; nog te inverteren
  MISO            12             12
  SCK             13             14 declare as output; nog te inverteren
  NSS             10             15 declare as output; nog te inverteren
*
*
*Packet zend formaat: < text: ,int ,float ,float >
*
*
*
*/

#include <SPI.h>
#include <LoRa.h>
// #include <math.h>
float x = 0.5;
int counter;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Sender");

  while (!LoRa.begin(868E6)) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("LoRa Initializing OK!");

}

void loop() {
  Serial.print("Sending packet: ");
  Serial.println(x + counter);

  // send packet
  LoRa.beginPacket();
  LoRa.print("< Counter: ,");
  LoRa.print(counter);
  LoRa.print(", ");
  LoRa.print(x + counter);
  LoRa.print(", ");
  LoRa.print(x + counter + 1.0);
  LoRa.print(" >");
  LoRa.endPacket();

  counter++;

  delay(5000);
}

The transmitter message contains < at the start, one text, one integer, two floats, and a > at the message end.

And the RX program:

/* Originally from LORA library examples
   Convert string to float: https://forum.arduino.cc/index.php?topic=179666.0
   Example:
     String inData;
     char char1[8];
     float float 1;
     .
     .
     inData.toCharArray(char1, inData.length() +1);
     float1 = atof(char1);
   end of example

   Adapted from: https://www.electronics-lab.com/project/introduction-lora-send-data-two-arduino-using-lora/
   Adapted from: https://forum.arduino.cc/index.php?topic=396450.0

  LoRa aansluitingen: Arduino en ESP8266
            1. Arduino:           2. ESP8266
  MOSI            11             13 declare as output; nog te inverteren
  MISO            12             12
  SCK             13             14 declare as output; nog te inverteren
  NSS             10             15 declare as output; nog te inverteren


*/

#include <SPI.h>
#include <LoRa.h>

const byte numChars = 64;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
// variables to hold the parsed data
char message1FromPC[numChars] = {0};
char message2FromPC[numChars] = {0};
char message3FromPC[numChars] = {0};
int integer1FromPC = 0;
int integer2FromPC = 0;
float float1FromPC = 0.0;
float float2FromPC = 0.0;
boolean newData = false;

//============

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Receiver");

  while (!LoRa.begin(868E6)) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("LoRa Initializing OK!");
}

//============

void loop() {
  // try to parse packet
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    showParsedData();
    newData = false;

    // print RSSI of packet
    Serial.print(" with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

//============

void showParsedData() {
  Serial.print("Message ");
  Serial.println(message1FromPC);
  Serial.print("Integer ");
  Serial.println(integer1FromPC);
  Serial.print("Float ");
  Serial.println(float1FromPC);
}

//============

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(message1FromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integer1FromPC = atoi(strtokIndx);     // convert this part to an integer



  strtokIndx = strtok(NULL, ",");
  float1FromPC = atof(strtokIndx);     // convert this part to a float
}

//============

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    // Serial.print("Received packet '");
    String LoRaData;
    // read packet
    while (LoRa.available() > 0 && newData == false) {
      LoRaData = LoRa.readString();
      //  Serial.print(LoRaData); // debug printout

      while (LoRa.available() > 0 && newData == false) {

        rc = LoRa.read();

        if (recvInProgress == true) {
          if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
              ndx = numChars - 1;
            }
          }
          else {
            receivedChars[ndx] = '\0'; // terminate the string
            recvInProgress = false;
            ndx = 0;
            newData = true;
          }
        }

        else if (rc == startMarker) {
          recvInProgress = true;
        }
      }
    }
  }
}

brice3010:
then when executing recvWithStartEndMarkers() I need to know the size ndx of the array.

You should probably use recvWithEndMarker() which uses a linefeed to determine the end of the message.

However the purpose of my reference to the parse example was for you to study the parsing code rather than the receiving code.

...R

brice3010:
Thanks, a lot, but I need it to work on AVR, and on ESP8266 (may I guess this would be identical to ESP32 for your proposal?).

ESP8266 would work fine as there is enough program memory to accommodate for the full sscanf() code. On AVR they decided that float would not be handled in the standard version so this code would fail.

You will need to atof() which requires to have the pointer at the right starting point, which is easy enough since you know you have "Data1: " or "Data2: " just before. So you can use strstr() to find the pointer to that substring and then parse with strtof () from 7 bytes further.

something like this:

char loraBuffer[100];

bool receiveLora()
{
  // fake reception
  strcpy(loraBuffer, "Counter: 579 Data1: 123.456 Data2: 78.9 with RSSI -28");
  return true;
}

void setup() {
  Serial.begin(115200);
  if (receiveLora()) {
    long counter, rssi;
    float data1, data2;
    char *ptr;

    ptr = strstr(loraBuffer, "Counter:");
    if (ptr) {
      counter = atol(ptr + strlen("Counter:"));
      Serial.print(F("Counter = ")); Serial.println(counter);
    }

    ptr = strstr(loraBuffer, "Data1:");
    if (ptr) {
      data1 = atof(ptr + strlen("Data1:"));
      Serial.print(F("Data1 = ")); Serial.println(data1, 4);  // 4 decimal digits, just to show it's a float
    }

    ptr = strstr(loraBuffer, "Data2:");
    if (ptr) {
      data2 = atof(ptr + strlen("Data2:"));
      Serial.print(F("Data2 = ")); Serial.println(data2);  // 2 decimals by default
    }

    ptr = strstr(loraBuffer, "RSSI");
    if (ptr) {
      rssi = atol(ptr + strlen("RSSI"));
      Serial.print(F("RSSI = ")); Serial.println(rssi);
    }
  }
}

void loop() {}