Particle.publish Particle.subscribe

Hello
At regular times the display shows values that are not real it almost seems that the Particle.subscribe procedure does not find the data in the cloud.

One photons, with a dht22 and the command:
void loop()
Particle.publish (“Temp”, String (t), PRIVATE, NO_ACK);
Particle.publish (“Umi”, String (h) + “%”, PRIVATE, NO_ACK); in the void loop


A Argon with a oled display (SSD1306) and the following command:
void setup()
Particle.subscribe (“Temp”, tempHandler, MY_DEVICES);
Particle.subscribe (“Umi”, umiHandler, MY_DEVICES);

void tempHandler (const char * event, const char * data)
{
Temp = atoi (date);
display.clearDisplay ();
display.setTextSize (1);
display.setTextColor (WHITE);
display.setCursor (0,0);
display.println (Time);
display.setCursor (0.20);
display.print (“Temp:”); display.println (Temp);}


void umiHandler (const char * event, const char * data)
{
Umi = atoi (date);
display.setCursor (0.30);
display.print (“Umi:”); display.println (Umi);
display.display ();
}

You are writing atoi(date) but the parameter you receive from the function call is data.
You should also not write display.println(Time) since Time is a device OS object and you shouldn’t reuse that variable name for anything else.

And another hint you definitly haven’t heard the first time: “Don’t use String, whenever you can avoid to” :wink:

BTW, since you are always publishing both readings at the same time, it would be better to package both readings in a single event.

For now thanks, I changed atoi (data) and replaced display.println (Time) with display.println (Ora).
Ora = Time.format ("% H:% M% d.% M.% Y")

The problem remains, now I have to commit to “it would be better to package both readings in a single event” spin my brain I’ll see if something comes out otherwise I’ll go back to ask the community for help.
Regards Valentino

Can you elaborate on this statement?

What are these regular intervals? Minutes, hours, days?
In what way are the values “not real”?

Also, Particle.subscribe() does not get triggered when there is no triggering event, but once it is triggered it will not need to “find” the data but the data is delivered to the function - meaning when the handler is called then definitely the data will be there too.

With regards to unifying the data into one event

publish

  char data[32];
  snprintf(data, sizeof(data), "temp:%d,umi:%d", t, h);
  Particle.publish("dhtData", data, PRIVATE, NO_ACK);

subscribe

  Particle.subscribe("dhtData", dataHandler, MY_DEVICES);
...
void dataHandler(const char *event, const char *data) {
  int t, h;

  // try parsing for two integers
  if (sscanf(data, "temp:%d,umi:%d", &t, &h) == 2) {
    // display your data
  }
}

Or you could use JSON format for the payload.

Hi @ScruffR
after the suggested changes the data are these, not legible, they should be decimals. As you can see, they change from time to time. Coming soon I try the format the json procedures.

Temp:1077333196
Umi:-1073741824
Temp:1077339750
Umi:1610612736
Temp:1077333196
Umi:-1073741824
Temp:1077333196
Umi:-1073741824
Temp:1077339750
Umi:1610612736
Temp:1077333196
Umi:-1073741824

I guess the datatype don’t match then.
Since you were using atoi() in your original code I deduced t and h should be int but if they were float or double that would explain what you’re seeing.

That’s why it’s always a good idea to provide all the relevant data and not let anything up to guessing :wink:

BTW, how does the data sent via Particle.publish() look like in console.particle.io?

For floating point values you’d do it like this

void loop() {
  static uint32_t ms = 0;
  if (millis() - ms < 1000) return;
  ms = millis();
  
  float t = 12.3;
  float h = 34.5;
  
  char data[32];
  snprintf(data, sizeof(data), "temp:%.1f,umi:%.1f", t, h);
  Particle.publish("dhtData", data, PRIVATE, NO_ACK);
}

void dataHandler(const char *event, const char *data) {
  digitalWrite(D7, !digitalRead(D7));
  char  sTemp[8];
  char  sHum[8];
  float t, h;

  // try parsing for two strings not containing comma (floats are not directly supporte)
  if (sscanf(data, "temp:%[^,],umi:%[^,]", sTemp, sHum) == 2) {
    t = atof(sTemp);
    h = atof(sHum);
    Serial.printlnf("Temp = %.1f, Hum = %.1f", t, h);
  }
}

Good morning @ScruffR
attached the result to the console.particle.io. The first is with my code, the second is with the one suggested by you, third result with particle.subscribe. I am also attaching the code as required (particle.pubish).
Regards Valentino

My code (publish)on console result (photon)
51.900002 %
21.400000

Your code (publish) console result (photon)
temp:1077293875,umi:1073741824

Result on Argon with particle.subscribe (your code)
Temp:1077287321
Umi:-1610612736
Temp:1077293875
Umi:1073741824
Temp:1077287321
Umi:-1610612736

// This #include statement was automatically added by the Particle IDE.
#include <PietteTech_DHT.h>

#define DHTTYPE  DHT22       // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN   D6         // Digital pin for communications

 /*
  * NOTE: Use of callback_wrapper has been deprecated
  */
  //declaration
  //void dht_wrapper(); // must be declared before the lib initialization
  
 // Lib instantiate
PietteTech_DHT DHT(DHTPIN, DHTTYPE);
int n;      // counter

//***Variabili temp e umi DHT22
double h = 0;
double t = 0;
//double f = 0;

// Orario
//String ora;

void setup()
{
  Serial.begin(9600);
Time.zone(+2);  
Particle.variable("Temp",t);
Particle.variable("Umi",h);        
  while (!Serial.available() && millis() < 30000) {
    	Serial.println("Press any key to start.");
    	Particle.process();
    	delay(1000);
  }
  Serial.println("DHT Simple program using DHT.acquireAndWait");
  Serial.print("LIB version: ");
  Serial.println(DHTLIB_VERSION);
  Serial.println("---------------");
  DHT.begin();
 }

/*
 * NOTE:  Use of callback_wrapper has been deprecated but left in this example
 * to confirm backwards compabibility.
 */
 // This wrapper is in charge of calling
 // must be defined like this for the lib work
 //void dht_wrapper() {
 //    DHT.isrCallback();
 //}

void loop()
{
Particle.connected();
  Serial.print("\n");
  Serial.print(n);
  Serial.print(": Retrieving information from sensor: ");
  Serial.println("Read sensor: ");
  DHT.acquireAndWait(1000); // wait up to 1 sec (default indefinitely)

  /*int result = DHT.acquireAndWait(1000); // wait up to 1 sec (default indefinitely)

  switch (result) {
  case DHTLIB_OK:
    Serial.println("OK");
    break;
  case DHTLIB_ERROR_CHECKSUM:
    Serial.println("Error\n\r\tChecksum error");
    break;
  case DHTLIB_ERROR_ISR_TIMEOUT:
    Serial.println("Error\n\r\tISR time out error");
    break;
  case DHTLIB_ERROR_RESPONSE_TIMEOUT:
    Serial.println("Error\n\r\tResponse time out error");
    break;
  case DHTLIB_ERROR_DATA_TIMEOUT:
    Serial.println("Error\n\r\tData time out error");
    break;
  case DHTLIB_ERROR_ACQUIRING:
    Serial.println("Error\n\r\tAcquiring");
    break;
  case DHTLIB_ERROR_DELTA:
    Serial.println("Error\n\r\tDelta time to small");
    break;
  case DHTLIB_ERROR_NOTSTARTED:
    Serial.println("Error\n\r\tNot started");
    break;
  default:
    Serial.println("Unknown error");
    break;
  }*/
  
  Serial.print("Humidity (%): ");
  h=DHT.getHumidity(), 2;
  Serial.println(DHT.getHumidity(), 2);

  Serial.print("Temperature (oC): ");
  t=DHT.getCelsius(), 2;
  Serial.println(DHT.getCelsius(), 2);
  n++;

// Mio codice
    //Particle.publish("Temp",String(t),PRIVATE,NO_ACK);
   // Particle.publish("Umi",String(h)+ " %",PRIVATE,NO_ACK);
        
    char data[32];
    snprintf(data, sizeof(data), "temp:%d,umi:%d", t, h);
    Particle.publish("dhtData", data, PRIVATE, NO_ACK);

//***    
    Serial.print("TempDHT: ");Serial.print(t);Serial.print(" ");Serial.print("Humid: );Serial.print(h);Serial.println("%");
    Serial.println("***");
    delay(2500);
}

You may have corrected the subscribe code, but your publish code is still taking the wrong datatype.
You need to correct that too.

This is the version meant for int

This would be the one needed for floating point types

Hello @ScruffR finally I was able to see concrete data. Without your your suggestions and help I would not have succeeded.
I enclose the important parts so that those who need them can find an answer.
Best Regards e Grazie Mille!

Role particle.publish

char data[32];
snprintf(data, sizeof(data), "temp:%f,umi:%f", t, h);
Particle.publish("dhtData", data, PRIVATE, NO_ACK);   
delay(500);

Role particle.subscribe display to a OLED SSD1306

void setup(){
Particle.subscribe("dhtData", dataHandler, MY_DEVICES);
}
void dataHandler(const char *event, const char *data) {
  char  sTemp[8];
  char  sHum[8];
  float t, h;

  // try parsing for two strings not containing comma (floats are not directly supporte)
  if (sscanf(data, "temp:%[^,],umi:%[^,]", sTemp, sHum) == 2) {
    t = atof(sTemp);
    h = atof(sHum);
     display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.print("Temp & Umi Rodifiesso");
    display.setCursor(0,20);
    display.println(Ora);
    display.println(" ");
    display.setCursor(0,30);
    display.print("Temp:");display.println(t);
    display.print("Umi:");display.println(h);
    display.display();
Serial.printlnf("Temp = %.1f, Hum = %.1f", t, h);
  }
}

Prego!

un punto in più

I’m pretty sure you can use printlnf() for display too ans since you are not using t & h anywhere else than to print the values, you can also drop the atof() and write it like this
e.g.

  display.printlnf("Temp: %s  \r\nUmi: %s", sTemp, sHum);

Or when you already send the text as you want it printed, you could drop sscanf() to and just write display.println(data).

Thanks I will treasure your suggestions same the last, I still have to add some text that will tell me the status of the humidifier fan that I control remotely. Now I have to assemble everything because these routines I needed for a remote command (via html) already working but without indications of temp and humidity.
Regards Valentino

1 Like