Difficulty using the substring function

idahowalker thanks.
I'll check that.

1 Like

I don't think the code of post 1 etc is using the Sigfox.h library where read() is called in a loop to read the next byte

int SIGFOXClass::read() {

but some higher level library (which probably uses Sigfox.h) which returns the 8 bytes of data as a String, e.g. RX=7B FF 2C FF 2C FF FF 7D.
What library is being used in the code of post 1?
upload the complete code?

https://github.com/Thinxtra/Xkit-Sample

I've been using this example

OK a pointer to a character array; the number of bytes in that array is specified by RecvMsg -> len. What do you get when you print RecvMsg -> len?

#include <WISOL.h>              //  
#include <Tsensors.h>          //
#include <Wire.h>             //
#include <math.h>              //
#include <SimpleTimer.h>       //
#include <avr/wdt.h>             //
#include <stdio.h>
//
Isigfox *Isigfox = new WISOL();       //
Tsensors *tSensors = new Tsensors();  //

I get a sequence of 3 and 2
Trash1

This is like pulling teeth

Have you posted your full sketch as requested in the first reply to your original post ?

If so, then I missed it

No, I haven't posted yet. I'm putting it in now. Just a minute

/*
  XKIT_WISOL_SIGFOX_V17 13FEB2023 - IJC PVM VERSION
  Version 1.7 
  DOWNLINK: 7B | FF | 2C | FF | 2C | FF FF   | 7D
            {  | HZ |  , | AL |  , | TIME TX | }

  UPLINK:   4E FF FF | 2C | 44 | FF  | 2C | 42 | FF   | 2C | 41 | FF
             N   ID  | ,  | D  | DIS | ,  | B  | BAT  | ,  | A  | ALA
*********************************************************************************************************************************  
*/
#include <WISOL.h>              // OK *
#include <Tsensors.h>           //
#include <Wire.h>               //
#include <math.h>               //
#include <SimpleTimer.h>        //
#include <avr/wdt.h>            //
#include <stdio.h>
//
Isigfox *Isigfox = new WISOL();       //
Tsensors *tSensors = new Tsensors();  // 
SimpleTimer timer;
int watchdogCounter;
uint8_t buttonCounter;
uint8_t PublicModeSF;
uint8_t stateLED;
uint8_t ledCounter;
const uint8_t buttonPin = A1;
const int redLED = 6;
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// VAR & CONSTANTS FOR DOWNLINK                 // Payload > {FF,FF,FF FF}
const byte numChars = 8;                        // 
char receivedChars[numChars];                   // HazardZone: 1-255cm AlarmAck: 0-1  TimeToTX: 1-65535min
char tempChars[numChars];                       // temporary array for use when parsing
boolean newData = false;                        // 
char idFromServer[numChars] = {0};              // variables that arrives from SERVER [to hold the parsed data]         

int hazardZoneLimit = 0;                        // Hazard Zone Parameter - default 20cm (200mm)                         - Hazard zone var
int alarmAck = 0;                               // Alarm acknoledge 0 - do nothing; 1 - unlatch flag of alarm           - Alarm acknowledgment var 
int timeFromServer = 1;                         // time from Kore to the next uplink in minutes - Range 1 to 65535min   - Transmission time var

String buffTrans;                               //  = {"7B FF 2C FF 2C FF FF 7D"};     // Buffer of transition
String hazardZone, alAck, tTTx;
String bufTest;
//
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
uint8_t n = 78;
uint8_t d = 68;
uint8_t b = 66;
uint8_t a = 65;
uint8_t comma = 44;
uint16_t varID = 0;
uint8_t varDistance = 0;
uint8_t varBatt = 0;
uint8_t varAlarm = 0;
//
typedef union{
    uint16_t number;
    uint8_t bytes[2];
} UINT16id_t;
//---------------------------------------------------------------------------------------------------------------------------
void setup() {                                // SETUP ***********
  Wire.begin();
  Wire.setClock(100000);
  Serial.begin(9600);
// Init watchdog timer
  watchdogSetup();                         // 
  watchdogCounter = 0;
// WISOL test
  Serial.println("");                       // Make a clean restart
  delay(1000);
  PublicModeSF = 0;
  Isigfox->initSigfox();
  Isigfox->testComms();
  GetDeviceID();                            //
// Init sensors on Thinxtra Module
  tSensors->initSensors();
  tSensors->setReed(reedIR);
  buttonCounter = 0;
  tSensors->setButton(buttonIR);
// Init LED
  stateLED = 0;
  ledCounter = 0;
  unsigned long sendInterval = 600000;          // Init timer to send a Sigfox message every 10 minutes 
  timer.setInterval(sendInterval, timeIR);
  Serial.println("");                                                         // Make a clean start
  delay(1000);
}                                         //.................. end Setup ...........................
//---------------------------------------------------------------------------------------------------------------------------
void loop() {                             // MAIN LOOP ****
//
    varID = 65535;
    varDistance = 255;
    varBatt = 255;
    varAlarm = 255;
//
  timer.run();
  wdt_reset();
  watchdogCounter = 0;
}                                       //.................. end loop ...........................
//------------------------- PAYLOAD ------------------------------------------------------------  
//
void Send_Sensors(uint8_t n, uint8_t d, uint8_t b, uint8_t a, uint8_t comma, uint16_t varID, uint8_t varDistance, uint8_t varBatt, uint8_t varAlarm){
  UINT16id_t iD;
       iD.number = varID;                                                                                                          
        Serial.print("ID [n]: "); Serial.println(varID);                                                                                                           
        Serial.print("Distance [cm]: "); Serial.println(varDistance);                                                                                                          
        Serial.print("Battery Level [V]: "); Serial.println(varBatt);
        Serial.print("Alarm Code: "); Serial.println(varAlarm);
//
  const uint8_t payloadSize = 12;                                     //in bytes
  uint8_t buf_str[payloadSize];

  buf_str[0] = n;
  buf_str[1] = iD.bytes[1];
  buf_str[2] = iD.bytes[0];
  buf_str[3] = comma;
  buf_str[4] = d;
  buf_str[5] = varDistance;
  buf_str[6] = comma;
  buf_str[7] = b;
  buf_str[8] = varBatt;
  buf_str[9] = comma;
  buf_str[10] = a;                                            
  buf_str[11] = varAlarm;                                            
//
  Send_Pload(buf_str, payloadSize);                               //
}
//---------------------------------------------------------------------------------------------------------------------------  
void reedIR(){
  Serial.println("Reed");
                           //  timer.setTimeout(50, Send_Sensors);    // send a Sigfox message after get out IRS I don't need
}
//---------------------------------------------------------------------------------------------------------------------------  
void buttonIR(){
  if (buttonCounter==0) {
    timer.setTimeout(500, checkLongPress);                        // check long click after 0.5s
  }
}
//---------------------------------------------------------------------------------------------------------------------------  
void checkLongPress() {
  buttonCounter++;
  if ((buttonCounter < 4)) {
    if (digitalRead(buttonPin) == 1) {
      Serial.println("Short Press");
      Send_Sensors (n, d, b, a, comma, varID, varDistance, varBatt, varAlarm);   //
      buttonCounter = 0;
    } else {
      timer.setTimeout(500, checkLongPress);                                      // check long click after 0.5s
    }
  } else {
    Serial.println("Long Press");
    Serial.print ("Hazard Zone:" );
    Serial.println (hazardZoneLimit);
    Serial.print ("Alarm Ack:" );
    Serial.println (alarmAck);
    Serial.print ("Time to TX:" );
    Serial.println (timeFromServer);
//    
    BlinkLED();
    pinMode(redLED, OUTPUT);
    buttonCounter = 0;
  }
}
//-----------------------------------------------------------------------------------------------------------------------------
void BlinkLED() {
  ledCounter++;
  if (ledCounter<=6) {
    if (stateLED == 0){
      digitalWrite(redLED, HIGH);
      stateLED = 1;
      timer.setTimeout(200, BlinkLED);
    } else {
      digitalWrite(redLED, LOW);
      stateLED = 0;
      timer.setTimeout(200, BlinkLED);
    }
  } else {
    pinMode(redLED, INPUT);
    ledCounter = 0;
  }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void timeIR(){                                                                        // Send payload using preset time
  Serial.println("Sending for the Time");
    Send_Sensors (n, d, b, a, comma, varID, varDistance, varBatt, varAlarm);          //  Send_Sensors(varID,varDistance,varBatt,varAlarm);
}
//
//*************************************************************************************************************************************************************************************  
void getDLMsg(){                                   // Sigfox Downlink Payload *
  recvMsg *RecvMsg;
  int result;

  RecvMsg = (recvMsg *)malloc(sizeof(recvMsg));
  result = Isigfox->getdownlinkMsg(RecvMsg);
  for (int i=0; i<RecvMsg->len; i++){
                                                   // Downlink string example RX=7B FF 2C FF 2C FF FF 7D
    buffTrans = (RecvMsg->inData[i]);              //                            {  FF ,  FF  , FF FF  }
    Serial.print (buffTrans);                      //                          {HazardZone, Alarm ack, Time to TX}
   }
     parseData();
    Serial.println ("");
    free(RecvMsg);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void parseData() {                                // split the data into its parts
//
    BlinkLED();
    pinMode(redLED, OUTPUT);
//
//  String rx = (buffTrans);
//  int d[8]={0};
//  sscanf(rx.c_str(),"RX=%2x%2x%2x%2x%2x%2x%2x%2x",&d[0],&d[1],&d[2],&d[3],&d[4],&d[5],&d[6],&d[7]);
//  for(int i=0;i<8;i++) {
//  Serial.print(d[i],HEX);
//  Serial.print(rx);
// }

//    
//    hazardZone  = buffTrans.substring (6,8);
//    alAck       = buffTrans.substring (12,14);
//    tTTx        = buffTrans.substring (18,23);

//                Serial.print ("Hazard Zone: ");  // Only for test. The data will be used in another part of the code
//                Serial.println (hazardZone);
//                Serial.print ("Alarm Ack: ");
//                Serial.println (alAck);
//                Serial.print ("Time to TX: ");
//                Serial.println (tTTx);
}

//      hazardZoneLimit = atoi(hazardZone.c_str());
//       Serial.print ("Hazard Zone: ");
//       Serial.println (hazardZoneLimit);
//       Serial.println (" ");
                                                
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
void Send_Pload(uint8_t *sendData, const uint8_t len){        //
  recvMsg *RecvMsg;
  RecvMsg = (recvMsg *)malloc(sizeof(recvMsg));
  Isigfox->sendPayload(sendData, len, 0, RecvMsg);            //  
  for (int i = 0; i < RecvMsg->len; i++) {
    Serial.print(RecvMsg->inData[i]);
  }
  Serial.println("Enviou a mensagem para Backend");
  free(RecvMsg);
//
  Isigfox->sendPayload(sendData, len, 1);                   // If want to get non-blocking downlink message, use the following block instead ++++++
  timer.setTimeout(46000, getDLMsg);                        // 
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
void GetDeviceID(){                                         // 
  recvMsg *RecvMsg;
  const char msg[] = "AT$I=10";
  RecvMsg = (recvMsg *)malloc(sizeof(recvMsg));
  Isigfox->sendMessage(msg, 7, RecvMsg);
    Serial.print("Device ID: ");
    for (int i=0; i<RecvMsg->len; i++){
      Serial.print(RecvMsg->inData[i]);
  }
  Serial.println("");
  free(RecvMsg);
}
//===========================================================================================================================================================================================
void watchdogSetup(void) {                              // Enable watchdog timer
  cli();                                                // disable all interrupts
  wdt_reset();                                          // reset the WDT timer
  
// Enter Watchdog Configuration mode:
// IF | IE | P3 | CE | E | P2 | P1 | P0
  WDTCSR |= B00011000;
  WDTCSR = B01110001;
  sei();
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
void watchdog_disable() {                                                   // Disable watchdog timer
  cli();                                                                    // disable all interrupts
  WDTCSR |= B00011000;
  WDTCSR = B00110001;
  sei();
}
ISR(WDT_vect)                                                               // Watchdog timer interrupt.
{
// ################### Include your code here - be careful not to use functions they may cause the interrupt to hang and prevent a reset. ###############################
  Serial.print("WD reset: ");
  Serial.println(watchdogCounter);
  watchdogCounter++;
  if (watchdogCounter == 20) {                                              // reset CPU after about 180 s

// Reset the CPU next time
// Enable WD reset
      cli();  // disable all interrupts
      WDTCSR |= B00011000;
      WDTCSR = B01111001;
      sei();
      wdt_reset();
  } else if (watchdogCounter < 8) {
    wdt_reset();
  }
}

It's 32, not alternating 3 and 2; and probably printed 32 times.

AT$SF ... ,1 is 32 characters.

But nowhere in your earlier posts was a mention of AT$SF :cry: And it does not seem to match the earlier text RX=7B FF 2C FF 2C FF FF 7D

The AT code to send the message to the backend server is AT$SF. In the case here, I send it twice to guarantee, but the second time I send it with the ending ,1 to ask the server to send me the previously established downlink string.

therefore the content of the payload that I send does not correspond to the values 7B FF 2C FF 2C FF FF 7D which is the value that I receive from the backen

Guys, I need to leave my lab now for a meeting and I'll be back later. I greatly appreciate your help.
Thank you very much!

And that is what you're interested in

What I actually wanted you to do was

  Serial.print(F("RecvMsg->len = "));
  Serial.println(RecvMsg->len);
  for (int i=0; i<RecvMsg->len; i++){
                                                   // Downlink string example RX=7B FF 2C FF 2C FF FF 7D
    buffTrans = (RecvMsg->inData[i]);              //                            {  FF ,  FF  , FF FF  }
    Serial.print (buffTrans);                      //                          {HazardZone, Alarm ack, Time to TX}
   }

I forgot to mention that you don't seem to get a String (capital S) nor that yopu receive a c-string (nul-terminated character array) but just an array of characters.
So (spaces added for clarity)

'R' 'X' '=' '7' 'B' 'F' 'F' '2' 'C' 'F' 'F' '2' 'C' 'F' 'F' 'F' ' F' '7' 'D'

You can create a String object and add the received characters one-by-one to it in the for-loop.

  String theData;
  Serial.print(F("RecvMsg->len = "));
  Serial.println(RecvMsg->len);
  for (int i=0; i<RecvMsg->len; i++){
                                                   // Downlink string example RX=7B FF 2C FF 2C FF FF 7D
    buffTrans = (RecvMsg->inData[i]);              //                            {  FF ,  FF  , FF FF  }
    Serial.print (buffTrans);                      //                          {HazardZone, Alarm ack, Time to TX}
    theData += (RecvMsg->inData[i]);
   }

You can in that case use the substring method.

Or use a character array that is one byte bigger than RecvMsg->len, fill it with '\0' and next add RecvMsg->inData[i]. In that case you can use strstr() to find the FF. It might be the better choice as you will not have the pitfalls of the String class.

I don't use Strings. I use char arrays with zero terminated text right in data. I address it with a pointer and process char by char.

if ( chr >= '0' && chr <= '9' ) 
{
  val = chr - '0';  // ASCII 0 is 48 is '0'. Text is numbers that print as symbols. 
}
else if ( chr >= 'A' && chr <= ''F' ) 
{
  val = 10 + chr - 'A';
}
else
{
  //not a number, maybe interpret RX= type identifiers here 
}

``'

PS if you're going to do trig, use pre-calculated tables where possible for speed, Arduino floats are generally slow, trig values get generated..v.v.slow.

Hi guys.
as would say Mr. Schwarzenegger "I'm back"
I saw that you posted some interesting stuff here.
Thank you very much.
Well, I think I'm going to capture a part of my dreams tonight.
I'll be testing these concepts and getting back to you.
Thanks.

Hi guys,
the problem was solved. See below:

//*************************************************************************************************************************************************************************************  
void getDLMsg(){                                   // Sigfox Downlink Payload *
  recvMsg *RecvMsg;
  int result;

  RecvMsg = (recvMsg *)malloc(sizeof(recvMsg));
  result = Isigfox->getdownlinkMsg(RecvMsg);

                                                  //  Serial.print(F("RecvMsg->len = "));  
                                                  //  Serial.println(RecvMsg->len);
    for (int i=0; i<RecvMsg->len; i++){
    buffTrans = (RecvMsg->inData[i]);               
    Serial.print (buffTrans);
    theData += (RecvMsg->inData[i]);
   }
     parseData();
    Serial.println ("");
    free(RecvMsg);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void parseData() {                                                          // split the data into its parts
    BlinkLED();
    pinMode(redLED, OUTPUT);
//    
                (theData.substring (10,12)).toCharArray(hazardZone,3);
                (theData.substring (16,18)).toCharArray(alAck,3);
                                                                           
                ttx2 = theData.substring (22,27);
                ttx2.replace(" ","");
                ttx2.toCharArray(tTTx,5);
                                                                  
                Serial.print ("Hazard Zone: ");  
                long transHZ = strtol(hazardZone,NULL,16);
                 Serial.println (transHZ);
             
                Serial.print ("Alarm Ack: ");
                long transAA = strtol(alAck,NULL,16);
                Serial.println (transAA);
                
                Serial.print ("Time to TX: ");
                long transTX = strtol(tTTx, NULL,16);
                Serial.println (transTX);
//
}     // --> end function 

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.