Exercises with commands particle.publish and particle.subscribe sscanf

Hello I continue with the exercises on the commands particle.publish and particle.subscribe.These exercises are for displaying text in the two commands. I was able to view on the console via the particle.publish, but I can’t find the right syntax for using the sscanf with the particle.subscribe command.
Attached is the skecht of the two commands

//Particle.publish
char *testo="Vale"; // se avessi messo const significa che la variabile non verra mai modificata
const char *EVENT_NAME = "Nome";
void setup() {
  Serial.begin(9600);
}
void loop() {
  char miamem[32];
  snprintf(miamem, sizeof(miamem), "%s", testo);
  Particle.publish(EVENT_NAME, miamem, PRIVATE);
  Serial.print("Nome: ");Serial.println(miamem);
  delay(2000);
}

Output on console:
Cattura

//Particle.subscribe
#include "Particle.h"
void setup(){
  Serial.begin(9600);
  Particle.subscribe("miamem", dataHandler, MY_DEVICES);
}
void loop() {
    //Serial.println("Prova subscribe");
    //delay(1000);
}

void dataHandler(const char *event, const char *data) {
   char *testo;
   if(sscanf(data,"%s",testo)){
        Serial.println(testo);
    }
}

sscanf() requires a place to put the string into, you are only providing a pointer that points who-knows-where but no buffer. You need to provide an array as I showed you in the example using floats.

But this sample is of very little use as you are taking the entire string you already have, why not stick with data as is? :wink:

Furthermore you are subscribing to miamem but publish an even Nome. Consequently the subscribe handler will not be triggered by your event as the filter does not match.
You need to subscribe to Nome in order to receive the event.

Hello thanks the suggestions to tell the truth I started with putting a character size of 8 in the char[] but seeing the error I made (Furthermore you are subscribing to miamem but publish an even Name) it didn’t work. I enclose the correct skecht as usual.
Regards Valentino

#include "Particle.h"
void setup(){
Serial.begin(9600);
Particle.subscribe("Nome", dataHandler, MY_DEVICES);
}
void loop() {
    Particle.connect();
    delay(1000);
}
void dataHandler(const char *event, const char *data) {
    char testo[16];
   if(sscanf(data,"%s",testo)){
    Serial.print("Nome: ");Serial.println(testo);
    Particle.publish("Nome: ", testo, PRIVATE);
    }
}

It’s always a good idea to have some unconditional feedback whether the event handler was called or not.

void dataHandler(const char *event, const char *data) {
  char testo[16];
  Serial.printlnf("%s: %s", event, data); // print incoming data   
  if(sscanf(data,"%15s", testo)) {        //  limit the length to 15 characters (plus on terminating '\0'
    Serial.printf("Nome: %s", testo);   
    Particle.publish("-Nome:", testo, PRIVATE); 
  }
}

You don’t (!) want to publish an event from the event handler that starts with the same string as you subscribed to otherwise your own even will keep triggering the event over and over.

And in order to understand what is happening (going wrong) in your code it would be good to attach the serial output and the console data of the entire interaction.

BTW, you also don’t want to call Particle.connect() over and over in loop().
And remove the delay(1000) too.

1 Like

Thanks ScruffR I implemented what was suggested, and everything works better, I put the Particle.connect () due to the photon being offline. But after corrections it stays connected.
Last question for concatenation you put
(temp:%. 1f, umi:%. 1f ", & t, & h) == 2) Does%. 1f mean 1 floating number?
and if I were to concatenate numbers and text (temp:%. 1f, umi:%. 1f, Name1:% s, Name2:% s ", & t, & h, & n1, & n2) == 4) I put for example == 4?
Thanks for the valuable suggestions
Valentino

the 1 after the dot/point means one decimal place (it's not allowed to have a space between the dot and the digit tho').

But you can find more about the variable place holders here
for output
http://www.cplusplus.com/reference/cstdio/printf/
for parsing
http://www.cplusplus.com/reference/cstdio/scanf/

For numeric datatypes you need to explicitly provide the pointer to the variable that should hold the result (hence the leading ampersand &) but for strings you typically already have a pointer so you are not using the ampersand there.

And as the scanf() documentation states the return value of that function is the number of fields that were successfully parsed (starting from the left up to the first unparsable field which will terminate the parsing).
Hence you are correct with your == 4

However, with parsing %s you need to take extra care to read all but no more than the data you want to read. After all the entire input data is a string, so it may be consumed entirely if you don't specify which characters should be consumed or must not be consumed. For that you'd use %[...] or %[^...] instead.

1 Like

Hello @ScruffR I’m sorry to have to ask for help again, I’ve searched the internet and a C book but something in the part SUBSCRIBE the sscanf syntax is incorrect.
I see the data with Serial.printlnf but unfortunately not after sscanf.
I attach both the publish part and the subscribe part.
Regards Valentino

// *** PUBLISH CONCATENATE TEM&UMI - TEXT ***
char *testoA="Vale"; // se avessi messo const significa che la variabile non verra mai modificata
char *testoB="Lore";
int t = 30;
int h = 40;
void setup() {
  Serial.begin(9600);
}
void loop() {
  char data[64];
  snprintf(data, sizeof(data), "temp:%d,umi:%d,NomeA:%s,NomeB:%s", t, h,testoA,testoB);
  Serial.print("Temp:");Serial.print(t);Serial.print(" ");Serial.print("Umi:");Serial.println(h);
  Serial.print("Nome1:");Serial.print(testoA);Serial.print(" ");Serial.print("Nome2:");Serial.println(testoB);
  Particle.publish("CONCATENATE",data, PRIVATE);
  delay(500);
}

Output on Particle console

temp:30,umi:40,NomeA:Vale,NomeB:Lore

Output on PuttY

Temp:30 Umi:40
Nome1:Vale Nome2:Lore
********************************************************
// *** SUBSCRIBE CONCATENATE TEMP&UMI - TEXT ***
//#include "Particle.h"
void setup(){
  Serial.begin(9600);
  Particle.subscribe("CONCATENATE", dataHandler, MY_DEVICES);
}
void loop() { }
void dataHandler(const char *event, const char *data) {
    Serial.printlnf("%s: %s", event, data); // print incoming data 
    int t,h;
    char *testoA;
    char *testoB;
    Particle.publish("-Nome:",data,PRIVATE);
    if(sscanf(data,"temp:%.1f,umi:%.1f,NomeA:%s,NomeB:%s",&t,&h,testoA,testoB) == 4){
        Serial.print("Temp :");Serial.println(t);Serial.print("Umi :");Serial.println(h);
        Serial.print("NomeA: ");Serial.println(testoA);Serial.print("NomeB: ");Serial.println(testoB);
        }
}

Output on Particle console with the command Particle.publish

temp:30,umi:40,NomeA:Vale,NomeB:Lore

Output on PuttY with command Serial.printlnf("%s: %s", event, data); // print incoming data

CONCATENATE: temp:30,umi:40,NomeA:Vale,NomeB:Lore
Output

Please, don't do this. It's a pain to read multi-instruction lines, especially when there are superior ways of printing formatted data (i.e. Serial.printlnf())

Also try to use the preformatted text feature image (Ctrl+Shift+C) for posting blocks of code.

Finally, the reason why you don't get any extra output is obviously due to the fact that the if() condition is not satisfied.
And the reason for that is what I meant with this above

Since your first string (%s) consumes all data - including ",NomeB:Lore" - the return value of sscanf() is only 3 but you are expecting 4 but there is no string left for the fourth variable to be filled with.
You either need to add a whitespace after Vale or parse for %[^,] (any non-whitespace character except comma ',') - you should know that one from the float example I provided you with in another thread a few days ago.

Good evening @ScruffR thanks for the answer now I have to concentrate and read carefully what you wrote.
A good evening Valentino

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