Webhook response handler example

Hello

I created the following webhook response handler to increase reliability of the delivery of the messages sent by the Electrons. The electrons are connected to machines that can send critical data at any moment so the objective of tracking the responses is to guarantee that the info reached the destination server or else resend.

Appreciate if anyone could comment and critique.

@ScruffR: appreciate your review in light of the discussion in this post Issues with sleep - Need advice on troubleshooting ideas and the need to reduce the risk of heap fragmentation. Thanks in advance

I’ve taken out all non-related code or variable definitions to focus on the response handling. Hope it’s clear. First time posting code.

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

const int  reintentos = 2; // number of retries to send to cloud before data is stored in local memory. 
const int waitcloud = 5000; //time in ms to wait for Particle.connected
const int  espera_ack = 45*1000; //wait time in seconds to receive acknowledge from the webhook response

//variables dealing with the webhook response
boolean data_in_flight_svc = FALSE; //use to signal the main loop that there was data published to cloud
int last_message;
int retries = 0; //

void setup() {

Particle.subscribe(System.deviceID() +"/hook-response/pub", respuesta_servicio, MY_DEVICES);

//... a bunch of other pin mode and attachInterrupt definitions
Particle.connect();
}

void loop() {

if (StartServ){ //flag set True from ISR when machine is turned ON
      timestamp_on = Time.now(); //records time when machine is turned ON
      if(waitFor(Particle.connected,waitcloud)) { // waitcloud is a constant set to 4-5 seconds 
           publicar_machine_on();
        }
       else { // no cloud then retry in a few secs
          retries = 0;
          data_in_flight = TRUE;
          last_message = millis();
        }
      StartServ =FALSE;
}

if (millis() - last_message > espera_ack && data_in_flight){ //webhook response not received, retry again or quit after a number of retries 
    retries++;
    if (Particle.connected() && retries <= reintentos){
          publicar_machine_on();
        }
    else { // too many retries, quit retrying
      data_in_flight = FALSE;
      retries = 0;
    }    
} 

// other loop code

}

// publish data to cloud function
void publicar_machine_on(){
      char data[256];
      snprintf(data, sizeof(data), "{\"maq\":%i, \"hora\":%i000}",1, timestamp_on); //
      Particle.publish("pub_on",data,PRIVATE);
      data_in_flight = TRUE;
      last_message = millis();
}

// webhook responses handler.  
void respuesta_servicio(const char *event, const char *codigo) {

     int codigo_respuesta = atoi(codigo); // registers https response code. Looking for the success 201/200 codes

     char evento_recibido[100]; //using chars instead of strings to avoid heap fragmentation?
     strcpy (evento_recibido, event); //make a copy of the event data received
     char dispositivo[25],a[25],b[6],c[1]; //b stores the label of the published event
     
// publish events handled by this webhook response handler
     char key_1[] = "pubsvc";
     char key_2[] = "pubinc";
     char key_3[] = "pub_on";
     char key_4[] = "puboff";
     sscanf(evento_recibido, "%[^/]/%[^/]/%[^/]/%s",dispositivo,a,b,c);

 if (strcmp(b,key_3) == 0){
     if (codigo_respuesta == 201 || codigo_respuesta == 200) { 
          data_in_flight = FALSE;  //successful receipt - resets flag and retries counter.
          retries = 0;
       }
   }
//** There are 4-6 publish events handled by the same handler. only 1 shown above for this example but all handled similarly

} 

Thanks in advance for the review
btw… thanks @chipmc. Most of the logic above is based on your recommendations

One thing I’d have some extra look at is the sscanf() instruction.
Not sure whether the received string could break the boundaries, but the format string does not limit the number of characters that may get placed in your character arrays - especially the final %s should rather be a %c as that array is only one byte long.

Also I’d raher go with char evento_recibido[strlen(event)+1]. If for some reason the cloud should split up the webhook response into multiple parts you may end up with a longer event name than you’d anticipate.

Thank you!