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;
}