Photon 2 goes offline - how do I figure out why this is happening?

Hello, I wrote a script to listen to MQTT for up and down signals for my projector screen. The script works for an hour or so and then the photon goes offline. What can I do to troubleshoot this?

// STATE MACHINE:
// A State Machine will be implemented to control the operation of the screen.
// This will eliminate the need for 'delay' statements and will allow the project screen to
// reverse part way through its opening or closing operations
//
// The states of the state machine are as follows (the number is the identifier of the state)
// 0 - SCREEN UP
// 1 - SCREEN LOWERING
// 2 - SCREEN DOWN
// 3 - SCREEN RAISING

// STATE DETAILS:
// 0 - SCREEN UP: This will be the initial state of the screen when the system starts.
// 1 - SCREEN LOWERING: When in this state, the screen will be lowering.
// 2 - SCREEN DOWN: This state is when the screen is down.
// 3 - SCREEN RAISING: When in this state, the screen will be raising.

#include <MQTT.h>
#include <Particle.h>

#define MQTT_MAX_PACKET_SIZE 512

// MQTT Configuration for Home Assistant
const char* mqtt_server = "192.168.x.x";
const int mqtt_port = 1883;
const char* mqtt_username = "user"; // Replace with your Home Assistant MQTT username
const char* mqtt_password = "pass!"; // Replace with your Home Assistant MQTT password
const String baseTopic = "homeassistant/cover/screen"; // Base topic for Home Assistant

MQTT client(mqtt_server, 1883, callback);

int relayScreenDown = D1;
int relayScreenUp = D2;
String screenState = "";
int stateReportTime = 1000;
int screenMovementDelay = 36000;
bool ignoreFirstMessage = true;

// State Machine Variables
int stateTime = 20;             // Time between successive calls to a state function (10 milliseconds)
int elapsedStateTime = 0;       // Number of milliseconds spent in the current state
int stateReportTimer = 0;       // Number of milliseconds spent in the current state

// NOTE: We will start in the Screen Up state.
int currentState = 0; // This is the current state of the state machine

// Setup MQTT callback function
void callback(char* topic, byte* payload, unsigned int length) {
    if (ignoreFirstMessage) {
        ignoreFirstMessage = false;  // Skip only the first message
        Particle.publish("debug", "Ignoring first MQTT message after boot");
        return;
    }

    String message = "";
    for (unsigned int i = 0; i < length; i++) {
        message += (char)payload[i];
    }

    if (String(topic) == baseTopic + "/set") {
        if (message == "DOWN" && screenState != "DOWN") { 
            functionScreenDown(relayScreenDown, true, "");
        } else if (message == "UP" && screenState != "UP") {
            functionScreenUp(relayScreenUp, true, "");
        }
    }
}

int functionOnOff(int device, bool onOff, String rawParameters) {
    digitalWrite(D7, (onOff) ? HIGH : LOW);
    return 1;
}

int functionScreenDown(int device, bool onOff, String rawParameters) {
    Particle.publish("screenState", "Screen Down Button was requested");
    digitalWrite(relayScreenDown, HIGH);
    delay(1000);
    digitalWrite(relayScreenDown, LOW);
    delay(1000);
    digitalWrite(relayScreenDown, HIGH);
    Particle.publish("screenState", "Screen is lowering");
    publishToMQTT(baseTopic + "/state", "LOWERING"); // Publish to MQTT topic
    delay(2000);
    digitalWrite(relayScreenDown, LOW);
    Particle.publish("screenState", "Screen is down");
    publishToMQTT(baseTopic + "/state", "DOWN"); // Publish to MQTT topic
    return 1;
}

int functionScreenUp(int device, bool onOff, String rawParameters) {
    Particle.publish("screenState", "Screen Up Button was requested");
    digitalWrite(relayScreenUp, HIGH);
    delay(1000);
    digitalWrite(relayScreenUp, LOW);
    delay(1000);
    digitalWrite(relayScreenUp, HIGH);
    Particle.publish("screenState", "Screen is raising");
    publishToMQTT(baseTopic + "/state", "RAISING"); // Publish to MQTT topic
    delay(2000);
    digitalWrite(relayScreenUp, LOW);
    Particle.publish("screenState", "Screen is up");
    publishToMQTT(baseTopic + "/state", "UP"); // Publish to MQTT topic
    return 1;
}

// MQTT Connection Setup (Directly in setup)
void setup() {
    pinMode(relayScreenDown, OUTPUT);
    pinMode(relayScreenUp, OUTPUT);
    // pinMode(D7, OUTPUT);

    Particle.variable("screenState", screenState); 
    Particle.function("downBtnPress", fxDownBtnPress);  
    Particle.function("upBtnPress", fxUpBtnPress);  

    client.connect("photonDev");

    // Connect to MQTT
    while (!client.isConnected()) {
        if (client.connect("ParticleDevice", mqtt_username, mqtt_password)) {
            Particle.publish("mqttStatus", "Connected to MQTT", PRIVATE);
        } else {
            Particle.publish("mqttStatus", "Failed to connect to MQTT", PRIVATE);
            delay(3000);
        }
    }
    
    // Subscribe to MQTT topics to receive commands from Home Assistant
    client.subscribe(baseTopic + "/set");
    
    Particle.publish("status", "Setup complete 0.8");
}

// Main loop
void loop() {
    client.loop();                      // Keep MQTT connection alive
    delay(3000);
    if (!client.isConnected()) {
        Particle.publish("mqttStatus", "MQTT connection lost, reconnecting...", PRIVATE);
        while (!client.connect("ParticleDevice", mqtt_username, mqtt_password)) {
            Particle.publish("mqttStatus", "Failed to reconnect to MQTT", PRIVATE);
            delay(1000);
        }
        Particle.publish("mqttStatus", "Reconnected to MQTT", PRIVATE);
        publishToMQTT(baseTopic + "/availability", "online"); // Publish to MQTT topic
        client.subscribe(baseTopic + "/set");
    } else {
        publishToMQTT(baseTopic + "/availability", "online"); // Publish to MQTT topic
    }

}

// Publish MQTT messages with status reporting
void publishToMQTT(String topic, String payload) {
    if (client.publish(topic.c_str(), payload.c_str())) {
        Particle.publish("status", "MQTT successful: " + topic);
    } else {
        Particle.publish("status", "MQTT failed: " + topic);
    }
}

////////////////////// PARTICLE FUNCTIONS ///////////////////

int fxDownBtnPress(String command) {
    if (command.equalsIgnoreCase("press")) {
        functionScreenDown(relayScreenDown, true, "");
        return 1;
    }
    return -1;
}

int fxUpBtnPress(String command) {
    if (command.equalsIgnoreCase("press")) {
        functionScreenUp(relayScreenUp, true, "");
        return 1;
    }
    return -1;
}

@clubanderson Which Device OS are you using? Before 6.3.0 there have been issues with losing connection.

it shows 5.9.0 - how do I upgrade?

I only see 6.2.1 as the highest for the device

Follow the instructions to enable pre-release versions.

Got to 6.2.1 and I already have more uptime today than I have had in a month. Thank you. I will look into getting to 6.3.0 next.

It was too good to be true. Offline again this morning. I guess the situation improved but I am back to search for an answer. I am going to try to get to 6.3.0 to see of this makes a difference. Could there be something in my code that causes this issue?

The problem definitely still exists in 6.2.1 and should be fixed in 6.3.0. See this thread for more information.