Set subscribe handler data as global

Either version should compile fine but when you get an error it's always best to read (and post) the exact error message as they tend to give you (or someone who knows to interpret them) some clue :wink:

nope, that function keeps executing DoLoop() at maximum rate as long the timeout is not met.
softDelay() delays the execution of the line following but allows all essential things (packaged in DoLoop()) to be done while waiting.

Hi ScruffR! Hmm very weird… last night i thought i had fixed the door handler crash … but now it crashes again even though i had the else statement added into the void handler.

Update - Upon reading on (!strcmp(s1,s2)) i found out that it means if(true),
https://cboard.cprogramming.com/c-programming/169955-if-strcmp-str1-str2.html
I tried changing to this line == but i’m still getting the crash at the same line, where the pointer stops at the closing else loop and does not fully execute the door handler function

if(strcmp(data, "DOOR UNLOCKED!") == 0) {
        Serial.printlnf("%4d", __LINE__); delay(10);

I’ve checked, my code editor line 26 matches the reference line printed.

  26 <-- reference line
  51 void loop start
 202 display start
 205 display end
 209 greet start
 226 greet end
  95 pub func start
 118 pub func end
  62 void loop end
  51 void loop start
 202 display start
 205 display end
 124 temp hand start
 129 press hand snrpintf start
 131 press hand snprintf end
 138 press hand start
 149 door hand start
 150
 152
 173

For some reason, the crash now happens in temp handler - so line 148 and 149 does not execute… not sure how i can fix the lcd.print though it seems fine?

187
 139 temp hand start
 141
 144
 147


update … why is my crash going to door handler now!!! I don’t get it but i’ve tried coding it this way! I assign char msg2 and msg3 to print door locked and unlocked instead of lcd.print(string)

174
 176
 146 door hand start
 147
 151
 174
 176

That assumption is wrong. Line 147 was the last line that was executed correctly! So the crash happens after 147 which would point to the issue being with the lcdX.print() statement. That also seems to hold true for the other crashes your reported.

There is little point in looking in what function it happens but rather look at what is common to all crashes.

Hi ScruffR! Hmm okay so it executes, and crashes… I don’t quite understand how I can identify what is common in these crashes, I do know that so far temp handler and door handler is crashing due to lcd.print…

Since WidgetLCD lcd3(V5) is a function, I can say my handlers are crashing due to excessive function calls aka recursive functions? So instead of calling the lcd.print inside my handler, I should try to break the function using return;?

Update, i tried to implement the return;but it still didnt work :frowning:

If this still are Stack Overflow (SOS+13) crashes I'd go with this reasoning:

Since lcd.print() works when called from setup() or another "top level" function it's safe to assume it's not the function in itself.
Since Stack Overflows can happen for reasons like a massive set of local variables or excessively deep calls (e.g. recursions as you said) and the point before makes the former unlikely I'd guess it's the latter.
Knowing that subscription handlers will be executed between loop() iterations or when Particle.process() is called (when not using SYSTEM_THREAD(ENABLED)), I'd guess the crash happens when the handler is called while your code flow sits somewhere in a nested call of Particle.process() (e.g. in softDelay()).
Since you have no control over the timing I repeat my advice to avoid delays of any kind and go with an entirely non-blocking approach like the one I provided already.

Actually not merely a function. This line of code instantiates a WidgedLCD object and calls the constructor of that object and subsequently you will call methods (functions in classes/objects) of that object instance.

Why should a random return statement change anyting?
Trial-n-Error is not the best approach - conscious reasoning usually works better.
For that you'd need a basic understanding of how functions calls work, how stack utilization works, ... and then in some cases like this some specifics about the inner workings of the Particle device OS.

Hi ScruffR, hmm… could it be the stack has a limit to store subscribed variables ? If so, then instead of using so many subscribe handlers I will try to combine them into a single subscribe then… as what you did with your code, you stored temp and press into enum… it does seem complicated for me since it is my first time seeing enum being used.
I will try to understand the enum part before applying it to my code…

Update, I think ill combine temp and press publish into one function and publish them!

Update 3 - I finally understand the webhook example!
Sub “D8”
Pub “D8_Door/D8_temp/D8_press”!
Because particle sub handlers will foo - food, foo, fool, foodprata, as long as the subscribed event name contains the specified name. Now my im able to use
void d8_handler(const char event, const char data)
if(strstr(event,“temperature”){
log.trace("%s, %s",event,data)
}
Update 4 - I can get the data now… I’ve observed that i have string data ! I converted them to float for temp and press vals, and to char str. I also used (!strcmp(event, “D8_temp”)) instead of
(strstr(event, "temp)) !

void env_data(){
    temp = bmp.readTemperature();
    press = bmp.readPressure();
   
    char envdata[128];  
    snprintf(envdata, sizeof(envdata), "%.2f~%.2f", temp, press);
    Particle.publish("D8_data", envdata, PRIVATE);
}

Though I have used a single particlesubscribe instead of three, I’m still facing stack overflow , I removed the entire do loop, however, my device still crashes in the event handler !! I removed the delay and only used display(time) in my code.

I guess I’ll change to another project. Perhaps this project is too hard for me to work on.

 107
0000016928 [app] INFO: Temperature Handler executed, 30.07°C
 110

Device 1 code

#include <MQTT.h>
#include <blynk.h>

BlynkTimer timer;

SerialLogHandler logHandler(LOG_LEVEL_ERROR, {{ "app", LOG_LEVEL_ALL }});

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)

void callback(char* topic, byte* payload, unsigned int length);
MQTT client("10.100.2.1", 1883, callback);  

Timer timer1(3000, pub_ambience_status);

const char auth[] = "";

void setup(){
    Serial.printlnf("%4d <-- reference line", __LINE__);
    pinMode(led3, OUTPUT); 
    Particle.function("led",ledToggle);
    Particle.variable("ldranalogvalue", ldr_status);
    
    Particle.subscribe("D8", D8_Handler, MY_DEVICES);
    
    Blynk.begin(auth); 

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

    //timer1.start();
    timer.setInterval(3000, blynkData);
    
    //Log.info("Serial is Running");
    client.connect("C8");
    if(client.isConnected()) {
        client.publish("C8_Ambience/C8",(String)WiFi.localIP());
        client.subscribe("C8_Ambience/C8");
    }
}


void loop(){
    //DoLoop();
    Blynk.run();
    timer.run();

    pub_ambience_status();

    //DisplayTimeDate();
    //delay(2000);


    //Greeting();
    //delay(2000);

    /*if (client.isConnected()) {
       client.loop();
    }
    delay(1000);*/
}

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


void pub_ambience_status(){
    char msg[10] = "";
    
    if (ldr_status <= 100){  
        strncpy(msg, "Dark", sizeof(msg));  
        Particle.publish("C8_ambience", msg, PRIVATE);
        lcd.print(9,0, "Dark  ");
    }
    
    else if (ldr_status >= 300){    
        strncpy(msg, "Bright", sizeof(msg));  
        Particle.publish("C8_ambience", msg, PRIVATE);
        lcd.print(9,0, "Bright");
    }
    
    else{
        strncpy(msg, "Dim", sizeof(msg));  
        Particle.publish("C8_ambience", msg, PRIVATE);
        lcd.print(9,0, "Dim   ");
    }
}


void D8_Handler(const char *event, const char *data){
    if(!strcmp(event, "D8_temperature")){
    Serial.printlnf("%4d", __LINE__); delay(10);    
    char msg[15];
    float val = atof(data);
    Serial.printlnf("%4d", __LINE__); delay(10);
    Log.info("Temperature Handler executed, %.2f°C", val);
    snprintf(msg, sizeof(msg), "%.2f°C %s", val, (val > 32.5) ? "Warm" : "Cool");
    Serial.printlnf("%4d", __LINE__); delay(10);
    lcd2.print(0,0, msg);
    Serial.printlnf("%4d", __LINE__); delay(10);
    }
    
    else if(!strcmp(event, "D8_pressure")){
    Serial.printlnf("%4d", __LINE__); delay(10);
    char msg[15];
    Serial.printlnf("%4d", __LINE__); delay(10);
    float val = atof(data)/1000; // kPa units
    Serial.printlnf("%4d", __LINE__); delay(10);
    Log.info("Pressure Handler executed, %.2fkPa", val);
    Serial.printlnf("%4d", __LINE__); delay(10);
    snprintf(msg, sizeof(msg), "%.2fkPa %s", val, (val > 0.9) ? "High" : "Low ");
    Serial.printlnf("%4d", __LINE__); delay(10);
    lcd2.print(0,1, msg);
    Serial.printlnf("%4d", __LINE__); delay(10);
    }
    
    else if(!strcmp(event, "D8_doorstatus")){ 
    Serial.printlnf("%4d", __LINE__); delay(10);
    char status[16];
    char msg[100];
    char msg2[16];
    char msg3[16];
    Serial.printlnf("%4d", __LINE__); delay(10);
    snprintf(status, sizeof(status), "%s",data);
    Serial.printlnf("%4d", __LINE__); delay(10);
    Log.info("Door Handler executed, %s", status);

    Serial.printlnf("%4d", __LINE__); delay(10);
        if(!strcmp(status, "DOOR UNLOCKED!")) {
            Serial.printlnf("%4d", __LINE__); delay(10);

            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"));
        Serial.printlnf("%4d", __LINE__); delay(10);
            Blynk.email("email@gmail.com", "SECURITY ALERT!", msg);
        Serial.printlnf("%4d", __LINE__); delay(10);
            snprintf(msg2, sizeof(msg), "DOOR UNLOCKED!");
        Serial.printlnf("%4d", __LINE__); delay(10);

            lcd3.print(0,0, msg2);
        Serial.printlnf("%4d", __LINE__); delay(10);
        }
        else if(!strcmp(status, "door locked")){    
            Serial.printlnf("%4d", __LINE__); delay(10);
            snprintf(msg3, sizeof(msg), "door locked   ");
            Serial.printlnf("%4d", __LINE__); delay(10);
            lcd3.print(0,0, msg3);
            Serial.printlnf("%4d", __LINE__); delay(10);
        }
    }
}


void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);

    if (message.equals("Dark")){
        client.publish("C8_Ambience/C8","D8 - Led ON");
    }
    else if (message.equals("Bright")){
        client.publish("C8_Ambience/C8","D8 - Led Off");
    }
    else if (message.equals("Dim")){
        client.publish("C8_Ambience/C8","D8 - Led Off");
    }
    else{
        //Do nothing
    }
}


void DisplayTimeDate(){
    Serial.printlnf("%4d display start", __LINE__); delay(10);
    lcd.print(0,0, (const char*)Time.format("%I:%M%p")); 
    lcd.print(0,1, (const char*)Time.format("%a %e %b    "));
    Serial.printlnf("%4d display end", __LINE__); delay(10);
}

void Greeting(){
    Serial.printlnf("%4d greet start", __LINE__); delay(10);
    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         ");
    }
    Serial.printlnf("%4d greet end", __LINE__); delay(10);
}


int ledToggle(const char* command){  // Assign command str as const char
    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") {
        Log.info("HTML led state");
        return digitalRead(led3);
    }
    else {
        return -1;
    }
}

Device 2 Code

#include <MQTT.h>
#include <Adafruit_BMP280.h>
#include <blynk.h>

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

Adafruit_BMP280 bmp; // I2C
BlynkTimer timer;

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

const char auth[] = "";  

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

bool tempNeedUpdate = false;
bool pressNeedUpdate = false;

Timer timer1(3000, temp);
Timer timer2(5000, press);

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("C8_ambience", myAmbienceHandler, MY_DEVICES); 

    Blynk.begin(auth); 

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

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

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

void temp(){
    char temp_data[10];
    t_temp = bmp.readTemperature();
    snprintf(temp_data, sizeof(temp_data), "%.2f", t_temp);
    Particle.publish("D8_temperature", temp_data, PRIVATE);
}

void press(){
    char press_data[10];
    t_press = bmp.readPressure();
    snprintf(press_data, sizeof(press_data), "%.2f", t_press);
    Particle.publish("D8_pressure", press_data, PRIVATE);
}
void pubDoorState(bool state) { // bool state flag 1/0 button
    Particle.publish("D8_doorstatus", state ? "door locked" : "DOOR UNLOCKED!");
}

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

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

// Get data from subscribed topic ambience_C8, on / off led according to ambience status
void myAmbienceHandler(const char *event, const char *data){
    if(!strcmp(data, "Dark")){
        digitalWrite(D2, HIGH);
        Log.info("Led turns on");
    }
    else if(!strcmp(data, "Bright") || !strcmp(data, "Dim")){
        digitalWrite(D2, LOW);
        Log.info("Led stays off");
    }
}

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