Stability updates, save state on SPIFFS, MQTT QOS
Modified * Better implementation of tickers (recommended) Added * Save State on SPIFFS (alternative to EEPROM) EEPROM has finite write cycles. * Added Custom MQTT QOS levels, as AMQTT can handle QOS level 0,1&2 in both publish and subscribe. Pubsub can only sunscribe in QOS 1&2, publish at QOS 1 only.
This commit is contained in:
parent
583d1396b7
commit
8b21969784
3 changed files with 441 additions and 212 deletions
Arduino/McLighting
|
@ -8,7 +8,7 @@
|
|||
// needed for library WiFiManager
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
|
||||
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
|
@ -41,7 +41,7 @@
|
|||
#ifdef ENABLE_HOMEASSISTANT
|
||||
#include <ArduinoJson.h>
|
||||
#endif
|
||||
|
||||
|
||||
AsyncMqttClient amqttClient;
|
||||
WiFiEventHandler wifiConnectHandler;
|
||||
WiFiEventHandler wifiDisconnectHandler;
|
||||
|
@ -92,7 +92,9 @@ Ticker ticker;
|
|||
Ticker mqttReconnectTimer;
|
||||
Ticker wifiReconnectTimer;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
Ticker spiffs_save_state;
|
||||
#endif
|
||||
void tick()
|
||||
{
|
||||
//toggle state
|
||||
|
@ -100,33 +102,33 @@ void tick()
|
|||
digitalWrite(BUILTIN_LED, !state); // set pin to the opposite state
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// EEPROM helper
|
||||
// ***************************************************************************
|
||||
String readEEPROM(int offset, int len) {
|
||||
String res = "";
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
res += char(EEPROM.read(i + offset));
|
||||
//DBG_OUTPUT_PORT.println(char(EEPROM.read(i + offset)));
|
||||
#ifdef ENABLE_STATE_SAVE_EEPROM
|
||||
// ***************************************************************************
|
||||
// EEPROM helper
|
||||
// ***************************************************************************
|
||||
String readEEPROM(int offset, int len) {
|
||||
String res = "";
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
res += char(EEPROM.read(i + offset));
|
||||
//DBG_OUTPUT_PORT.println(char(EEPROM.read(i + offset)));
|
||||
}
|
||||
DBG_OUTPUT_PORT.printf("readEEPROM(): %s\n", res.c_str());
|
||||
return res;
|
||||
}
|
||||
DBG_OUTPUT_PORT.printf("readEEPROM(): %s\n", res.c_str());
|
||||
return res;
|
||||
}
|
||||
|
||||
void writeEEPROM(int offset, int len, String value) {
|
||||
DBG_OUTPUT_PORT.printf("writeEEPROM(): %s\n", value.c_str());
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (i < value.length()) {
|
||||
EEPROM.write(i + offset, value[i]);
|
||||
} else {
|
||||
EEPROM.write(i + offset, NULL);
|
||||
|
||||
void writeEEPROM(int offset, int len, String value) {
|
||||
DBG_OUTPUT_PORT.printf("writeEEPROM(): %s\n", value.c_str());
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (i < value.length()) {
|
||||
EEPROM.write(i + offset, value[i]);
|
||||
} else {
|
||||
EEPROM.write(i + offset, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ***************************************************************************
|
||||
// Saved state handling
|
||||
|
@ -194,10 +196,10 @@ void saveConfigCallback () {
|
|||
// ***************************************************************************
|
||||
void setup() {
|
||||
// system_update_cpu_freq(160);
|
||||
|
||||
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
EEPROM.begin(512);
|
||||
|
||||
|
||||
// set builtin led pin as output
|
||||
pinMode(BUILTIN_LED, OUTPUT);
|
||||
// button pin setup
|
||||
|
@ -207,13 +209,30 @@ void setup() {
|
|||
// start ticker with 0.5 because we start in AP mode and try to connect
|
||||
ticker.attach(0.5, tick);
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: SPIFFS
|
||||
// ***************************************************************************
|
||||
SPIFFS.begin();
|
||||
{
|
||||
Dir dir = SPIFFS.openDir("/");
|
||||
while (dir.next()) {
|
||||
String fileName = dir.fileName();
|
||||
size_t fileSize = dir.fileSize();
|
||||
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
|
||||
}
|
||||
|
||||
FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
DBG_OUTPUT_PORT.printf("FS Usage: %d/%d bytes\n\n", fs_info.usedBytes, fs_info.totalBytes);
|
||||
}
|
||||
|
||||
wifi_station_set_hostname(const_cast<char*>(HOSTNAME));
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: Neopixel
|
||||
// ***************************************************************************
|
||||
strip.init();
|
||||
strip.setBrightness(brightness);
|
||||
strip.setBrightness(brightness);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
//strip.setMode(FX_MODE_RAINBOW_CYCLE);
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
|
@ -226,17 +245,21 @@ void setup() {
|
|||
// After connecting, parameter.getValue() will get you the configured value
|
||||
// id/name placeholder/prompt default length
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
String settings_available = readEEPROM(134, 1);
|
||||
if (settings_available == "1") {
|
||||
readEEPROM(0, 64).toCharArray(mqtt_host, 64); // 0-63
|
||||
readEEPROM(64, 6).toCharArray(mqtt_port, 6); // 64-69
|
||||
readEEPROM(70, 32).toCharArray(mqtt_user, 32); // 70-101
|
||||
readEEPROM(102, 32).toCharArray(mqtt_pass, 32); // 102-133
|
||||
DBG_OUTPUT_PORT.printf("MQTT host: %s\n", mqtt_host);
|
||||
DBG_OUTPUT_PORT.printf("MQTT port: %s\n", mqtt_port);
|
||||
DBG_OUTPUT_PORT.printf("MQTT user: %s\n", mqtt_user);
|
||||
DBG_OUTPUT_PORT.printf("MQTT pass: %s\n", mqtt_pass);
|
||||
}
|
||||
#if defined(ENABLE_STATE_SAVE_SPIFFS)
|
||||
(readConfigFS()) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Read success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Read failure!");
|
||||
#else
|
||||
String settings_available = readEEPROM(134, 1);
|
||||
if (settings_available == "1") {
|
||||
readEEPROM(0, 64).toCharArray(mqtt_host, 64); // 0-63
|
||||
readEEPROM(64, 6).toCharArray(mqtt_port, 6); // 64-69
|
||||
readEEPROM(70, 32).toCharArray(mqtt_user, 32); // 70-101
|
||||
readEEPROM(102, 32).toCharArray(mqtt_pass, 32); // 102-133
|
||||
DBG_OUTPUT_PORT.printf("MQTT host: %s\n", mqtt_host);
|
||||
DBG_OUTPUT_PORT.printf("MQTT port: %s\n", mqtt_port);
|
||||
DBG_OUTPUT_PORT.printf("MQTT user: %s\n", mqtt_user);
|
||||
DBG_OUTPUT_PORT.printf("MQTT pass: %s\n", mqtt_pass);
|
||||
}
|
||||
#endif
|
||||
WiFiManagerParameter custom_mqtt_host("host", "MQTT hostname", mqtt_host, 64);
|
||||
WiFiManagerParameter custom_mqtt_port("port", "MQTT port", mqtt_port, 6);
|
||||
WiFiManagerParameter custom_mqtt_user("user", "MQTT user", mqtt_user, 32);
|
||||
|
@ -254,7 +277,7 @@ void setup() {
|
|||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
//set config save notify callback
|
||||
wifiManager.setSaveConfigCallback(saveConfigCallback);
|
||||
|
||||
|
||||
//add all your parameters here
|
||||
wifiManager.addParameter(&custom_mqtt_host);
|
||||
wifiManager.addParameter(&custom_mqtt_port);
|
||||
|
@ -283,18 +306,22 @@ void setup() {
|
|||
strcpy(mqtt_pass, custom_mqtt_pass.getValue());
|
||||
|
||||
//save the custom parameters to FS
|
||||
if (shouldSaveConfig) {
|
||||
DBG_OUTPUT_PORT.println("Saving WiFiManager config");
|
||||
#if defined(ENABLE_STATE_SAVE_SPIFFS)
|
||||
(writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!");
|
||||
#else if defined(ENABLE_STATE_SAVE_EEPROM)
|
||||
if (shouldSaveConfig) {
|
||||
DBG_OUTPUT_PORT.println("Saving WiFiManager config");
|
||||
|
||||
writeEEPROM(0, 64, mqtt_host); // 0-63
|
||||
writeEEPROM(64, 6, mqtt_port); // 64-69
|
||||
writeEEPROM(70, 32, mqtt_user); // 70-101
|
||||
writeEEPROM(102, 32, mqtt_pass); // 102-133
|
||||
writeEEPROM(134, 1, "1"); // 134 --> always "1"
|
||||
EEPROM.commit();
|
||||
}
|
||||
writeEEPROM(0, 64, mqtt_host); // 0-63
|
||||
writeEEPROM(64, 6, mqtt_port); // 64-69
|
||||
writeEEPROM(70, 32, mqtt_user); // 70-101
|
||||
writeEEPROM(102, 32, mqtt_pass); // 102-133
|
||||
writeEEPROM(134, 1, "1"); // 134 --> always "1"
|
||||
EEPROM.commit();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
|
||||
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
|
||||
|
@ -312,20 +339,20 @@ void setup() {
|
|||
// ***************************************************************************
|
||||
#ifdef ENABLE_OTA
|
||||
DBG_OUTPUT_PORT.println("Arduino OTA activated.");
|
||||
|
||||
|
||||
// Port defaults to 8266
|
||||
ArduinoOTA.setPort(8266);
|
||||
|
||||
|
||||
// Hostname defaults to esp8266-[ChipID]
|
||||
ArduinoOTA.setHostname(HOSTNAME);
|
||||
|
||||
|
||||
// No authentication by default
|
||||
// ArduinoOTA.setPassword("admin");
|
||||
|
||||
|
||||
// Password can be set with it's md5 value as well
|
||||
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
|
||||
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
|
||||
|
||||
|
||||
ArduinoOTA.onStart([]() {
|
||||
DBG_OUTPUT_PORT.println("Arduino OTA: Start updating");
|
||||
});
|
||||
|
@ -343,7 +370,7 @@ void setup() {
|
|||
else if (error == OTA_RECEIVE_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Receive Failed");
|
||||
else if (error == OTA_END_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: End Failed");
|
||||
});
|
||||
|
||||
|
||||
ArduinoOTA.begin();
|
||||
DBG_OUTPUT_PORT.println("");
|
||||
#endif
|
||||
|
@ -356,16 +383,16 @@ void setup() {
|
|||
if (mqtt_host != "" && String(mqtt_port).toInt() > 0) {
|
||||
snprintf(mqtt_intopic, sizeof mqtt_intopic, "%s/in", HOSTNAME);
|
||||
snprintf(mqtt_outtopic, sizeof mqtt_outtopic, "%s/out", HOSTNAME);
|
||||
|
||||
|
||||
DBG_OUTPUT_PORT.printf("MQTT active: %s:%d\n", mqtt_host, String(mqtt_port).toInt());
|
||||
|
||||
|
||||
mqtt_client.setServer(mqtt_host, String(mqtt_port).toInt());
|
||||
mqtt_client.setCallback(mqtt_callback);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
if (mqtt_host != "" && String(mqtt_port).toInt() > 0) {
|
||||
if (mqtt_host != "" && String(mqtt_port).toInt() > 0) {
|
||||
amqttClient.onConnect(onMqttConnect);
|
||||
amqttClient.onDisconnect(onMqttDisconnect);
|
||||
amqttClient.onMessage(onMqttMessage);
|
||||
|
@ -376,9 +403,9 @@ void setup() {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
ha_send_data.attach(5, sendState); // Send HA data back only every 5 sec
|
||||
#endif
|
||||
// #ifdef ENABLE_HOMEASSISTANT
|
||||
// ha_send_data.attach(5, tickerSendState); // Send HA data back only every 5 sec
|
||||
// #endif
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: MDNS responder
|
||||
|
@ -395,10 +422,10 @@ void setup() {
|
|||
|
||||
DBG_OUTPUT_PORT.print("New users: Open http://");
|
||||
DBG_OUTPUT_PORT.print(WiFi.localIP());
|
||||
DBG_OUTPUT_PORT.println("/upload to upload the webpages first.");
|
||||
DBG_OUTPUT_PORT.println("/upload to upload the webpages first.");
|
||||
|
||||
DBG_OUTPUT_PORT.println("");
|
||||
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: WebSocket server
|
||||
|
@ -406,24 +433,6 @@ void setup() {
|
|||
webSocket.begin();
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: SPIFFS
|
||||
// ***************************************************************************
|
||||
SPIFFS.begin();
|
||||
{
|
||||
Dir dir = SPIFFS.openDir("/");
|
||||
while (dir.next()) {
|
||||
String fileName = dir.fileName();
|
||||
size_t fileSize = dir.fileSize();
|
||||
DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
|
||||
}
|
||||
|
||||
FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
DBG_OUTPUT_PORT.printf("FS Usage: %d/%d bytes\n\n", fs_info.usedBytes, fs_info.totalBytes);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: SPIFFS Webserver handler
|
||||
// ***************************************************************************
|
||||
|
@ -515,14 +524,14 @@ void setup() {
|
|||
DBG_OUTPUT_PORT.print("/get_brightness: ");
|
||||
DBG_OUTPUT_PORT.println(str_brightness);
|
||||
});
|
||||
|
||||
|
||||
server.on("/set_speed", []() {
|
||||
if (server.arg("d").toInt() >= 0) {
|
||||
ws2812fx_speed = server.arg("d").toInt();
|
||||
ws2812fx_speed = constrain(ws2812fx_speed, 0, 255);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
}
|
||||
|
||||
|
||||
getStatusJSON();
|
||||
});
|
||||
|
||||
|
@ -616,17 +625,19 @@ void setup() {
|
|||
});
|
||||
|
||||
#ifdef HTTP_OTA
|
||||
httpUpdater.setup(&server, "/firmware", "admin", "allforfun");
|
||||
httpUpdater.setup(&server, "/update");
|
||||
#endif
|
||||
|
||||
|
||||
server.begin();
|
||||
|
||||
// Start MDNS service
|
||||
if (mdns_result) {
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_STATE_SAVE
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
(readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!");
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_EEPROM
|
||||
// Load state string from EEPROM
|
||||
String saved_state_string = readEEPROM(256, 32);
|
||||
String chk = getValue(saved_state_string, '|', 0);
|
||||
|
@ -642,10 +653,10 @@ void setup() {
|
|||
void loop() {
|
||||
#ifdef ENABLE_BUTTON
|
||||
button();
|
||||
#endif
|
||||
#endif
|
||||
server.handleClient();
|
||||
webSocket.loop();
|
||||
|
||||
|
||||
#ifdef ENABLE_OTA
|
||||
ArduinoOTA.handle();
|
||||
#endif
|
||||
|
@ -667,14 +678,18 @@ void loop() {
|
|||
ha_send_data.detach();
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.println("MQTT disconnected, reconnecting!");
|
||||
mqtt_reconnect();
|
||||
mqtt_reconnect();
|
||||
} else {
|
||||
mqtt_client.loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
// if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
if (new_ha_mqtt_msg) sendState();
|
||||
#endif
|
||||
|
||||
// Simple statemachine that handles the different modes
|
||||
if (mode == SET_MODE) {
|
||||
DBG_OUTPUT_PORT.printf("SET_MODE: %d %d\n", ws2812fx_mode, mode);
|
||||
|
@ -682,8 +697,9 @@ void loop() {
|
|||
mode = HOLD;
|
||||
}
|
||||
if (mode == OFF) {
|
||||
strip.setColor(0,0,0);
|
||||
strip.setMode(FX_MODE_STATIC);
|
||||
// strip.setColor(0,0,0);
|
||||
// strip.setMode(FX_MODE_STATIC);
|
||||
if(strip.isRunning()) strip.stop(); //should clear memory
|
||||
// mode = HOLD;
|
||||
}
|
||||
if (mode == ALL) {
|
||||
|
@ -727,11 +743,13 @@ void loop() {
|
|||
mode = HOLD;
|
||||
}
|
||||
if (mode == HOLD || mode == CUSTOM) {
|
||||
if(!strip.isRunning()) strip.start();
|
||||
if (exit_func) {
|
||||
exit_func = false;
|
||||
}
|
||||
}
|
||||
if (mode == TV) {
|
||||
if(!strip.isRunning()) strip.start();
|
||||
tv();
|
||||
}
|
||||
|
||||
|
@ -740,11 +758,16 @@ void loop() {
|
|||
strip.service();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if (updateStateFS) {
|
||||
(writeStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_STATE_SAVE
|
||||
#ifdef ENABLE_STATE_SAVE_EEPROM
|
||||
// Check for state changes
|
||||
sprintf(current_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d", mode, strip.getMode(), ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue);
|
||||
|
||||
|
||||
if (strcmp(current_state, last_state) != 0) {
|
||||
// DBG_OUTPUT_PORT.printf("STATE CHANGED: %s / %s\n", last_state, current_state);
|
||||
strcpy(last_state, current_state);
|
||||
|
|
|
@ -32,15 +32,18 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
|
|||
#ifdef ENABLE_MQTT
|
||||
#define MQTT_MAX_PACKET_SIZE 512
|
||||
#define MQTT_MAX_RECONNECT_TRIES 4
|
||||
|
||||
|
||||
int mqtt_reconnect_retries = 0;
|
||||
char mqtt_intopic[strlen(HOSTNAME) + 4 + 5]; // Topic in will be: <HOSTNAME>/in
|
||||
char mqtt_outtopic[strlen(HOSTNAME) + 5 + 5]; // Topic out will be: <HOSTNAME>/out
|
||||
uint8_t qossub = 0; // PubSubClient can sub qos 0 or 1
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
String mqtt_intopic = String(HOSTNAME) + "/in";
|
||||
String mqtt_outtopic = String(HOSTNAME) + "/out";
|
||||
uint8_t qossub = 0; // AMQTT can sub qos 0 or 1 or 2
|
||||
uint8_t qospub = 0; // AMQTT can pub qos 0 or 1 or 2
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
|
@ -48,17 +51,17 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
|
|||
String mqtt_ha_state_in = mqtt_ha + "state/in";
|
||||
String mqtt_ha_state_out = mqtt_ha + "state/out";
|
||||
String mqtt_ha_speed = mqtt_ha + "speed";
|
||||
|
||||
|
||||
const char* on_cmd = "ON";
|
||||
const char* off_cmd = "OFF";
|
||||
bool stateOn = false;
|
||||
bool animation_on = false;
|
||||
bool new_ha_mqtt_msg = true;
|
||||
bool new_ha_mqtt_msg = false;
|
||||
uint16_t color_temp = 327; // min is 154 and max is 500
|
||||
#endif
|
||||
|
||||
|
||||
const char mqtt_clientid[] = "NeoPixelStrip01"; // MQTT ClientID
|
||||
|
||||
|
||||
char mqtt_host[64] = "";
|
||||
char mqtt_port[6] = "";
|
||||
char mqtt_user[32] = "";
|
||||
|
@ -97,14 +100,18 @@ typedef struct ledstate LEDState; // Define the datatype LEDState
|
|||
LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip
|
||||
LEDState main_color = { 255, 0, 0 }; // Store the "main color" of the strip used in single color modes
|
||||
|
||||
#define ENABLE_STATE_SAVE // If defined, save state on reboot
|
||||
#ifdef ENABLE_STATE_SAVE
|
||||
#define ENABLE_STATE_SAVE_SPIFFS // If defined, saves state on SPIFFS
|
||||
//#define ENABLE_STATE_SAVE_EEPROM // If defined, save state on reboot
|
||||
#ifdef ENABLE_STATE_SAVE_EEPROM
|
||||
char current_state[32]; // Keeps the current state representation
|
||||
char last_state[32]; // Save the last state as string representation
|
||||
unsigned long time_statechange = 0; // Time when the state last changed
|
||||
int timeout_statechange_save = 5000; // Timeout in ms to wait before state is saved
|
||||
bool state_save_requested = false; // State has to be saved after timeout
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
bool updateStateFS = false;
|
||||
#endif
|
||||
|
||||
// Button handling
|
||||
#ifdef ENABLE_BUTTON
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
// ***************************************************************************
|
||||
// Request handlers
|
||||
// ***************************************************************************
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
void tickerSendState(){
|
||||
new_ha_mqtt_msg = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
void tickerSpiffsSaveState(){
|
||||
updateStateFS = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void getArgs() {
|
||||
if (server.arg("rgb") != "") {
|
||||
uint32_t rgb = (uint32_t) strtol(server.arg("rgb").c_str(), NULL, 16);
|
||||
|
@ -190,7 +201,7 @@ void handleSetNamedMode(String str_mode) {
|
|||
exit_func = true;
|
||||
|
||||
if (str_mode.startsWith("=off")) {
|
||||
mode = OFF;
|
||||
mode = OFF;
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = false;
|
||||
#endif
|
||||
|
@ -383,7 +394,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -405,7 +419,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -415,7 +432,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -447,7 +467,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
DBG_OUTPUT_PORT.printf("Activated mode [%u]!\n", mode);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -475,7 +498,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -513,7 +539,7 @@ void checkForRequests() {
|
|||
LEDState temp2rgb(unsigned int kelvin) {
|
||||
int tmp_internal = kelvin / 100.0;
|
||||
LEDState tmp_color;
|
||||
|
||||
|
||||
// red
|
||||
if (tmp_internal <= 66) {
|
||||
tmp_color.red = 255;
|
||||
|
@ -527,7 +553,7 @@ void checkForRequests() {
|
|||
tmp_color.red = tmp_red;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// green
|
||||
if (tmp_internal <= 66) {
|
||||
float tmp_green = 99.4708025861 * log(tmp_internal) - 161.1195681661;
|
||||
|
@ -548,7 +574,7 @@ void checkForRequests() {
|
|||
tmp_color.green = tmp_green;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// blue
|
||||
if (tmp_internal >= 66) {
|
||||
tmp_color.blue = 255;
|
||||
|
@ -568,47 +594,47 @@ void checkForRequests() {
|
|||
}
|
||||
|
||||
void sendState() {
|
||||
if (new_ha_mqtt_msg) {
|
||||
const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5);
|
||||
//StaticJsonBuffer<bufferSize> jsonBuffer;
|
||||
DynamicJsonBuffer jsonBuffer(bufferSize);
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
root["state"] = (stateOn) ? on_cmd : off_cmd;
|
||||
JsonObject& color = root.createNestedObject("color");
|
||||
color["r"] = main_color.red;
|
||||
color["g"] = main_color.green;
|
||||
color["b"] = main_color.blue;
|
||||
|
||||
root["brightness"] = brightness;
|
||||
|
||||
root["color_temp"] = color_temp;
|
||||
|
||||
char modeName[30];
|
||||
strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem
|
||||
root["effect"] = modeName;
|
||||
|
||||
char buffer[root.measureLength() + 1];
|
||||
root.printTo(buffer, sizeof(buffer));
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_ha_state_out.c_str(), buffer, true);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out.c_str(), buffer);
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_ha_state_out.c_str(), 1, true, buffer);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out.c_str(), buffer);
|
||||
#endif
|
||||
new_ha_mqtt_msg = false;
|
||||
}
|
||||
const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5);
|
||||
//StaticJsonBuffer<bufferSize> jsonBuffer;
|
||||
DynamicJsonBuffer jsonBuffer(bufferSize);
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
root["state"] = (stateOn) ? on_cmd : off_cmd;
|
||||
JsonObject& color = root.createNestedObject("color");
|
||||
color["r"] = main_color.red;
|
||||
color["g"] = main_color.green;
|
||||
color["b"] = main_color.blue;
|
||||
|
||||
root["brightness"] = brightness;
|
||||
|
||||
root["color_temp"] = color_temp;
|
||||
|
||||
char modeName[30];
|
||||
strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem
|
||||
root["effect"] = modeName;
|
||||
|
||||
char buffer[root.measureLength() + 1];
|
||||
root.printTo(buffer, sizeof(buffer));
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_ha_state_out.c_str(), buffer, true);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out.c_str(), buffer);
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_ha_state_out.c_str(), 1, true, buffer);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out.c_str(), buffer);
|
||||
#endif
|
||||
new_ha_mqtt_msg = false;
|
||||
ha_send_data.detach();
|
||||
DBG_OUTPUT_PORT.printf("Heap size: %u\n", ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
|
||||
bool processJson(char* message) {
|
||||
const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + 150;
|
||||
//StaticJsonBuffer<bufferSize> jsonBuffer;
|
||||
DynamicJsonBuffer jsonBuffer(bufferSize);
|
||||
JsonObject& root = jsonBuffer.parseObject(message);
|
||||
|
||||
|
||||
if (!root.success()) {
|
||||
DBG_OUTPUT_PORT.println("parseObject() failed");
|
||||
return false;
|
||||
|
@ -636,7 +662,7 @@ void checkForRequests() {
|
|||
main_color.blue = (uint8_t) color["b"];
|
||||
mode = SETCOLOR;
|
||||
}
|
||||
|
||||
|
||||
if (root.containsKey("color_temp")) {
|
||||
//temp comes in as mireds, need to convert to kelvin then to RGB
|
||||
color_temp = (uint16_t) root["color_temp"];
|
||||
|
@ -644,14 +670,14 @@ void checkForRequests() {
|
|||
main_color = temp2rgb(kelvin);
|
||||
mode = SETCOLOR;
|
||||
}
|
||||
|
||||
|
||||
if (root.containsKey("brightness")) {
|
||||
const char * brightness_json = root["brightness"];
|
||||
uint8_t b = (uint8_t) strtol((const char *) &brightness_json[0], NULL, 10);
|
||||
brightness = constrain(b, 0, 255);
|
||||
mode = BRIGHTNESS;
|
||||
}
|
||||
|
||||
|
||||
if (root.containsKey("effect")) {
|
||||
animation_on = true;
|
||||
String effectString = root["effect"].asString();
|
||||
|
@ -678,7 +704,7 @@ void checkForRequests() {
|
|||
payload[length] = NULL;
|
||||
DBG_OUTPUT_PORT.printf("]: %s\n", payload);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
void mqtt_callback(char* topic, byte* payload_in, unsigned int length) {
|
||||
uint8_t * payload = (uint8_t *)malloc(length + 1);
|
||||
|
@ -691,8 +717,11 @@ void checkForRequests() {
|
|||
if (!processJson((char*)payload)) {
|
||||
return;
|
||||
}
|
||||
new_ha_mqtt_msg = true;
|
||||
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
|
||||
} else if (strcmp(topic, mqtt_ha_speed.c_str()) == 0) {
|
||||
uint8_t d = (uint8_t) strtol((const char *) &payload[0], NULL, 10);
|
||||
ws2812fx_speed = constrain(d, 0, 255);
|
||||
|
@ -704,7 +733,7 @@ void checkForRequests() {
|
|||
} else if (strcmp(topic, mqtt_intopic.c_str()) == 0) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// # ==> Set main color
|
||||
if (payload[0] == '#') {
|
||||
handleSetMainColor(payload);
|
||||
|
@ -713,14 +742,17 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ? ==> Set speed
|
||||
if (payload[0] == '?') {
|
||||
uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10);
|
||||
|
@ -731,10 +763,10 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// % ==> Set brightness
|
||||
if (payload[0] == '%') {
|
||||
uint8_t b = (uint8_t) strtol((const char *) &payload[1], NULL, 10);
|
||||
|
@ -745,14 +777,17 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// * ==> Set main color and light all LEDs (Shortcut)
|
||||
if (payload[0] == '*') {
|
||||
handleSetAllMode(payload);
|
||||
|
@ -761,14 +796,17 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ! ==> Set single LED in given color
|
||||
if (payload[0] == '!') {
|
||||
handleSetSingleLED(payload, 1);
|
||||
|
@ -777,10 +815,10 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// + ==> Set multiple LED in the given colors
|
||||
if (payload[0] == '+') {
|
||||
handleSetDifferentColors(payload);
|
||||
|
@ -788,10 +826,10 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// R ==> Set range of LEDs in the given colors
|
||||
if (payload[0] == 'R') {
|
||||
handleRangeDifferentColors(payload);
|
||||
|
@ -800,10 +838,10 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// = ==> Activate named mode
|
||||
if (payload[0] == '=') {
|
||||
String str_mode = String((char *) &payload[0]);
|
||||
|
@ -813,13 +851,16 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// $ ==> Get status Info.
|
||||
if (payload[0] == '$') {
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Get status info.\n");
|
||||
|
@ -829,10 +870,10 @@ void checkForRequests() {
|
|||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
String liststat = (String) listStatusJSON();
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, liststat.c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, liststat.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ~ ==> Get WS2812 modes.
|
||||
// TODO: Fix this, doesn't return anything. Too long?
|
||||
// Hint: https://github.com/knolleary/pubsubclient/issues/110
|
||||
|
@ -843,15 +884,15 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, "ERROR: Not implemented. Message too large for pubsubclient.");
|
||||
//String json_modes = listModesJSON();
|
||||
//DBG_OUTPUT_PORT.printf(json_modes.c_str());
|
||||
|
||||
|
||||
//int res = mqtt_client.publish(mqtt_outtopic, json_modes.c_str(), json_modes.length());
|
||||
//DBG_OUTPUT_PORT.printf("Result: %d / %d", res, json_modes.length());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String("ERROR: Not implemented. Message too large for AsyncMQTT.").c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("ERROR: Not implemented. Message too large for AsyncMQTT.").c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// / ==> Set WS2812 mode.
|
||||
if (payload[0] == '/') {
|
||||
handleSetWS2812FXMode(payload);
|
||||
|
@ -860,11 +901,14 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -889,13 +933,13 @@ void checkForRequests() {
|
|||
strcat(message, HOSTNAME);
|
||||
mqtt_client.publish(mqtt_outtopic, message);
|
||||
// ... and resubscribe
|
||||
mqtt_client.subscribe(mqtt_intopic);
|
||||
mqtt_client.subscribe(mqtt_intopic, qossub, qossub);
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
ha_send_data.attach(5, sendState); // Send HA data back only every 5 sec
|
||||
mqtt_client.subscribe(mqtt_ha_state_in.c_str());
|
||||
mqtt_client.subscribe(mqtt_ha_speed.c_str());
|
||||
ha_send_data.detach();
|
||||
mqtt_client.subscribe(mqtt_ha_state_in.c_str(), qossub);
|
||||
mqtt_client.subscribe(mqtt_ha_speed.c_str(), qossub);
|
||||
#endif
|
||||
|
||||
|
||||
DBG_OUTPUT_PORT.printf("MQTT topic in: %s\n", mqtt_intopic);
|
||||
DBG_OUTPUT_PORT.printf("MQTT topic out: %s\n", mqtt_outtopic);
|
||||
} else {
|
||||
|
@ -923,12 +967,12 @@ void checkForRequests() {
|
|||
DBG_OUTPUT_PORT.println("Connecting to MQTT...");
|
||||
amqttClient.connect();
|
||||
}
|
||||
|
||||
|
||||
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
|
||||
DBG_OUTPUT_PORT.println("Connected to Wi-Fi.");
|
||||
connectToMqtt();
|
||||
}
|
||||
|
||||
|
||||
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
|
||||
DBG_OUTPUT_PORT.println("Disconnected from Wi-Fi.");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
|
@ -937,7 +981,7 @@ void checkForRequests() {
|
|||
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
|
||||
wifiReconnectTimer.once(2, connectToWifi);
|
||||
}
|
||||
|
||||
|
||||
void onMqttConnect(bool sessionPresent) {
|
||||
DBG_OUTPUT_PORT.println("Connected to MQTT.");
|
||||
DBG_OUTPUT_PORT.print("Session present: ");
|
||||
|
@ -945,19 +989,19 @@ void checkForRequests() {
|
|||
char * message = new char[18 + strlen(HOSTNAME) + 1];
|
||||
strcpy(message, "McLighting ready: ");
|
||||
strcat(message, HOSTNAME);
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, message);
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, message);
|
||||
//Subscribe
|
||||
uint16_t packetIdSub1 = amqttClient.subscribe((char *)mqtt_intopic.c_str(),1);
|
||||
DBG_OUTPUT_PORT.print("Subscribing at QoS 1, packetId: "); DBG_OUTPUT_PORT.println(packetIdSub1);
|
||||
uint16_t packetIdSub1 = amqttClient.subscribe((char *)mqtt_intopic.c_str(), qossub);
|
||||
DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub1);
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
ha_send_data.attach(5, sendState); // Send HA data back only every 5 sec
|
||||
uint16_t packetIdSub2 = amqttClient.subscribe((char *)mqtt_ha_state_in.c_str(), 1);
|
||||
DBG_OUTPUT_PORT.print("Subscribing at QoS 1, packetId: "); DBG_OUTPUT_PORT.println(packetIdSub2);
|
||||
uint16_t packetIdSub3 = amqttClient.subscribe((char *)mqtt_ha_speed.c_str(), 1);
|
||||
DBG_OUTPUT_PORT.print("Subscribing at QoS 1, packetId: "); DBG_OUTPUT_PORT.println(packetIdSub3);
|
||||
ha_send_data.detach();
|
||||
uint16_t packetIdSub2 = amqttClient.subscribe((char *)mqtt_ha_state_in.c_str(), qossub);
|
||||
DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub2);
|
||||
uint16_t packetIdSub3 = amqttClient.subscribe((char *)mqtt_ha_speed.c_str(), qossub);
|
||||
DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub3);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
||||
DBG_OUTPUT_PORT.print("Disconnected from MQTT, reason: ");
|
||||
if (reason == AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT) {
|
||||
|
@ -980,7 +1024,7 @@ void checkForRequests() {
|
|||
if (WiFi.isConnected()) {
|
||||
mqttReconnectTimer.once(5, connectToMqtt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1004,15 +1048,18 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String("OK =off").c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = false;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// called when button is kept pressed for less than 2 seconds
|
||||
void mediumKeyPress() {
|
||||
DBG_OUTPUT_PORT.printf("Medium button press\n");
|
||||
|
@ -1021,14 +1068,17 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String("OK =fire flicker").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String("OK =fire flicker").c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =fire flicker").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// called when button is kept pressed for 2 seconds or more
|
||||
void longKeyPress() {
|
||||
DBG_OUTPUT_PORT.printf("Long button press\n");
|
||||
|
@ -1037,20 +1087,23 @@ void checkForRequests() {
|
|||
mqtt_client.publish(mqtt_outtopic, String("OK =fireworks random").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), 1, false, String("OK =fireworks random").c_str());
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =fireworks random").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
new_ha_mqtt_msg = true;
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void button() {
|
||||
if (millis() - keyPrevMillis >= keySampleIntervalMs) {
|
||||
keyPrevMillis = millis();
|
||||
|
||||
|
||||
byte currKeyState = digitalRead(BUTTON);
|
||||
|
||||
|
||||
if ((prevKeyState == HIGH) && (currKeyState == LOW)) {
|
||||
// key goes from not pressed to pressed
|
||||
KeyPressCount = 0;
|
||||
|
@ -1074,4 +1127,150 @@ void checkForRequests() {
|
|||
prevKeyState = currKeyState;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
bool updateFS = false;
|
||||
// Write configuration to FS JSON
|
||||
bool writeConfigFS(bool saveConfig){
|
||||
if (saveConfig) {
|
||||
//FS save
|
||||
updateFS = true;
|
||||
DBG_OUTPUT_PORT.print("Saving config: ");
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(4));
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(4)> jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.createObject();
|
||||
json["mqtt_host"] = mqtt_host;
|
||||
json["mqtt_port"] = mqtt_port;
|
||||
json["mqtt_user"] = mqtt_user;
|
||||
json["mqtt_pass"] = mqtt_pass;
|
||||
|
||||
// SPIFFS.remove("/config.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
|
||||
File configFile = SPIFFS.open("/config.json", "w");
|
||||
if (!configFile) DBG_OUTPUT_PORT.println("failed to open config file for writing");
|
||||
|
||||
json.printTo(DBG_OUTPUT_PORT);
|
||||
json.printTo(configFile);
|
||||
configFile.close();
|
||||
updateFS = false;
|
||||
return true;
|
||||
//end save
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("SaveConfig is False!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Read search_str to FS
|
||||
bool readConfigFS() {
|
||||
//read configuration from FS JSON
|
||||
updateFS = true;
|
||||
if (SPIFFS.exists("/config.json")) {
|
||||
//file exists, reading and loading
|
||||
DBG_OUTPUT_PORT.print("Reading config file... ");
|
||||
File configFile = SPIFFS.open("/config.json", "r");
|
||||
if (configFile) {
|
||||
DBG_OUTPUT_PORT.println("Opened!");
|
||||
size_t size = configFile.size();
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
configFile.readBytes(buf.get(), size);
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(4)+300);
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(4)+300> jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.parseObject(buf.get());
|
||||
DBG_OUTPUT_PORT.print("Config: ");
|
||||
json.printTo(DBG_OUTPUT_PORT);
|
||||
if (json.success()) {
|
||||
DBG_OUTPUT_PORT.println(" Parsed!");
|
||||
strcpy(mqtt_host, json["mqtt_host"]);
|
||||
strcpy(mqtt_port, json["mqtt_port"]);
|
||||
strcpy(mqtt_user, json["mqtt_user"]);
|
||||
strcpy(mqtt_pass, json["mqtt_pass"]);
|
||||
updateFS = false;
|
||||
return true;
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Failed to load json config");
|
||||
}
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Failed to open /config.json");
|
||||
}
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Coudnt find config.json");
|
||||
}
|
||||
//end read
|
||||
updateFS = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool writeStateFS(){
|
||||
updateFS = true;
|
||||
//save the strip state to FS JSON
|
||||
DBG_OUTPUT_PORT.print("Saving cfg: ");
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(6));
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(6)> jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.createObject();
|
||||
json["mode"] = static_cast<int>(mode);
|
||||
json["strip_mode"] = (int) strip.getMode();
|
||||
json["brightness"] = brightness;
|
||||
json["red"] = main_color.red;
|
||||
json["green"] = main_color.green;
|
||||
json["blue"] = main_color.blue;
|
||||
|
||||
// SPIFFS.remove("/state.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
|
||||
File configFile = SPIFFS.open("/stripstate.json", "w");
|
||||
if (!configFile) {
|
||||
DBG_OUTPUT_PORT.println("Failed!");
|
||||
updateFS = false;
|
||||
spiffs_save_state.detach();
|
||||
updateStateFS = false;
|
||||
return false;
|
||||
}
|
||||
json.printTo(DBG_OUTPUT_PORT);
|
||||
json.printTo(configFile);
|
||||
configFile.close();
|
||||
updateFS = false;
|
||||
spiffs_save_state.detach();
|
||||
updateStateFS = false;
|
||||
return true;
|
||||
//end save
|
||||
}
|
||||
|
||||
bool readStateFS() {
|
||||
//read strip state from FS JSON
|
||||
updateFS = true;
|
||||
//if (resetsettings) { SPIFFS.begin(); SPIFFS.remove("/config.json"); SPIFFS.format(); delay(1000);}
|
||||
if (SPIFFS.exists("/stripstate.json")) {
|
||||
//file exists, reading and loading
|
||||
DBG_OUTPUT_PORT.print("Read cfg: ");
|
||||
File configFile = SPIFFS.open("/stripstate.json", "r");
|
||||
if (configFile) {
|
||||
size_t size = configFile.size();
|
||||
// Allocate a buffer to store contents of the file.
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
configFile.readBytes(buf.get(), size);
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(6)+170);
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(6)+170> jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.parseObject(buf.get());
|
||||
json.printTo(DBG_OUTPUT_PORT);
|
||||
if (json.success()) {
|
||||
mode = static_cast<MODE>((int) json["mode"]);
|
||||
ws2812fx_mode = json["strip_mode"];
|
||||
brightness = json["brightness"];
|
||||
main_color.red = json["red"];
|
||||
main_color.green = json["green"];
|
||||
main_color.blue = json["blue"];
|
||||
updateFS = false;
|
||||
return true;
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Failed to parse JSON!");
|
||||
}
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Failed to open \"/stripstate.json\"");
|
||||
}
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Coudnt find \"/stripstate.json\"");
|
||||
}
|
||||
//end read
|
||||
updateFS = false;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue