# Set subscribe handler data as global

**URL:** https://community.particle.io/t/set-subscribe-handler-data-as-global/59099
**Category:** Cloud
**Tags:** photon
**Created:** [January 18, 2021, 2:15am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099 "2021-01-18T02:15:30Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 20, 2021, 10:59am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/22 "2021-01-20T10:59:05Z")

</div>

Ahh i see! So far no crash with a single subscribe used. Currently im trying to implement MQTT pub/sub to replace particle pub/sub but im facing issues connecting my localhost.  
It doesnt connect to 127.0.0.1;1883 !

How do I connect to localhost?

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 20, 2021, 11:38am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/23 "2021-01-20T11:38:07Z")

</div>

127.0.0.1 would refer to the Photon itself 😉

Your local MQTT broker has probably a 192.168.x.y or 10.0.0.x address which you should either get from the device running the broker or your router.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 21, 2021, 10:11am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/24 "2021-01-21T10:11:18Z")

</div>

Hi ScruffR, thanks! I managed to get MQTT to work using wifi hotspot. I also tidied up mode of my code using timers. I forgot to mention that I’m also sending data from particle.variable(ldr/temp/pressure) to HTML file.

 ![html1](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/3/6/3654726c880103f06ce38744e1c8f75405d4f119.png)  
After tidying up my code, the red SOS still occurs every 10seconds after code successfully flashes.

Update: I commented away timer4.start() yet the red SOS continues, I suspect the timer time length is causing this …

Q1. Should I run the auto crash detection and debug to fix the SOS?

Q2. Should I sync the timer time length on Device1 Timer3&4 same as Device2 Timer1&2? I’m not sure if I’m using timer correctly in both device codes.

Q3. I put my particle sub/pub handlers into timers hoping it would fix the red SOS since i expected timers to work in a sequential manner.  
Example:  
Timer timer1(1000L, pub\_ambience\_status);  
Timer timer2(5000L, blynkLDRdata);  
Timer timer3(5000L, subTemp);  
Timer timer4(1000L, subPress);

void setup(){  
timer1.start();  
timer2.start();  
timer3.start();  
timer4.start();  
}

timer1 (1s) → timer2 (5s) → timer3 (5s) → timer4 (1s) and repeat again

```
(timer1) (timer2) (timer3) (timer4)

```

0-------------1---------------6---------------11------------12

```
(timer1) (timer2) (timer3) (timer4)

```

12-----------13--------------18-------------23------------24

\<Device 1 Code\>

```auto
#include <DailyTimerSpark.h>
#include <blynk.h>

char auth[] = "HIDE";

int led3=D0; // Blynk Nightlight Control + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 
int ldranalogvalue=0; // Blynk Ambience Brightness Gauge

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting)
WidgetLCD lcd2(V3);

// Check ambience status every 30s
Timer timer1(1000L, pub_ambience_status);

// Blynk LDR Gauge
Timer timer2(5000L, blynkLDRdata);

// iot_C8 MQTT sub to temp and pressure data vals from D8 published temp and pressure readings
Timer timer3(5000L, subTemp);
Timer timer4(1000L, subPress);

void pub_ambience_status(){
       ldr_status = analogRead(ldr);
       Serial.println("Ambience Change");
       Serial.printlnf("LDR Status = %d", ldr_status);

    if (ldr_status <= 100){ // Modify this in class
        Particle.publish("ambience_C8", "Dark", PRIVATE);
        Serial.println("Ambience Status= Dark");
        Serial.println("Ambience Dark Request triggered");
    }
    
    else if (ldr_status >= 300){
        Particle.publish("ambience_C8", "Bright", PRIVATE);
        Serial.println("Ambience Status= Bright");
        Serial.println("Ambience Bright Request triggered");
    }
    
    else{
        Particle.publish("ambience_C8", "Dim", PUBLIC);
        Serial.println("Ambience Status= Dim");
        Serial.println("Ambience Dim Request triggered");
    }
}

void blynkLDRdata(){
   ldr_status = analogRead(ldr);
   Blynk.virtualWrite(V0, ldr_status);
}

void subTemp(){
   Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
   double temp_val = atof(data);
   Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

   char msg[32];
   snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
   lcd2.print(0, 0, msg);
}

void subPress(){
   Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
}

void myPressHandler(const char *event, const char *data){
   double press_val = atof(data);
   Serial.printlnf("Pressure Handler executed, %fPa", press_val);

   char msg[32];
   snprintf(msg, sizeof(msg), "%dPa %s", press_val, (press_val > 900) ? "High" : "Low");
   lcd2.print(0, 0, msg);
}

void setup(){
   
   // bLYNK LCD Time Display (Set Timezone to SG using +8)
   Time.zone(+8);  
   
   // Nightlight Toggle On/Off
   pinMode(led3, OUTPUT); 
   Particle.function("led",ledToggle);

   // HTML Ambience Brightness Gauge
   ldr_status=analogRead(ldr);
   Particle.variable("ldranalogvalue", ldr_status);
   
   Serial.begin(9600);
   while (!Serial);
   Serial.println("Serial is Running");
   
   Blynk.begin(auth); 
   
   timer1.start();
   timer2.start();
   timer3.start();
   timer4.start();
}

void loop(){                     
   
   Blynk.run();

   // Blynk LCD Display (Date + Greeting)
   DisplayTime();
   MorningDisplay();
   AfternoonDisplay();

}

int ledToggle(String command) {
   if (command=="on") {
       digitalWrite(led3,HIGH);
       Serial.print("HTML led3 ");
       Serial.println(command);
       return 1;
   }
   else if (command=="off") {
       digitalWrite(led3,LOW);
       Serial.print("HTML led3 ");
       Serial.println(command);
       return 0;
   }
   else if (command=="read") {
       return digitalRead(led3);
   }

   else {
       return -1;
   }
}

void DisplayTime(){

   lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
   lcd.print(0,1, (const char*)Time.format("%a %e %b"));
   delay(1000);
}

void MorningDisplay(){
   DailyTimer MorningTimer(6, 0, 11, 59, EVERY_DAY); // Fixed start time and end time
   if(MorningTimer.startTrigger()){
       lcd.print(0,1, "Good Morning!");
       delay(2000);
       
       MorningMsg();
       delay(1000);
   }
}

void AfternoonDisplay(){
   DailyTimer AfternoonTimer(12, 0, 17, 59, EVERY_DAY); // Fixed start time and end time
   if(AfternoonTimer.startTrigger()){
       lcd.print(0,1, "Good Afternoon! ");
       delay(1000);
       
       AfternoonMsg();
       delay(1000);
   }
}

void MorningMsg(){
   String text = "Time for Breakfast";
   int space=(strlen(text)-15); // Set no. of space for text to move
   for(int start=0; start<space; start++){ // Increment loop
       
       lcd.print(0,1, text.substring(start)); // substring func remove char of string via loop and prints continuously
       delay(1000);
   }
}

void AfternoonMsg(){
   String text = "Lunch Break "; // Spaces to avoid other text from overlapping
   lcd.print(0,1, text);   
   delay(1000);
}

```

\<Device 2 Code\>

```auto
#include <Adafruit_BMP280.h>
#include <blynk.h>

Adafruit_BMP280 bmp; 

char auth[] = "HIDE";  

double env_temp;
double env_Pressure;

// HTML Temp + Press Gage Data
double temp_reading;
double press_reading;

// Blynk Slider + Button
int led1 = D2;

Timer timer1(5000L, pubTemp);
Timer timer2(10000L, pubPress);

// iot_D8 Device MQTT subscribe to Ambience_C8
Timer timer3(10000L, subAmbience);

void pubTemp(){
   double t_temp = bmp.readTemperature();
   Serial.println("Temperature Request triggered");
   Particle.publish("temperature_D8", String(t_temp), PRIVATE);
}

void pubPress(){
   double t_Pressure = bmp.readPressure();
   Serial.println("Pressure Request triggered");
   Particle.publish("pressure_D8", String(t_Pressure), PRIVATE);
}

void subAmbience(){
   Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
   String ambience_status = String(data);
   Serial.println("Ambience Handler executed");
   Serial.println(ambience_status);

   if(ambience_status == "Dark"){
       digitalWrite(D2, HIGH);
       Serial.println("Led turns on");
   }
   else if(ambience_status == "Bright"){
       digitalWrite(D2, LOW);
       Serial.println("Led stays off");
   }
   else if(ambience_status == "Dim"){
       digitalWrite(D2, LOW);
       Serial.println("Led stays off");
   }
}

void setup() {
   
   pinMode(led1, OUTPUT);

   // HTML Temp and pressure gauge reading
   Particle.variable("temp", temp_reading);    
   Particle.variable("press", press_reading);    
   
   Blynk.begin(auth); 

   Serial.begin(9600);
   while (!Serial);
   Serial.println("Serial is Running");

   if (!bmp.begin()){
       Serial.println("Can't find the sensor BMP280");
   }
   
   timer1.start();
   timer2.start();
   timer3.start();
}

void loop() {
   Blynk.run();

   temp_reading = bmp.readTemperature();
   press_reading = bmp.readPressure();
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 21, 2021, 11:09am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/25 "2021-01-21T11:09:31Z")

</div>

> [@kannnyyy](#):
>
> I suspect the timer time length is causing this …

I doubt that. It's usually not helpful to jump to conclusions before having evidence for it.  
So yes to Q1.  
Q2 is a non-issue IMO although having multiple timers with the same cadence would rather suggest to do all the stuff in the same timer (if it has to be via timer at all is open for discussion).  
For Q3, no. your 1sec timers will fire 5 times in 5 seconds while your 5sec timers will fire only once. And in the long run you should _ **not** _ rely on the order of execution at all.

When using timers you need to be aware that the thread running these timers only has a very limited stack space and hence any heavy library calls (i.e. Blynk) may run the risk of overflowing the stack.

Typically when you get an SOS crash you also get a number of slow blinks after the first set of SOS blinks. The number of these blinks tells you more about the type of crash.  
If this is indeed a stack issue you'd see SOS+13.  
For that it's always good to _ **also** _ provide that information as early as possible in a discussion like this.

[https://docs.particle.io/tutorials/device-os/led/photon/#red-flash-sos](https://docs.particle.io/tutorials/device-os/led/photon/#red-flash-sos)

While Software Timers are a great tool for some things, they are not suitable for everything and in your case I don't see good reason for them.

I'd guess your initial SOS crash was of a different kind. That also shows that it is _ **not** _ advisable to considerably change code you still haven't fully debugged.  
Adding new features (in this case Software Timers) may well introduce _ **new** _ problems of its own and makes debugging much harder (is it still the old problem or a new one or a combination of the two).

BTW, why on earth have you got `subTemp()`, `subPress()` and `subAmbience` timers that keep subscribing to the same events over and over every few seconds?

About this

> [@kannnyyy](#):
>
> I’m also sending data from particle.variable(ldr/temp/pressure) to HTML file.

Since programming is a matter where preciseness is key I also want to be precise when describing things verbally 😉  
`Particle.variable()`s are _ **requested** _ not sent.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 1:46am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/26 "2021-01-22T01:46:52Z")

</div>

Hey ScruffR! My initial crash is indeed different from the current one is due to stack overflow.

 ![stackoverflow](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/4/6/464bf02782ca1635e7af14640a46ff77cd204073.png)

Q1. Is panic error and stack\_overflow error the same?

Q2. In device1 code, im using software timer2 to write data to blynk gauge, however it doesnt seem to work with blynk and is causing the red SOS.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 2:52am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/27 "2021-01-22T02:52:33Z")

</div>

With new code here, I’ve bottled down the two issues of red SOS.

**Device 1 updated code has the following:**  
Timer 1 - publishes ambience\_c8, no subscribes are inside.  
**Timer 2 - publishes ldrdata to blynk (This causes red SOS) [I couldnt get blynktimer timer; to work thus i used software timer], remove timer 2 and device works fine**  
Prints displaytime and message function to blynk widget lcd(v1) via lcd.print.

**Device 2 updated code has the following:**  
Timer 1 - publishes temp  
Timer 2 - publishes pressure  
**Subscribes to temp, pressure and ambience\_c8** **(This causes panic, hard\_fault, not sure what this is though still flash red)**  
Prints temp and pressure to blynk widget lcd2(V3) via lcd2.print

I understand that IoT integration with blynk and particle requires the void loop to be as clean as possible containing only  
blynk.run() and timer.run().

Q3. In device1 code, I know the displaytime() with delay(1000) and displaymorningmsg() in void loop causes the blynk app connection instability, however I have no idea how to change the code. If i put these two functions in void setup, then only displaytime() lcd.print(0,1) will display.

Q4. Now I know that int (32bit int) vs long int (64bit int), I will remove the L from all my timers.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 2:58am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/28 "2021-01-22T02:58:47Z")

</div>

\<Device 1 code\>

```auto
#include <DailyTimerSpark.h>
#include <blynk.h>

char auth[] = "HIDDEN";
    
int led3=D0; // Blynk Nightlight Control + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 
int ldranalogvalue=0; // Blynk Ambience Brightness Gauge

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting)
WidgetLCD lcd2(V3);

// Check ambience status every 1min
Timer timer1(60000, pub_ambience_status);

// Blynk LDR Gauge
Timer timer2(1000, blynkLDRdata);

void pub_ambience_status(){
    if(analogRead(ldr) >= (ldr_status+30) || analogRead(ldr) <= (ldr_status-30)) //50
    {
        ldr_status = analogRead(ldr);
        Serial.println("Ambience Change");
        Serial.printlnf("LDR Status = %d", ldr_status);

        if (ldr_status <= 100){ // Modify this in class
         Particle.publish("ambience_C8", "Dark", PRIVATE);
         Serial.println("Ambience Status= Dark");
         Serial.println("Ambience Dark Request triggered");
        }
     
         else if (ldr_status >= 300){
         Particle.publish("ambience_C8", "Bright", PRIVATE);
         Serial.println("Ambience Status= Bright");
         Serial.println("Ambience Bright Request triggered");
        }
     
        else{
         Particle.publish("ambience_C8", "Dim", PUBLIC);
         Serial.println("Ambience Status= Dim");
         Serial.println("Ambience Dim Request triggered");
        }
    }
}

void blynkLDRdata(){
    ldr_status = analogRead(ldr);
    Blynk.virtualWrite(V0, ldr_status);
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%dPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

void setup(){
    DisplayTime();
    MorningDisplay();
    
    // Nightlight Toggle On/Off
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);

    // HTML Ambience Brightness Gauge
    ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
    Particle.variable("ldranalogvalue", ldr_status);
    
    Blynk.begin(auth); 

    // bLYNK LCD Time Display (Set Timezone to SG using +8)
    Time.zone(+8);  

    // IP ADDRESS
    // iot_C8 MQTT sub to temp and pressure data vals from D8 published temp and pressure readings
    //Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    //Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    
    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
    
    timer1.start();
    //timer2.start();
}

void loop(){                     
    
    // Run Blynk App
    Blynk.run();
    
    // Blynk LDR Gauge
    //Blynk.virtualWrite(V0, ldr_status);
    
    // Blynk LCD Display (Date + Greeting)
    //DisplayTime();
    //MorningDisplay();
}

int ledToggle(String command) {
    if (command=="on") {
        digitalWrite(led3,HIGH);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led3,LOW);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 0;
    }
    else if (command=="read") {
        return digitalRead(led3);
    }

    else {
        return -1;
    }
}

void DisplayTime(){
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
    lcd.print(0,1, (const char*)Time.format("%a %e %b "));
    delay(2000);
}

void MorningDisplay(){
    DailyTimer MorningTimer(6, 0, 11, 59, EVERY_DAY); // Fixed start time and end time
    if(MorningTimer.startTrigger()){
        lcd.print(0,1, "Good Morning!");
    }
}

```

\<Device 2 code\>

```auto
#include <blynk.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp; // I2C

WidgetLCD lcd2(V3);

char auth[] = "HIDDEN";  

double env_temp;
double env_Pressure;

// HTML Temp + Press Gage Data
double temp_reading;
double press_reading;

// Blynk Slider + Button
int led1 = D2;

Timer timer1(5000, pubTemp);
Timer timer2(20000, pubPress);

void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

void pubTemp(){
    double t_temp = bmp.readTemperature();
    Serial.println("Temperature Request triggered");
    Particle.publish("temperature_D8", String(t_temp), PRIVATE);
}

void pubPress(){
    double t_Pressure = bmp.readPressure();
    Serial.println("Pressure Request triggered");
    Particle.publish("pressure_D8", String(t_Pressure), PRIVATE);
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
    String ambience_status = String(data);
    Serial.println("Ambience Handler executed");
    Serial.println(ambience_status);

    if(ambience_status == "Dark"){
        digitalWrite(D2, HIGH);
        Serial.println("Led turns on");
    }
    else if(ambience_status == "Bright"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
    else if(ambience_status == "Dim"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
}

void setup() {
    
    pinMode(led1, OUTPUT);

    // HTML Temp and pressure gauge reading
    Particle.variable("temp", temp_reading);    
    Particle.variable("press", press_reading);    
    
    
    // iot_D8 Device MQTT subscribe to Ambience_C8
    Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 
    
    Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    

    Blynk.begin(auth); 

    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
 
    if (!bmp.begin()){
        Serial.println("Can't find the sensor BMP280");
    }
    
    timer1.start();
    timer2.start();
}

void loop() {
    Blynk.run();

    temp_reading = bmp.readTemperature();
    press_reading = bmp.readPressure();
}

```

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 3:23am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/29 "2021-01-22T03:23:14Z")

</div>

Update 2:

Now I've made some changes to both device codes. I'm only getting red SOS on device 1 (13 blinks ) when I use timer2.start().

Not sure why the hard\_fault error earlier is gone but i guess thats a good sign!

**Device 1 code:**

- Timer1- publish amibnece\_c8 every 1min (updates ldr val to HTML every 1min)
- timer 2 - publish ldrdata to blynk (causes red sos) [ I just need to fix this but blynktimer timer; doesnt work ☹ )
- subscribes to press and temp in void setup,
- removed displaytimer and msg() in void loop, placed inside setup instead. prints only %a, %e, %b on lcd(0,1), not sure why lcd(0,0) not printing %I:%M%p.
- prints temp and pressure display on lcd2

> [@kannnyyy](#):
>
> **Device 1 updated code has the following:**  
> Timer 1 - publishes ambience\_c8, no subscribes are inside.  
> **Timer 2 - publishes ldrdata to blynk (This causes red SOS) [I couldnt get blynktimer timer; to work thus i used software timer], remove timer 2 and device works fine**  
> Prints displaytime and message function to blynk widget lcd(v1) via lcd.print.

**Device 2 code**

- timer 1 - publishes temp every 5s
- timer 2 - publishes pressure every 20s
- subscribes to ambience\_c8 only (NO panic, hard\_fault, works fine!)

> [@kannnyyy](#):
>
> **Device 2 updated code has the following:**  
> Timer 1 - publishes temp  
> Timer 2 - publishes pressure  
> **Subscribes to temp, pressure and ambience\_c8** **(This causes panic, hard\_fault, not sure what this is though still flash red)**  
> Prints temp and pressure to blynk widget lcd2(V3) via lcd2.print

\<Device 1 code\>

```auto
#include <DailyTimerSpark.h>
#include <blynk.h>

char auth[] = "HIDDEN";
    
int led3=D0; // Blynk Nightlight Control + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 
int ldranalogvalue=0; // Blynk Ambience Brightness Gauge

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting)
WidgetLCD lcd2(V3);

// Check ambience status every 1min
Timer timer1(60000, pub_ambience_status);

// Blynk LDR Gauge
Timer timer2(60000, blynkLDRdata);

void pub_ambience_status(){
    if(analogRead(ldr) >= (ldr_status+30) || analogRead(ldr) <= (ldr_status-30)) //50
    {
        ldr_status = analogRead(ldr);
        Serial.println("Ambience Change");
        Serial.printlnf("LDR Status = %d", ldr_status);

        if (ldr_status <= 100){ // Modify this in class
         Particle.publish("ambience_C8", "Dark", PRIVATE);
         Serial.println("Ambience Status= Dark");
         Serial.println("Ambience Dark Request triggered");
        }
     
         else if (ldr_status >= 300){
         Particle.publish("ambience_C8", "Bright", PRIVATE);
         Serial.println("Ambience Status= Bright");
         Serial.println("Ambience Bright Request triggered");
        }
     
        else{
         Particle.publish("ambience_C8", "Dim", PUBLIC);
         Serial.println("Ambience Status= Dim");
         Serial.println("Ambience Dim Request triggered");
        }
    }
}

void blynkLDRdata(){
    ldr_status = analogRead(ldr);
    Blynk.virtualWrite(V0, ldr_status);
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

void setup(){
    DisplayTime();
    MorningDisplay();
    
    // Nightlight Toggle On/Off
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);

    // HTML Ambience Brightness Gauge
    ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
    Particle.variable("ldranalogvalue", ldr_status);
    
    Blynk.begin(auth); 

    // bLYNK LCD Time Display (Set Timezone to SG using +8)
    Time.zone(+8);  

    // IP ADDRESS
    // iot_C8 MQTT sub to temp and pressure data vals from D8 published temp and pressure readings
    Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    
    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
    
    timer1.start();
    //timer2.start();
}

void loop(){                     
    
    // Run Blynk App
    Blynk.run();
    
    // Blynk LDR Gauge
    //Blynk.virtualWrite(V0, ldr_status);
    
    // Blynk LCD Display (Date + Greeting)
    //DisplayTime();
    //MorningDisplay();
}

int ledToggle(String command) {
    if (command=="on") {
        digitalWrite(led3,HIGH);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led3,LOW);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 0;
    }
    else if (command=="read") {
        return digitalRead(led3);
    }

    else {
        return -1;
    }
}

void DisplayTime(){
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
    lcd.print(0,1, (const char*)Time.format("%a %e %b "));
    delay(2000);
}

void MorningDisplay(){
    DailyTimer MorningTimer(6, 0, 11, 59, EVERY_DAY); // Fixed start time and end time
    if(MorningTimer.startTrigger()){
        lcd.print(0,1, "Good Morning!");
    }
}

```

\<Device 2 code \>

```auto
#include <blynk.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp; // I2C

WidgetLCD lcd2(V3);

char auth[] = "HIDDEN";  

double env_temp;
double env_Pressure;

// HTML Temp + Press Gage Data
double temp_reading;
double press_reading;

// Blynk Slider + Button
int led1 = D2;

Timer timer1(5000, pubTemp);
Timer timer2(20000, pubPress);

void pubTemp(){
    double t_temp = bmp.readTemperature();
    Serial.println("Temperature Request triggered");
    Particle.publish("temperature_D8", String(t_temp), PRIVATE);
}

void pubPress(){
    double t_Pressure = bmp.readPressure();
    Serial.println("Pressure Request triggered");
    Particle.publish("pressure_D8", String(t_Pressure), PRIVATE);
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
    String ambience_status = String(data);
    Serial.println("Ambience Handler executed");
    Serial.println(ambience_status);

    if(ambience_status == "Dark"){
        digitalWrite(D2, HIGH);
        Serial.println("Led turns on");
    }
    else if(ambience_status == "Bright"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
    else if(ambience_status == "Dim"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
}

void setup() {
    
    pinMode(led1, OUTPUT);

    // HTML Temp and pressure gauge reading
    Particle.variable("temp", temp_reading);    
    Particle.variable("press", press_reading);    
    
    
    // iot_D8 Device MQTT subscribe to Ambience_C8
    Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 
    
    //Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    //Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    

    Blynk.begin(auth); 

    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
 
    if (!bmp.begin()){
        Serial.println("Can't find the sensor BMP280");
    }
    
    timer1.start();
    timer2.start();
}

void loop() {
    Blynk.run();

    temp_reading = bmp.readTemperature();
    press_reading = bmp.readPressure();
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 22, 2021, 8:43am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/30 "2021-01-22T08:43:45Z")

</div>

> [@kannnyyy](#):
>
> Is panic error and stack\_overflow error the same?

"Panic crash" is the umbrella term for all SOS+x errors and "stack overflow" (SOS+13) is one of them.

> [@kannnyyy](#):
>
> Q2. In device1 code, im using software timer2 to write data to blynk gauge, however it doesnt seem to work with blynk and is causing the red SOS.

While this isn't really a question, that's what I was referring to with this

> [@ScruffR](#):
>
> When using timers you need to be aware that the thread running these timers only has a very limited stack space and hence any heavy library calls (i.e. Blynk) may run the risk of overflowing the stack.

> [@kannnyyy](#):
>
> hard\_fault, not sure what this is

Hmm, how come? I provided you with a link that would have clarified that and also listed some common causes 😉

> [@kannnyyy](#):
>
> I understand that IoT integration with blynk and particle requires the void loop to be as clean as possible containing only  
> blynk.run() and timer.run().

This is a very simplistic view. You can still keep `loop()` clean and tidy even _with_ doing other stuff therein. You just need to avoid anything that may bog down the code flow for extended periods (e.g. `delay()`, tight loops, ...).

> [@kannnyyy](#):
>
> I know the displaytime() with delay(1000) and displaymorningmsg() in void loop causes the blynk app connection instability, however I have no idea how to change the code.

One way to do that is by _ **conciously** _ using timers (i.e. one-shot timers) or a dedicated "soft delay" function that keeps your essential tasks running while waiting.

e.g.

```cpp
bool ldrNeedUpdate = false;
void blynkLDRdata(){
  ldrNeedUpdate = true;
}

// cannot be called from a Software Timer!
void mustDo() {
  if (Particle.connected()) {
    Blynk.run(); // not Blynk.loop();
    timer.run(); // not Blynk.timer();
    if (ldrNeedUpdate) {
      ldr_status = analogRead(ldr);
      Blynk.virtualWrite(V0, ldr_status);
      ldrNeedUpdate = false;
    }
  }
  Particle.process();
}

void softDelay(uint32_t timeout) {
  for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}

void loop() {
  mustDo();
}

```

Whenever you need a delay all the essential stuff will still be executed while waiting.  
Alternatively I'd even consider using an FSM for the display which would be called in the `mustDo()` function and can be controlled from your other code - including timers.

I'd also _ **not** _ read the BMP sensor on each iteration of `loop()`, particularly when only using the readings every few seconds.

BTW, Blynk timers are nothing else than "obscured" a `millis()` timers.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 12:13pm UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/31 "2021-01-22T12:13:49Z")

</div>

Hi ScruffR! I noticed that the red SOS would appear when my device1 timer1 (pub\_ambience) duration is set to 3 seconds. However at 30seconds or 60seconds, the red SOS does not appear.

Q5. I was wondering if using switch-case would work with timers than compared to if-elseif-else statement.

I tried your example code but Blynk.loop() and Blynk.timer() gives blynkparticle does not contain member loop/timer! I commented them out and pasted the code, the ldr value wasnt updated ☹ Also, how do I set the timeout or softdelay duration?

Despite that, I was able to use BlynkTimer timer; to update ldr value in blynk app and also displaytime.

```auto
BlynkTimer timer;

void setup(){    
timer.setInterval(3000, ldrData);
}

void ldrData(){
    ldr_status=analogRead(ldr);
    Blynk.virtualWrite(V0, ldr_status);
    
    DisplayTime();
}

void loop(){
timer.run();
}

```

Q6. What can I use to replace the delay function which will not interrupt blynk.run in void loop since I want to display the day + date for two seconds, followed by a greeting message (e.g good morning) for two seconds and repeat this cycle.

Meanwhile, im doing some reading up on one shot timers and soft delays here...

> [@Delay(), vs "soft delay" \[end of discourse\]](https://community.particle.io/t/delay-vs-soft-delay-end-of-discourse/12051/11):
>
> But to prevent any hick-ups with type incompatibilities - uint32\_t vs. int vs. number literals - it has prooven useful to just snapshot millis() in your sub-process and check against ((millis() - snapshotMillis) \>= processDelayTime) On the other hand there are also interrupt driven ways to achieve some of these things … And beaten again by @peekay123 wink +1

> [@Pass parameters to one-shot software timer's callback function](https://community.particle.io/t/pass-parameters-to-one-shot-software-timers-callback-function/52236/3):
>
> It could also just advance a FSM and each step then calls a separate function?

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 22, 2021, 12:50pm UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/32 "2021-01-22T12:50:24Z")

</div>

Update 2:

For device 1, Instead of using software timer to publish this value, I decided to use the BlynkTimer timer; and place my if-elseif-else statement + publish ambience value. However, the Red SOS occurs after 3minutes of running the code and connects back to cloud.

Q7. How should I optimize this?

Q8. I plan put temp and pressure publish and reading in BlynkTimer timer; as well, do you recommend this?

Device 1 Code

```auto
#include <DailyTimerSpark.h>
#include <blynk.h>

BlynkTimer timer;

char auth[] = "HIDDEN";
    
int led3=D0; // Blynk Nightlight Control + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting)
WidgetLCD lcd2(V3); // Blynk LCD (Temp + Pressure)

// Check ambience status every 30 seconds
/*Timer timer1(30000, pub_ambience_status);

void pub_ambience_status(){

        ldr_status = analogRead(ldr);
        Serial.println("Ambience Change");
        Serial.printlnf("LDR Status = %d", ldr_status);

        if (ldr_status <= 100){ // Modify this in class
         Particle.publish("ambience_C8", "Dark", PRIVATE);
         Serial.println("Ambience Status= Dark");
         Serial.println("Ambience Dark Request triggered");
        }
     
         else if (ldr_status >= 300){
         Particle.publish("ambience_C8", "Bright", PRIVATE);
         Serial.println("Ambience Status= Bright");
         Serial.println("Ambience Bright Request triggered");
        }
     
        else{
         Particle.publish("ambience_C8", "Dim", PUBLIC);
         Serial.println("Ambience Status= Dim");
         Serial.println("Ambience Dim Request triggered");
        }
}*/

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

void setup(){
    //MorningDisplay();
    
    // Nightlight Toggle On/Off
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);

    // HTML Ambience Brightness Gauge
    ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
    Particle.variable("ldranalogvalue", ldr_status);
    
    Blynk.begin(auth); 

    // bLYNK LCD Time Display (Set Timezone to SG using +8)
    Time.zone(+8);  
    lcd.clear();
    lcd2.clear();

    // IP ADDRESS
    // iot_C8 MQTT sub to temp and pressure data vals from D8 published temp and pressure readings
    Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    
    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
    
    //timer1.start();
    
    // Push ldrdata into blynk app every 3 seconds (Prevents floodings)
    timer.setInterval(3000, ambience_status);
}

void ambience_status(){
    // update ldr_value to gauge
    ldr_status=analogRead(ldr);
    Blynk.virtualWrite(V0, ldr_status);
    
    // Publish ambience_status
    if (ldr_status <= 100){  
        lcd.print(9,0, "Dark ");
        Particle.publish("ambience_C8", "Dark", PRIVATE);
        Serial.println("Ambience Status= Dark");
        Serial.println("Ambience Dark Request triggered");
    }
    
    else if (ldr_status >= 300){    
        lcd.print(9,0, "Bright");
        Particle.publish("ambience_C8", "Bright", PRIVATE);
        Serial.println("Ambience Status= Bright");
        Serial.println("Ambience Bright Request triggered");
    }
    
    else{
        lcd.print(9,0, "Dim ");
        Particle.publish("ambience_C8", "Dim", PRIVATE);
        Serial.println("Ambience Status= Dim");
        Serial.println("Ambience Dim Request triggered");
    }

    DisplayTime();
    DisplayDate();
}

void loop(){                     
    Blynk.run();
    timer.run();
}

void DisplayTime(){
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
}

void DisplayDate(){
    lcd.print(0,1, (const char*)Time.format("%a %e %b "));
}

void MorningDisplay(){
    DailyTimer MorningTimer(6, 0, 11, 59, EVERY_DAY); 
    if(MorningTimer.startTrigger()){
        lcd.print(0,1, "Good Morning!");
    }
}

int ledToggle(String command) {
    if (command=="on") {
        digitalWrite(led3,HIGH);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led3,LOW);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 0;
    }
    else if (command=="read") {
        return digitalRead(led3);
    }

    else {
        return -1;
    }
}

```

Device 2 Code

```auto
#include <Adafruit_BMP280.h>
#include <blynk.h>

Adafruit_BMP280 bmp; // I2C

WidgetLCD lcd2(V3);

char auth[] = "HIDDEN";  

double env_temp;
double env_Pressure;

// HTML Temp + Press Gage Data
double temp_reading;
double press_reading;

// Blynk Slider + Button
int led1 = D2;

// Publish temp val every 5s
Timer timer1(5000, pubTemp);
// Publish press val every 20s
Timer timer2(20000, pubPress);

void pubTemp(){
    double t_temp = bmp.readTemperature();
    Serial.println("Temperature Request triggered");
    Particle.publish("temperature_D8", String(t_temp), PRIVATE);
}

void pubPress(){
    double t_Pressure = bmp.readPressure();
    Serial.println("Pressure Request triggered");
    Particle.publish("pressure_D8", String(t_Pressure), PRIVATE);
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
    String ambience_status = String(data);
    Serial.println("Ambience Handler executed");
    Serial.println(ambience_status);

    if(ambience_status == "Dark"){
        digitalWrite(D2, HIGH);
        Serial.println("Led turns on");
    }
    else if(ambience_status == "Bright"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
    else if(ambience_status == "Dim"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
}

void setup() {
    
    pinMode(led1, OUTPUT);

    // HTML Temp and pressure gauge reading
    Particle.variable("temp", temp_reading);    
    Particle.variable("press", press_reading);    
    
    
    // iot_D8 Device MQTT subscribe to Ambience_C8
    Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 

    Blynk.begin(auth); 

    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
 
    if (!bmp.begin()){
        Serial.println("Can't find the sensor BMP280");
    }
    
    timer1.start();
    timer2.start();
}

void loop() {
    Blynk.run();

    temp_reading = bmp.readTemperature();
    press_reading = bmp.readPressure();
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 22, 2021, 1:03pm UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/33 "2021-01-22T13:03:52Z")

</div>

> [@kannnyyy](#):
>
> I was wondering if using switch-case would work with timers than compared to if-elseif-else statement.

switch-case is a common C concept and works irrespective of location. The only thing to consider that it can only work on ordinal values (not strings nor floating point values).

> [@kannnyyy](#):
>
> I tried your example code but Blynk.loop() and Blynk.timer() gives blynkparticle does not contain member loop/timer!

My bad, it should obviously be `Blynk.run()` instead of `Blynk.loop()` (corrected above) and `Blynk.timer()` should rather be `timer.run()` 😊

> [@kannnyyy](#):
>
> how do I set the timeout or softdelay duration?

Just as you would with `delay()` pass the desired time as parameter `softDelay(1000)`.

> [@kannnyyy](#):
>
> What can I use to replace the delay function which will not interrupt blynk.run in void loop since

That _ **is** _ what `softDelay()` would do. In both cases - when running `loop()` or stuck inside `softDelay()` the important stuff will be attended to via the `mustDo()` calls.

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 23, 2021, 7:33am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/34 "2021-01-23T07:33:14Z")

</div>

Hi ScruffR! Thanks for your advice! I put my particle.publish inside the Mustdo() function using a couple of if-statements to replace use of software timer and also iterate through bmp.reading in mustDo function as well!

Q1. I have a physical button and widget button. I am able to code the physical button to publish data when pressed. However, I cant seem to sync widget button state to physical button.  
I want both widget button and physical button to publish data when pressed. How can I achieve this?  
I tried this method to read state of button V4:

```auto
BLYNK_READ(V4){
    if(BLYNK_READ(V4)==HIGH){
         Particle.publish("door_status_D8", "door locked");
    }
    else{
        Particle.publish("door_status_D8", "DOOR UNLOCKED");
    }
}

```

Q2. Now that most of my code is inside the mustDo() function and use of softdelays in void loop, the red SOS is gone! but… im getting red SOS when Im trying to write code for blynk.email widget to send an email when particle.subscribe door handler receives “door unlocked” but I cant get the email to send through ☹ Am I using blynk.email widget correctly?

```auto
void myDoorHandler(const char *event, const char *data){
    String door_status = String(data);
    Serial.println("Door Handler executed");
    Serial.println(door_status);

    if(door_status == "DOOR UNLOCKED"){
        String msg = "Your door was UNLOCKED on "+Time.format("%a %e %b")+" at "+Time.format("%I:%M%p.")+"Please ignore this email if this was you.";
        lcd3.print(0, 0, "Door UNLOCKED!");
        Serial.println(msg);
        Blynk.email("SECURITY ALERT!", msg);

```

Device 1 Code

```auto
#include <DailyTimerSpark.h>
#include <blynk.h>

BlynkTimer timer;

char auth[] = "HIDDEN";
    
int led3=D0; // Blynk Nightlight Control + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting + Ambience Status)
WidgetLCD lcd2(V3); // Blynk LCD (Temp + Pressure)
WidgetLCD lcd3(V5); // Blynk LCD (Door status)

bool ldrNeedUpdate = false;

void blynkLDRdata(){
  ldrNeedUpdate = true;
}

// cannot be called from a Software Timer!
void mustDo() {
  if (Particle.connected()) { //Particle.process() is a blocking call, and blocks for a few milliseconds.
    Blynk.run(); 
    timer.run();
    if (ldrNeedUpdate) {
      ldr_status = analogRead(ldr);
      Blynk.virtualWrite(V0, ldr_status);
      ldrNeedUpdate = false;
    }
  }
  Particle.process();
}

void softDelay(uint32_t timeout) {
  for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}

// Get Temperature data from subscribed topic and print on LCD
void myTempHandler(const char *event, const char *data){
    double temp_val = atof(data);
    Serial.printlnf("Temperature Handler executed, %f°C", temp_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2f°C %s", temp_val, (temp_val > 32.50) ? "Warm" : "Cool");
    lcd2.print(0, 0, msg);
}

void myPressHandler(const char *event, const char *data){
    double press_val = atof(data);
    Serial.printlnf("Pressure Handler executed, %.2fPa", press_val);

    char msg[32];
    snprintf(msg, sizeof(msg), "%.2fPa %s", press_val, (press_val > 900) ? "High" : "Low");
    lcd2.print(0, 1, msg);
}

void myDoorHandler(const char *event, const char *data){
    String door_status = String(data);
    Serial.println("Door Handler executed");
    Serial.println(door_status);

    if(door_status == "DOOR UNLOCKED"){
        String msg = "Your door was UNLOCKED on "+Time.format("%a %e %b")+" at "+Time.format("%I:%M%p.")+"Please ignore this email if this was you.";
        lcd3.print(0, 0, "Door UNLOCKED!");
        Serial.println(msg);
        Blynk.email("SECURITY ALERT!", msg);

    }
    else{
        lcd3.print(0, 0, "Door locked ");
    }
}

void setup(){

    // Nightlight Toggle On/Off
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);

    // HTML Ambience Brightness Gauge
    ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
    Particle.variable("ldranalogvalue", ldr_status);
    
    Blynk.begin(auth); 

    // bLYNK LCD Time Display (Set Timezone to SG using +8)
    Time.zone(+8);  
    lcd.clear();
    lcd2.clear();
    lcd3.clear();

    // IP ADDRESS
    // iot_C8 MQTT sub to temp and pressure data vals from D8 published temp and pressure readings
    Particle.subscribe("temperature_D8", myTempHandler, MY_DEVICES);
    Particle.subscribe("pressure_D8", myPressHandler, MY_DEVICES);
    Particle.subscribe("door_status_D8", myDoorHandler, MY_DEVICES);
    
    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
    
    // Push ldrdata into blynk app every 3 seconds (Prevents floodings)
    timer.setInterval(2000, functions);
}

void functions(){
    // update ldr_value to gauge
    blynkLDRdata();
    pub_ambience_status();
    
}

void pub_ambience_status(){
    if (ldr_status <= 100){  
        lcd.print(9,0, "Dark ");
        Particle.publish("ambience_C8", "Dark", PRIVATE);
        Serial.println("Ambience Status= Dark");
        Serial.println("Ambience Dark Request triggered");
    }
    
    else if (ldr_status >= 300){    
        lcd.print(9,0, "Bright");
        Particle.publish("ambience_C8", "Bright", PRIVATE);
        Serial.println("Ambience Status= Bright");
        Serial.println("Ambience Bright Request triggered");
    }
    
    else{
        lcd.print(9,0, "Dim ");
        Particle.publish("ambience_C8", "Dim", PRIVATE);
        Serial.println("Ambience Status= Dim");
        Serial.println("Ambience Dim Request triggered");
    }
}

void loop(){                     
    mustDo();

    DisplayTime();
    DisplayDate();
    softDelay(1500);
    Greeting();
    softDelay(1500);
}

void DisplayTime(){
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
}

void DisplayDate(){
    lcd.print(0,1, (const char*)Time.format("%a %e %b "));
}

void Greeting(){
    DailyTimer MorningTimer(5, 0, 11, 59, EVERY_DAY); 
    DailyTimer AfternoonTimer(12, 0, 16, 59, EVERY_DAY); 
    DailyTimer EveningTimer(17, 0, 19, 59, EVERY_DAY); 
    DailyTimer NightTimer(20, 0, 23, 59, EVERY_DAY); 

    if(MorningTimer.startTrigger()){
        lcd.print(0,1, "Good Morning ");
    }
    
    else if(AfternoonTimer.startTrigger()){
        lcd.print(0,1, "Good Afternoon");
    }
    
    else if(EveningTimer.startTrigger()){
        lcd.print(0,1, "Good Evening ");
    }
    else if(NightTimer.startTrigger()){
        lcd.print(0,1, "Good Night ");
    }
    else{
        lcd.print(0,1, "Midnight ");
    }
}

int ledToggle(String command) {
    if (command=="on") {
        digitalWrite(led3,HIGH);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led3,LOW);
        Serial.print("HTML led3 ");
        Serial.println(command);
        return 0;
    }
    else if (command=="read") {
        return digitalRead(led3);
    }

    else {
        return -1;
    }
}

```

Device 2 Code

```auto
#include <Adafruit_BMP280.h>
#include <blynk.h>

Adafruit_BMP280 bmp; // I2C
BlynkTimer timer;

int button=D4; // Fingerprint scanner

char auth[] = "HIDDEN";  

// HTML Temp + Press Gage Data
double t_temp;
double t_press;

// Blynk Slider + Button
int led1 = D2;

Timer timer1(5000, fingerprint_scanner);

bool tempNeedUpdate = false;
bool pressNeedUpdate = false;

void tempdata(){
    tempNeedUpdate = true;
}

void pressdata(){
    pressNeedUpdate = true;
}

// cannot be called from a Software Timer!
void mustDo() {
  if (Particle.connected()) {
    Blynk.run(); 
    timer.run();
    if (tempNeedUpdate) {
        t_temp = bmp.readTemperature();
        Particle.publish("temperature_D8", String(t_temp), PRIVATE);
        Serial.println("Temperature Request triggered");
        tempNeedUpdate = false;
    }
    
    if (pressNeedUpdate) {
        t_press = bmp.readPressure();
        Particle.publish("pressure_D8", String(t_press), PRIVATE);
        Serial.println("Pressure Request triggered");
        pressNeedUpdate = false;
        
    }
  }
  Particle.process();
}

void functions(){
    tempdata();
    pressdata();
}

void softDelay(uint32_t timeout) {
  for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
    String ambience_status = String(data);
    Serial.println("Ambience Handler executed");
    Serial.println(ambience_status);

    if(ambience_status == "Dark"){
        digitalWrite(D2, HIGH);
        Serial.println("Led turns on");
    }
    else if(ambience_status == "Bright"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
    else if(ambience_status == "Dim"){
        digitalWrite(D2, LOW);
        Serial.println("Led stays off");
    }
}

void setup() {
    
    pinMode(led1, OUTPUT);
    pinMode(button, INPUT_PULLUP);
    
    // HTML Temp and pressure gauge reading
    Particle.variable("temp", t_temp);
    Particle.variable("press", t_press);
    
    // iot_D8 Device MQTT subscribe to Ambience_C8
    Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 

    Blynk.begin(auth); 

    Serial.begin(9600);
    while (!Serial);
    Serial.println("Serial is Running");
    Serial.println("Blynk is running. Ensure wifi connected on device and app are same");
 
    if (!bmp.begin()){
        Serial.println("Can't find the sensor BMP280");
    }
    

    timer1.start();
    timer.setInterval(5000, functions);
}

void loop(){
    mustDo();

}

void fingerprint_scanner(){
    if (digitalRead(button) == LOW){
        Particle.publish("door_status_D8", "DOOR UNLOCKED");
    }
    else{
        Particle.publish("door_status_D8", "door locked");
    }
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 23, 2021, 8:11am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/35 "2021-01-23T08:11:46Z")

</div>

> [@kannnyyy](#):
>
> im getting red SOS when Im trying to write code for blynk.email widget

You omitted the info about which kind of SOS it was again!  
And you also use `String` again despite being warned to avoid it wherever possible.

If I'm not mistaken the first parameter of `Blynk.email()` is supposed to be the email address, isn't it? But you are _ **not** _ passing a valid email address there.

* * *

Not sure what the current state of your project is, but here I have tried to do the same thing entirely without timers and delays. Also unifying functions that mainly do the same thing into only one.  
[Particle Web IDE](https://go.particle.io/shared_apps/600c4afae6f0b000092f775c)

The code for both device types is all there in that one file. You only need to set the target type in the first line

```cpp
// either
#define DEVICE_TYPE 1
// or
#define DEVICE_TYPE 2

```

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 24, 2021, 8:19am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/36 "2021-01-24T08:19:32Z")

</div>

Hi ScruffR! Thank you very much for your writing the code. I've tested it and I have no stack overflow, i will try to implement parts of it (unifying function and publish) into my code

- Why do you use const int instead of int to declare pins?
- I see that you used log.info/log.warn instead of serial.print! I'll implement that to my code so it looks neater 🙂
- I've also removed dailysparktimer and used your float hh timer instead.
- I noticed that you used wrote char msg[16] = "", strncpy(msg, "Dark", sizeof(msg)); and Particle.publish("C8\_ambience", msg);  
How is this different from Particle.publish("C8\_ambience", "Dark", PRIVATE);? Is the one you wrote, is a char and the one with "Dark" a string that gets converted to char (Since ambience\_handler (const char \*event, const char \*data) )?
- Whats the difference between having a function prototype and function declaration? Does having a function prototype help to improve code speed?

I just realised i used strings in my ambience handler!! I noticed in your code you wrote the below.

```cpp
void c8_Handler(const char *event, const char *data){
  Log.trace("%s: <%s>", event, data);
  if(!LITERALCMP(data, "Dark")) {

```

I;m trying to understand const and strings. If I replace if(ambience\_status=="Dark") with if(data=="Dark"), my code still verified, however whatever is inside the if statement does not execute. I tried if(data = "Dark") and whatever inside the if statement works. Why is this so?

> [@kannnyyy](#):
>
> ```cpp
> void myAmbienceHandler(const char *event, const char *data){
> String ambience_status = String(data);
> Serial.println("Ambience Handler executed");
> Serial.println(ambience_status);
> 
> if(ambience_status == "Dark"){
> 
> ```

I was wondering if writing serialprint&publish once based on LDR state every 5 seconds would allow photon to be more efficient;

> <https://arduino.stackexchange.com/questions/37378/write-to-serial-only-if-the-state-of-a-light-sensor-changes>

I'm about halfway done with my project, though I'm still facing stack overflow issue with my own code.

> [@Setting stack size](https://community.particle.io/t/setting-stack-size/31840/3):
>
> @larse, there is no way to set the stack size except for new FreeRTOS threads. Calling System.freeMemory() show he available space on the Heap but does not indicate how fragmented it is. Often, memory issues are due to using functions that dynamically allocate and release memory on the Heap, creating fragmentation. This includes some Standard Library functions (eg. \<vector\>) and more commonly the Arduino String commands. The solution to the latter is to use c-string (char arrays) functions. …

I managed to get the fingerprint scanner widget button on blynk working with this:

```cpp
void fingerprint_scanner(){
    if (digitalRead(button) == LOW){
        Particle.publish("door_status_D8", "DOOR UNLOCKED");
    }
    else{ // HIGH
        Particle.publish("door_status_D8", "door locked");
    }
}

BLYNK_WRITE(V4){ // widget btn state opposite of physical btn state  
    if(param.asInt()){ // HIGH , param.asInt() gets value from pin V4
        Particle.publish("door_status_D8", "door locked");
    }
    else{ // LOW
        Particle.publish("door_status_D8", "DOOR UNLOCKED");
    }
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 24, 2021, 11:13am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/37 "2021-01-24T11:13:40Z")

</div>

> [@kannnyyy](#):
>
> Why do you use const int instead of int to declare pins?

`const` "variables" will only reside in flash and use no RAM. Non-const initialised variables occupy space in both flash and RAM. Since these values will never change while the program is running there is no use in wasting RAM.

`Log.xxx()` is not only neater but also allows you to disable the logging entirely (and not even be compiled into the code) by simply changing the `LOG_LEVEL`

A single `Particle.publish()` instruction makes it easier to (potentially) change the event name and using a common variable to store the data makes reusing that variable for different function calls easier (e.g. logging and publishing and displaying the same text).  
Also Particle has removed the possibility to publish PUBLIC events and hence the `PRIVATE` scope has become redundant.  
I also moved the `C8_`/`D8_` qualifyier to the front in order to have one subscribe filter and thus handler catch multiple events of the same type.

Function prototypes are actually a C/C++ requirement but Particle (adopting the Wiring/Arduino ease-of-use paradigm) has opted to have a pre-processor adding prototypes when the user happens to have forgotten to do so.  
However, in some circumstances that pre-processor fails to do that perfectly and hence it's best practice to add them manually anyway (in my test at least one function was not prototyped by the pre-processor, so I added prototypes for all functions - if you remove the prototypes you may see the difference).

`String` is a non-trivial datatype and hence has a somewhat heavier impact on code size and may also cause heap fragmentation due to its dynamic memory needs but offers some layers of comfort using it. However, I usually opt for safer and smaller code even when it means needing to know more about _how_ programming works 😉

C-strings (i.e. `char*` and `char[]`) don't offer the comfort of having an `operator==()` overload for equality checks hence you need to use [`strcmp()`](http://www.cplusplus.com/reference/cstring/strcmp/) and relatives instead.  
In addition to that I defined a macro (`LITERALCMP`) which neatly packages `strncmp()` in a way so that I don't have to write the same literal twice 🕶 (programmers are lazy too 🙈).  
The `==` check didn't fail to compile because it's a perfectly allowed instruction but it doesn't do what you may think it does. It only compares the addresses of the two strings but they will (almost) never be the same even when the string contents are.

> [@kannnyyy](#):
>
> ```auto
> void fingerprint_scanner(){
> if (digitalRead(button) == LOW){
> Particle.publish("door_status_D8", "DOOR UNLOCKED");
> }
> else{ // HIGH
> Particle.publish("door_status_D8", "door locked");
> }
> }
> 
> BLYNK_WRITE(V4){ // widget btn state opposite of physical btn state  
> if(param.asInt()){ // HIGH , param.asInt() gets value from pin V4
> Particle.publish("door_status_D8", "door locked");
> }
> else{ // LOW
> Particle.publish("door_status_D8", "DOOR UNLOCKED");
> }
> }
> 
> ```

This isn't best style tho'  
Both functions do mostly the same thing, so that part should go in a dedicated function which can be called from these two.

```cpp
inline void pubDoorState(bool state) {
  Particle.publish("D8_door_status", state ? "door locked" : "DOOR UNLOCKED!");
}

void fingerprint_scanner() {
  pubDoorState(digitalRead(button));
}

BLYNK_WRITE(V4) {
  pubDoorState(param.asInt());
}

```

_(I also changed the event name for above reason to unify the subscription handler(s) and also added the exclamation mark to the unlocked-message as my subscribe handler looks for it)_

BTW, even with the two separate implementations it's poor style to have the same logic flipped between the two. In one you first check for LOW/FALSE/0 and else and in the second you do the opposite HIGH/TRUE/!0 and else. Even when writing code only for yourself try to write it in a way that anybody (including yourself in the far future) will be easily able to comprehend what's going on and functions that do the same should also look the same (which would then make it easy to see that they actually should be _the same_ 😉 ).

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 24, 2021, 11:36am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/38 "2021-01-24T11:36:58Z")

</div>

Hi ScruffR! Thanks for the detailed explaination!! I never knew about all these !! Interesting and informative!  
Update 2 :A lright, I’ll put a function into physical and widget button function. Currently checking my code now since D8\_handlers arent working

- Does the same goes for static int (flash only, no ram) and int (flash and ram)?
- My log.info doesnt output in console. Why is this so? I’m trying to debug my D8\_Handler function which consists of all the 3 handlers (temp, press and door)

I’ve re-written my code here

Device 1 Code

```auto
#include <blynk.h>

BlynkTimer timer;

SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{"iot_C8", LOG_LEVEL_INFO}});

const int led3=D0; // Blynk Nightlight Control (Slider) + HTML Nightlight Toggle On/Off
int led3_status=-1; // HTML Nightlight Toggle On/Off

const int ldr=A0; // Blynk Ambience Brightness 
int ldr_status=0; // Blynk Ambience Brightness 

WidgetLCD lcd(V1); // Blynk LCD (Date Day Greeting + Ambience Status)
WidgetLCD lcd2(V3); // Blynk LCD (Temp + Pressure)
WidgetLCD lcd3(V5); // Blynk LCD (Door status)

const char auth[] = "HIDDEN";

bool ldrNeedUpdate = false;

void blynkLDRdata(){
    ldrNeedUpdate = true;
}

// cannot be called from a Software Timer!
void mustDo() {
  if (Particle.connected()) {  
    Blynk.run(); 
    timer.run();
    if (ldrNeedUpdate) {
      ldr_status = analogRead(ldr);
      Blynk.virtualWrite(V0, ldr_status);
      ldrNeedUpdate = false; //Particle.process() is a blocking call, and blocks for a few milliseconds.
    }
  }
  Particle.process();
}

void softDelay(uint32_t timeout) {
  for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}

void D8_Handlers(const char *event, const char *data){
    char msg[128];
    int line = 0;
    double val = atof(data);

    if(event = "D8_temperature"){
        Log.info("Temperature Handler executed, %f°C", val);
        snprintf(msg, sizeof(msg), "%.2f°C %s", val, (val > 32.50) ? "Warm" : "Cool");
        line = 0;
    }
    
    else if(event = "D8_pressure"){
        Log.info("Pressure Handler executed, %.2fPa", val);
        snprintf(msg, sizeof(msg), "%.2fPa %s", val, (val > 900) ? "High" : "Low");
        line = 1;
    }
    
    else if(event = "D8_door_status"){
        Log.info("Door Handler executed: %s", data);
        if(data = "DOOR UNLOCKED!") {
            snprintf(msg, sizeof(msg), "Your door was UNLOCKED on %s.\r\n"
                                       "Please ignore if this was you."
                                     , (const char*)Time.format("%a %e %b at %I:%M%p"));
            Log.info(msg);
            Blynk.email("hidden@gmail.com", "SECURITY ALERT!", msg);
        }
        lcd3.print(0, 0, data);
    }
    
    else{
        Log.warn("Unknown event <%s>", event);
        return;
    }
    lcd.print(0, line, msg);
}

void setup(){

    // Nightlight Toggle On/Off
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);

    // HTML Ambience Brightness Gauge
    ldr_status=analogRead(ldr); // pinMode not needed since analogRead used
    Particle.variable("ldranalogvalue", ldr_status);
    
    Blynk.begin(auth); 

    // bLYNK LCD Time Display (Set Timezone to SG using +8)
    Time.zone(+8);  
    lcd.clear();
    lcd2.clear();
    lcd3.clear();

    // IP ADDRESS
    // iot_C8 MQTT sub to door status, temp and pressure data vals from D8 published temp and pressure readings
    //Particle.subscribe("D8_door_status", myDoorHandler, MY_DEVICES);
    //Particle.subscribe("D8_temperature", myTempHandler, MY_DEVICES);
    //Particle.subscribe("D8_pressure", myPressHandler, MY_DEVICES);

    Particle.subscribe("D8_Handlers", D8_Handlers, MY_DEVICES);

    // Push ldrdata into blynk app every 3 seconds
    timer.setInterval(2000, functions);
    
    Log.info("Serial is Running");
}

void functions(){
    // update ldr_value to gauge
    blynkLDRdata();
    pub_ambience_status();
}

void pub_ambience_status(){
    if (ldr_status <= 100){  
        lcd.print(9,0, "Dark ");
        Particle.publish("ambience_C8", "Dark", PRIVATE);
        Log.info("Ambience Status= Dark");
    }
    
    else if (ldr_status >= 300){    
        lcd.print(9,0, "Bright");
        Particle.publish("ambience_C8", "Bright", PRIVATE);
        Log.info("Ambience Status= Bright");
    }
    
    else{
        lcd.print(9,0, "Dim ");
        Particle.publish("ambience_C8", "Dim", PRIVATE);
        Log.info("Ambience Status= Dim");
    }
}

void loop(){                     
    mustDo();

    DisplayTime();
    DisplayDate();
    softDelay(2000);
    Greeting();
    softDelay(2000);
}

void DisplayTime(){
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
}

void DisplayDate(){
    lcd.print(0,1, (const char*)Time.format("%a %e %b "));
}

void Greeting(){

    float hh = (Time.local() % 86400) / 3600.0; // Current decimal hour of the day , currenthr*24hr/1hr
    if (hh < 5.0){
        lcd.print(0, 1, "Midnight");
    }
    else if (hh < 12.0){
        lcd.print(0, 1, "Good Morning");
    }
    else if (hh < 17.0){
        lcd.print(0, 1, "Good Afternoon");
    }
    else if(hh < 20.0){
        lcd.print(0, 1, "Good Evening");
    }
    else if(hh < 24.0){
        lcd.print(0, 1, "Night");
    }
}

int ledToggle(String command) {
    if (command=="on") {
        digitalWrite(led3,HIGH);
        Log.info("HTML led3 on");
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led3,LOW);
        Log.info("HTML led3 off");
        return 0;
    }
    else if (command=="read") {
        return digitalRead(led3);
    }
    else {
        return -1;
    }
}

```

Device 2 Code

```auto
#include <Adafruit_BMP280.h>
#include <blynk.h>

SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{"iot_D8", LOG_LEVEL_INFO}});

Adafruit_BMP280 bmp; // I2C
BlynkTimer timer;

const int led1 = D2; // Ambience light
const int button = D4; // Fingerprint scanner

const char auth[] = "HIDDEN";  

// HTML Temp + Press Gage Data
double t_temp;
double t_press;

// Update fingerprint status every 5s
Timer timer1(3000, fingerprint_scanner);

bool tempNeedUpdate = false;
bool pressNeedUpdate = false;

void tempdata(){
    tempNeedUpdate = true;
}

void pressdata(){
    pressNeedUpdate = true;
}

// cannot be called from a Software Timer!  
void mustDo() {
  if (Particle.connected()) {
    Blynk.run(); 
    timer.run();
    if (tempNeedUpdate) {
        
        char temp_data[16];
        t_temp = bmp.readTemperature();
        snprintf(temp_data, sizeof(temp_data), "%.2f", t_temp);

        Particle.publish("D8_temperature", temp_data, PRIVATE);
        tempNeedUpdate = false;
    }
    
    if (pressNeedUpdate) {

        char press_data[16];
        t_press = bmp.readPressure();
        snprintf(press_data, sizeof(press_data), "%.1f", t_press);
        
        Particle.publish("D8_pressure", press_data, PRIVATE);
        pressNeedUpdate = false;
        
    }
  }
  Particle.process();
}

void functions(){
    tempdata();
    pressdata();
}

void softDelay(uint32_t timeout) {
  for (uint32_t ms = millis(); millis() - ms < timeout; mustDo());
}

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){

    if(data = "Dark"){
        digitalWrite(D2, HIGH);
        Log.info("Led turns on");
    }
    else if((data = "Bright") || (data = "Dim")){
        digitalWrite(D2, LOW);
        Log.info("Led stays off");
    }
    else{
        // nothing
    }
}

void fingerprint_scanner(){
    if (digitalRead(button) == LOW){
        Particle.publish("D8_door_status", "DOOR UNLOCKED");
    }
    else{ // HIGH
        Particle.publish("D8_door_status", "door locked");
    }
}

BLYNK_WRITE(V4){ // widget btn state opposite of physical btn state  
    if(param.asInt()){ // HIGH , param.asInt() gets value from pin V4
        Particle.publish("D8_door_status", "door locked");
    }
    else{ // LOW
        Particle.publish("D8_door_status", "DOOR UNLOCKED");
    }
}

void setup() {
    
    pinMode(led1, OUTPUT);
    pinMode(button, INPUT_PULLUP);
    
    // HTML Temp and pressure gauge reading
    Particle.variable("temp", t_temp);
    Particle.variable("press", t_press);
    
    // iot_D8 Device MQTT subscribe to Ambience_C8
    Particle.subscribe("ambience_C8", myAmbienceHandler, MY_DEVICES); 

    Blynk.begin(auth); 

    timer1.start();
    
    // Update temp and press every 5 seconds
    timer.setInterval(5000, functions);
    
    Log.info("Serial is Running");

    if (!bmp.begin()){
        Log.warn("Can't find the sensor BMP280");
    }
}

void loop(){
    mustDo();
}

```

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 24, 2021, 11:47am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/39 "2021-01-24T11:47:32Z")

</div>

> [@kannnyyy](#):
>
> Does the same goes for static int (flash only, no ram) and int (flash and ram)?

`static` has different meanings between C and C++.  
`static` variables inside functions are still RAM based but will retain their value even after the function has finished.  
`static` class variables are shared between all instances of said class but are also RAM based.

> [@kannnyyy](#):
>
> My log.info doesnt output in console.

Because you changed the scope for the log handler from `app` to `iot_C8`.  
But `Log.info()` logs to the `app` scope. If you want it to log it the `iot_C8` scope you'd need to instantiate a `Logger myLog("iot_C8")` and use that instead.

---

<div class="post-metadata">

### Author: ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)
#### Post date: [January 24, 2021, 11:50am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/40 "2021-01-24T11:50:53Z")

</div>

> [@kannnyyy](#):
>
> `if(event = "D8_temperature"){`

There are mulitple issues.

1. You are using the assignment operator `=` instead of the equality check `==`
2. even with `==` as I said earlier `const char*` cannot be checked for equality that way
3. in a really early post of mine in this thread I suggested, when debugging _always_ add an unconditional `Log.trace("%s: <%s>", event, data);` at the very top of your handler to see, whether the handler fires at all and _what_ data it receives (will require extenging the scope to `LOG_LEVEL_ALL`)

But foremost this

> [@kannnyyy](#):
>
> `Particle.subscribe("D8_Handlers", D8_Handlers, MY_DEVICES);`

This will only trigger for events _ **starting with** _ `D8_Handlers` but the only common part of your events is `D8_`. That's why my code looks like this

```cpp
  Particle.subscribe("D8_", d8_Handler);

```

---

<div class="post-metadata">

### Author: ![kannnyyy](https://avatars.discourse-cdn.com/v4/letter/k/c77e96/32.png) [@kannnyyy](https://community.particle.io/u/kannnyyy)
#### Post date: [January 24, 2021, 11:55am UTC](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099/41 "2021-01-24T11:55:35Z")

</div>

Hi ScruffR! Oh thanks!! I checked out the strcmp() you hyperlinked. Now I understand that it was a const char string instead of normal string!!

[Previous page](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099.md?page=1)

[Next page](https://community.particle.io/t/set-subscribe-handler-data-as-global/59099.md?page=3)
