Merge branch 'debsahu/master'
Support for AMQTT, NEOANIMATIONFX
This commit is contained in:
commit
9b7ca2ac47
4 changed files with 1157 additions and 396 deletions
|
@ -35,6 +35,18 @@
|
|||
PubSubClient mqtt_client(espClient);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
#include <AsyncMqttClient.h> //https://github.com/marvinroger/async-mqtt-client
|
||||
//https://github.com/me-no-dev/ESPAsyncTCP
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
#include <ArduinoJson.h>
|
||||
#endif
|
||||
|
||||
AsyncMqttClient amqttClient;
|
||||
WiFiEventHandler wifiConnectHandler;
|
||||
WiFiEventHandler wifiDisconnectHandler;
|
||||
#endif
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Instanciate HTTP(80) / WebSockets(81) Server
|
||||
|
@ -43,10 +55,29 @@ ESP8266WebServer server(80);
|
|||
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||
|
||||
#ifdef HTTP_OTA
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEOANIMATIONFX
|
||||
// ***************************************************************************
|
||||
// Load libraries / Instanciate NeoAnimationFX library
|
||||
// ***************************************************************************
|
||||
// https://github.com/debsahu/NeoAnimationFX
|
||||
#include <NeoAnimationFX.h>
|
||||
#define NEOMETHOD NeoPBBGRB800
|
||||
|
||||
NEOMETHOD neoStrip(NUMLEDS);
|
||||
NeoAnimationFX<NEOMETHOD> strip(neoStrip);
|
||||
|
||||
// Uses Pin RX / GPIO3 (Only pin that is supported, due to hardware limitations)
|
||||
// NEOMETHOD NeoPBBGRB800 uses GRB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
||||
// NEOMETHOD NeoPBBGRB400 uses GRB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||
// NEOMETHOD NeoPBBRGB800 uses RGB config 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
|
||||
// NEOMETHOD NeoPBBRGB400 uses RGB config 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||
#endif
|
||||
|
||||
#ifdef USE_WS2812FX
|
||||
// ***************************************************************************
|
||||
// Load libraries / Instanciate WS2812FX library
|
||||
// ***************************************************************************
|
||||
|
@ -66,14 +97,23 @@ WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800);
|
|||
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
|
||||
// and minimize distance between Arduino and first pixel. Avoid connecting
|
||||
// on a live circuit...if you must, connect GND first.
|
||||
|
||||
#endif
|
||||
|
||||
// ***************************************************************************
|
||||
// Load library "ticker" for blinking status led
|
||||
// ***************************************************************************
|
||||
#include <Ticker.h>
|
||||
Ticker ticker;
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
Ticker ha_send_data;
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
Ticker mqttReconnectTimer;
|
||||
Ticker wifiReconnectTimer;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
Ticker spiffs_save_state;
|
||||
#endif
|
||||
void tick()
|
||||
{
|
||||
//toggle state
|
||||
|
@ -81,11 +121,11 @@ void tick()
|
|||
digitalWrite(BUILTIN_LED, !state); // set pin to the opposite state
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// EEPROM helper
|
||||
// ***************************************************************************
|
||||
String readEEPROM(int offset, int len) {
|
||||
#ifdef ENABLE_STATE_SAVE_EEPROM
|
||||
// ***************************************************************************
|
||||
// EEPROM helper
|
||||
// ***************************************************************************
|
||||
String readEEPROM(int offset, int len) {
|
||||
String res = "";
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
|
@ -94,9 +134,9 @@ String readEEPROM(int offset, int len) {
|
|||
}
|
||||
DBG_OUTPUT_PORT.printf("readEEPROM(): %s\n", res.c_str());
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void writeEEPROM(int offset, int len, String value) {
|
||||
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)
|
||||
{
|
||||
|
@ -106,8 +146,8 @@ void writeEEPROM(int offset, int len, String value) {
|
|||
EEPROM.write(i + offset, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// ***************************************************************************
|
||||
// Saved state handling
|
||||
|
@ -130,7 +170,6 @@ String getValue(String data, char separator, int index)
|
|||
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Callback for WiFiManager library when config mode is entered
|
||||
// ***************************************************************************
|
||||
|
@ -171,12 +210,12 @@ void saveConfigCallback () {
|
|||
// ***************************************************************************
|
||||
#include "colormodes.h"
|
||||
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// MAIN
|
||||
// ***************************************************************************
|
||||
void setup() {
|
||||
// system_update_cpu_freq(160);
|
||||
|
||||
DBG_OUTPUT_PORT.begin(115200);
|
||||
EEPROM.begin(512);
|
||||
|
||||
|
@ -189,6 +228,23 @@ 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));
|
||||
|
||||
// ***************************************************************************
|
||||
|
@ -207,7 +263,10 @@ void setup() {
|
|||
// The extra parameters to be configured (can be either global or just in the setup)
|
||||
// After connecting, parameter.getValue() will get you the configured value
|
||||
// id/name placeholder/prompt default length
|
||||
#ifdef ENABLE_MQTT
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
#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
|
||||
|
@ -219,7 +278,7 @@ void setup() {
|
|||
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);
|
||||
|
@ -234,7 +293,7 @@ void setup() {
|
|||
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
|
||||
wifiManager.setAPCallback(configModeCallback);
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
//set config save notify callback
|
||||
wifiManager.setSaveConfigCallback(saveConfigCallback);
|
||||
|
||||
|
@ -245,6 +304,8 @@ void setup() {
|
|||
wifiManager.addParameter(&custom_mqtt_pass);
|
||||
#endif
|
||||
|
||||
WiFi.setSleepMode(WIFI_NONE_SLEEP);
|
||||
|
||||
//fetches ssid and pass and tries to connect
|
||||
//if it does not connect it starts an access point with the specified name
|
||||
//here "AutoConnectAP"
|
||||
|
@ -256,7 +317,7 @@ void setup() {
|
|||
delay(1000);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
//read updated parameters
|
||||
strcpy(mqtt_host, custom_mqtt_host.getValue());
|
||||
strcpy(mqtt_port, custom_mqtt_port.getValue());
|
||||
|
@ -264,6 +325,9 @@ void setup() {
|
|||
strcpy(mqtt_pass, custom_mqtt_pass.getValue());
|
||||
|
||||
//save the custom parameters to FS
|
||||
#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");
|
||||
|
||||
|
@ -275,6 +339,12 @@ void setup() {
|
|||
EEPROM.commit();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
|
||||
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
|
||||
#endif
|
||||
|
||||
//if you get here you have connected to the WiFi
|
||||
DBG_OUTPUT_PORT.println("connected...yeey :)");
|
||||
|
@ -340,6 +410,21 @@ void setup() {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
if (mqtt_host != "" && String(mqtt_port).toInt() > 0) {
|
||||
amqttClient.onConnect(onMqttConnect);
|
||||
amqttClient.onDisconnect(onMqttDisconnect);
|
||||
amqttClient.onMessage(onMqttMessage);
|
||||
amqttClient.setServer(mqtt_host, String(mqtt_port).toInt());
|
||||
amqttClient.setClientId(mqtt_clientid);
|
||||
|
||||
connectToMqtt();
|
||||
}
|
||||
#endif
|
||||
|
||||
// #ifdef ENABLE_HOMEASSISTANT
|
||||
// ha_send_data.attach(5, tickerSendState); // Send HA data back only every 5 sec
|
||||
// #endif
|
||||
|
||||
// ***************************************************************************
|
||||
// Setup: MDNS responder
|
||||
|
@ -367,24 +452,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
|
||||
// ***************************************************************************
|
||||
|
@ -462,7 +529,19 @@ void setup() {
|
|||
brightness = 0;
|
||||
}
|
||||
strip.setBrightness(brightness);
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK %") + String(brightness)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK %") + String(brightness)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = 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
|
||||
getStatusJSON();
|
||||
});
|
||||
|
||||
|
@ -478,6 +557,15 @@ void setup() {
|
|||
ws2812fx_speed = server.arg("d").toInt();
|
||||
ws2812fx_speed = constrain(ws2812fx_speed, 0, 255);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ?") + String(ws2812fx_speed)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ?") + String(ws2812fx_speed)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
}
|
||||
|
||||
getStatusJSON();
|
||||
|
@ -511,6 +599,18 @@ void setup() {
|
|||
mode = OFF;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = false;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/all", []() {
|
||||
|
@ -518,6 +618,18 @@ void setup() {
|
|||
mode = ALL;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =all").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =all").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/wipe", []() {
|
||||
|
@ -525,6 +637,18 @@ void setup() {
|
|||
mode = WIPE;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =wipe").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =wipe").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/rainbow", []() {
|
||||
|
@ -532,6 +656,18 @@ void setup() {
|
|||
mode = RAINBOW;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =rainbow").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =rainbow").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/rainbowCycle", []() {
|
||||
|
@ -539,6 +675,18 @@ void setup() {
|
|||
mode = RAINBOWCYCLE;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =rainbowCycle").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =rainbowCycle").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/theaterchase", []() {
|
||||
|
@ -546,6 +694,37 @@ void setup() {
|
|||
mode = THEATERCHASE;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =theaterchase").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =theaterchase").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/twinkleRandom", []() {
|
||||
exit_func = true;
|
||||
mode = TWINKLERANDOM;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =twinkleRandom").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =twinkleRandom").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/theaterchaseRainbow", []() {
|
||||
|
@ -553,6 +732,18 @@ void setup() {
|
|||
mode = THEATERCHASERAINBOW;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =theaterchaseRainbow").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =theaterchaseRainbow").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/tv", []() {
|
||||
|
@ -560,6 +751,18 @@ void setup() {
|
|||
mode = TV;
|
||||
getArgs();
|
||||
getStatusJSON();
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =tv").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =tv").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
#endif
|
||||
#ifdef ENABLE_STATE_SAVE_SPIFFS
|
||||
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
|
||||
#endif
|
||||
});
|
||||
|
||||
server.on("/get_modes", []() {
|
||||
|
@ -570,20 +773,40 @@ void setup() {
|
|||
getArgs();
|
||||
mode = SET_MODE;
|
||||
getStatusJSON();
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK /") + String(ws2812fx_mode).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK /") + String(ws2812fx_mode)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = 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
|
||||
});
|
||||
|
||||
#ifdef HTTP_OTA
|
||||
httpUpdater.setup(&server,"/update");
|
||||
#endif
|
||||
|
||||
#ifdef HTTP_OTA
|
||||
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);
|
||||
|
@ -608,13 +831,32 @@ void loop() {
|
|||
#endif
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
ha_send_data.detach();
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.println("WiFi disconnected, reconnecting!");
|
||||
WiFi.disconnect();
|
||||
WiFi.setSleepMode(WIFI_NONE_SLEEP);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin();
|
||||
} else {
|
||||
if (mqtt_host != "" && String(mqtt_port).toInt() > 0 && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) {
|
||||
if (!mqtt_client.connected()) {
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
ha_send_data.detach();
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.println("MQTT disconnected, reconnecting!");
|
||||
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
|
||||
|
@ -624,8 +866,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) {
|
||||
|
@ -633,6 +876,18 @@ void loop() {
|
|||
strip.setMode(FX_MODE_STATIC);
|
||||
mode = HOLD;
|
||||
}
|
||||
if (mode == SETCOLOR) {
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
mode = HOLD;
|
||||
}
|
||||
if (mode == SETSPEED) {
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
// mode = HOLD;
|
||||
}
|
||||
if (mode == BRIGHTNESS) {
|
||||
strip.setBrightness(brightness);
|
||||
mode = HOLD;
|
||||
}
|
||||
if (mode == WIPE) {
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
strip.setMode(FX_MODE_COLOR_WIPE);
|
||||
|
@ -661,11 +916,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();
|
||||
}
|
||||
|
||||
|
@ -674,8 +931,13 @@ 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);
|
||||
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
//#define USE_NEOANIMATIONFX // Uses NeoAnimationFX, PIN is ignored & set to RX/GPIO3
|
||||
#define USE_WS2812FX // Uses WS2812FX
|
||||
|
||||
// Neopixel
|
||||
#define PIN 5 // PIN (5 / D1) where neopixel / WS2811 strip is attached
|
||||
#define PIN 5 // PIN (14 / D5) where neopixel / WS2811 strip is attached
|
||||
#define NUMLEDS 24 // Number of leds in the strip
|
||||
// #define BUILTIN_LED 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
||||
#define BUILTIN_LED 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
||||
#define BUTTON 4 // Input pin (4 / D2) for switching the LED strip on / off, connect this PIN to ground to trigger button.
|
||||
|
||||
const char HOSTNAME[] = "McLighting01"; // Friedly hostname
|
||||
|
||||
//#define HTTP_OTA // If defined, enable Added ESP8266HTTPUpdateServer
|
||||
#define ENABLE_OTA // If defined, enable Arduino OTA code.
|
||||
#define ENABLE_MQTT // If defined, enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API
|
||||
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active
|
||||
// #define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control
|
||||
#define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control
|
||||
|
||||
#if defined(USE_NEOANIMATIONFX) and defined(USE_WS2812FX)
|
||||
#error "Cant have both NeoAnimationFX and WS2812FX enabled. Choose either one."
|
||||
#endif
|
||||
#if !defined(USE_NEOANIMATIONFX) and !defined(USE_WS2812FX)
|
||||
#error "Need to either use NeoAnimationFX and WS2812FX mode."
|
||||
#endif
|
||||
#if defined(ENABLE_MQTT) and defined(ENABLE_AMQTT)
|
||||
#error "Cant have both PubSubClient and AsyncMQTT enabled. Choose either one."
|
||||
#endif
|
||||
#if ( (defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT)) and (defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_AMQTT)) )
|
||||
#error "To use HA, you have to either enable PubCubClient or AsyncMQTT"
|
||||
#endif
|
||||
|
||||
// parameters for automatically cycling favorite patterns
|
||||
uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
|
||||
|
@ -20,33 +35,44 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
|
|||
{0x0000ff, 200, 42, 15.0} // fireworks for 15 seconds
|
||||
};
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
#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
|
||||
String mqtt_ha = "home/" + String(HOSTNAME) + "_ha/";
|
||||
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;
|
||||
String effectString = "Static";
|
||||
bool new_ha_mqtt_msg = false;
|
||||
uint16_t color_temp = 327; // min is 154 and max is 500
|
||||
#endif
|
||||
|
||||
const char * mqtt_clientid = HOSTNAME; // Set ClientID to HOSTNAME to be unique
|
||||
const char mqtt_clientid[] = "NeoPixelsStrip"; // MQTT ClientID
|
||||
|
||||
char mqtt_host[64] = "";
|
||||
char mqtt_port[6] = "";
|
||||
char mqtt_user[32] = "";
|
||||
char mqtt_pass[32] = "";
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -56,7 +82,7 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)
|
|||
#define DBG_OUTPUT_PORT Serial // Set debug output port
|
||||
|
||||
// List of all color modes
|
||||
enum MODE { SET_MODE, HOLD, OFF, ALL, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
|
||||
enum MODE { SET_MODE, HOLD, OFF, ALL, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
|
||||
|
||||
MODE mode = RAINBOW; // Standard mode that is active when software starts
|
||||
|
||||
|
@ -80,14 +106,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
|
||||
|
@ -103,3 +133,13 @@ LEDState main_color = { 255, 0, 0 }; // Store the "main color" of the strip use
|
|||
byte prevKeyState = HIGH; // button is active low
|
||||
boolean buttonState = false;
|
||||
#endif
|
||||
|
||||
#define PIN 14 // PIN (14 / D5) where neopixel / WS2811 strip is attached
|
||||
#define NUMLEDS 300 // Number of leds in the strip
|
||||
#define BUILTIN_LED 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
||||
#define BUTTON 0 // Input pin (4 / D2) for switching the LED strip on / off, connect this PIN to ground to trigger button.
|
||||
#define HTTP_OTA // If defined, enable ESP8266HTTPUpdateServer OTA code.
|
||||
//#define ENABLE_OTA // If defined, enable Arduino OTA code.
|
||||
#define ENABLE_AMQTT // If defined, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
|
||||
//#define ENABLE_MQTT // If defined, enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API
|
||||
const char * mqtt_clientid = HOSTNAME; // Set ClientID to HOSTNAME to be unique
|
|
@ -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);
|
||||
|
@ -40,8 +51,9 @@ void getArgs() {
|
|||
}
|
||||
|
||||
|
||||
long convertSpeed(int mcl_speed) {
|
||||
long ws2812_speed = mcl_speed * 256;
|
||||
uint16_t convertSpeed(uint8_t mcl_speed) {
|
||||
//long ws2812_speed = mcl_speed * 256;
|
||||
uint16_t ws2812_speed = 61760 * (exp(0.0002336 * mcl_speed) - exp(-0.03181 * mcl_speed));
|
||||
ws2812_speed = SPEED_MAX - ws2812_speed;
|
||||
if (ws2812_speed < SPEED_MIN) {
|
||||
ws2812_speed = SPEED_MIN;
|
||||
|
@ -286,33 +298,6 @@ void getModesJSON() {
|
|||
server.send ( 200, "application/json", listModesJSON() );
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
/********************************** START SEND STATE*****************************************/
|
||||
void sendState() {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(10)> jsonBuffer;
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
mqtt_client.publish(mqtt_ha_state_out.c_str(), buffer, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ***************************************************************************
|
||||
// HTTP request handlers
|
||||
// ***************************************************************************
|
||||
|
@ -408,9 +393,18 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
handleSetMainColor(payload);
|
||||
DBG_OUTPUT_PORT.printf("Set main color to: [%u] [%u] [%u]\n", main_color.red, main_color.green, main_color.blue);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -421,6 +415,15 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
DBG_OUTPUT_PORT.printf("WS: Set speed to: [%u]\n", ws2812fx_speed);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// % ==> Set brightness
|
||||
|
@ -430,9 +433,18 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
DBG_OUTPUT_PORT.printf("WS: Set brightness to: [%u]\n", brightness);
|
||||
strip.setBrightness(brightness);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -440,9 +452,18 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
if (payload[0] == '*') {
|
||||
handleSetAllMode(payload);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -450,18 +471,36 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
if (payload[0] == '!') {
|
||||
handleSetSingleLED(payload, 1);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
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);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// + ==> Set range of LEDs in the given color
|
||||
if (payload[0] == 'R') {
|
||||
handleRangeDifferentColors(payload);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// = ==> Activate named mode
|
||||
|
@ -473,8 +512,17 @@ 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_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -485,6 +533,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
String json = listStatusJSON();
|
||||
DBG_OUTPUT_PORT.println(json);
|
||||
webSocket.sendTXT(num, json);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, listStatusJSON());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
String liststat = (String) listStatusJSON();
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, liststat.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// ~ ==> Get WS2812 modes.
|
||||
|
@ -494,15 +549,36 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
|||
String json = listModesJSON();
|
||||
DBG_OUTPUT_PORT.println(json);
|
||||
webSocket.sendTXT(num, json);
|
||||
#ifdef ENABLE_MQTT
|
||||
DBG_OUTPUT_PORT.printf("Error: Not implemented. Message too large for pubsubclient.");
|
||||
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(), qospub, false, String("ERROR: Not implemented. Message too large for AsyncMQTT.").c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// / ==> Set WS2812 mode.
|
||||
if (payload[0] == '/') {
|
||||
handleSetWS2812FXMode(payload);
|
||||
webSocket.sendTXT(num, "OK");
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -533,24 +609,25 @@ void checkForRequests() {
|
|||
// ***************************************************************************
|
||||
// MQTT callback / connection handler
|
||||
// ***************************************************************************
|
||||
#ifdef ENABLE_MQTT
|
||||
#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)
|
||||
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
|
||||
void temp2rgb(unsigned int kelvin) {
|
||||
LEDState temp2rgb(unsigned int kelvin) {
|
||||
int tmp_internal = kelvin / 100.0;
|
||||
LEDState tmp_color;
|
||||
|
||||
// red
|
||||
if (tmp_internal <= 66) {
|
||||
main_color.red = 255;
|
||||
tmp_color.red = 255;
|
||||
} else {
|
||||
float tmp_red = 329.698727446 * pow(tmp_internal - 60, -0.1332047592);
|
||||
if (tmp_red < 0) {
|
||||
main_color.red = 0;
|
||||
tmp_color.red = 0;
|
||||
} else if (tmp_red > 255) {
|
||||
main_color.red = 255;
|
||||
tmp_color.red = 255;
|
||||
} else {
|
||||
main_color.red = tmp_red;
|
||||
tmp_color.red = tmp_red;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,142 +635,203 @@ void checkForRequests() {
|
|||
if (tmp_internal <= 66) {
|
||||
float tmp_green = 99.4708025861 * log(tmp_internal) - 161.1195681661;
|
||||
if (tmp_green < 0) {
|
||||
main_color.green = 0;
|
||||
tmp_color.green = 0;
|
||||
} else if (tmp_green > 255) {
|
||||
main_color.green = 255;
|
||||
tmp_color.green = 255;
|
||||
} else {
|
||||
main_color.green = tmp_green;
|
||||
tmp_color.green = tmp_green;
|
||||
}
|
||||
} else {
|
||||
float tmp_green = 288.1221695283 * pow(tmp_internal - 60, -0.0755148492);
|
||||
if (tmp_green < 0) {
|
||||
main_color.green = 0;
|
||||
tmp_color.green = 0;
|
||||
} else if (tmp_green > 255) {
|
||||
main_color.green = 255;
|
||||
tmp_color.green = 255;
|
||||
} else {
|
||||
main_color.green = tmp_green;
|
||||
tmp_color.green = tmp_green;
|
||||
}
|
||||
}
|
||||
|
||||
// blue
|
||||
if (tmp_internal >= 66) {
|
||||
main_color.blue = 255;
|
||||
tmp_color.blue = 255;
|
||||
} else if (tmp_internal <= 19) {
|
||||
main_color.blue = 0;
|
||||
tmp_color.blue = 0;
|
||||
} else {
|
||||
float tmp_blue = 138.5177312231 * log(tmp_internal - 10) - 305.0447927307;
|
||||
if (tmp_blue < 0) {
|
||||
main_color.blue = 0;
|
||||
tmp_color.blue = 0;
|
||||
} else if (tmp_blue > 255) {
|
||||
main_color.blue = 255;
|
||||
tmp_color.blue = 255;
|
||||
} else {
|
||||
main_color.blue = tmp_blue;
|
||||
tmp_color.blue = tmp_blue;
|
||||
}
|
||||
}
|
||||
return tmp_color;
|
||||
}
|
||||
|
||||
//handleSetWS2812FXMode((uint8_t *) "/0");
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
strip.start();
|
||||
void sendState() {
|
||||
const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6);
|
||||
//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;
|
||||
|
||||
root["speed"] = ws2812fx_speed;
|
||||
|
||||
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) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(10)> jsonBuffer;
|
||||
|
||||
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()) {
|
||||
Serial.println("parseObject() failed");
|
||||
DBG_OUTPUT_PORT.println("parseObject() failed");
|
||||
return false;
|
||||
}
|
||||
//DBG_OUTPUT_PORT.println("JSON ParseObject() done!");
|
||||
|
||||
if (root.containsKey("state")) {
|
||||
if (strcmp(root["state"], on_cmd) == 0 and !(animation_on)) {
|
||||
const char* state_in = root["state"];
|
||||
if (strcmp(state_in, on_cmd) == 0 and !(animation_on)) {
|
||||
stateOn = true;
|
||||
mode = ALL;
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
strip.start();
|
||||
}
|
||||
else if (strcmp(root["state"], off_cmd) == 0) {
|
||||
else if (strcmp(state_in, off_cmd) == 0) {
|
||||
stateOn = false;
|
||||
mode = OFF;
|
||||
animation_on = false;
|
||||
strip.start();
|
||||
mode = OFF;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (root.containsKey("color")) {
|
||||
main_color.red = root["color"]["r"];
|
||||
main_color.green = root["color"]["g"];
|
||||
main_color.blue = root["color"]["b"];
|
||||
//handleSetWS2812FXMode((uint8_t *) "/0");
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
strip.start();
|
||||
JsonObject& color = root["color"];
|
||||
main_color.red = (uint8_t) color["r"];
|
||||
main_color.green = (uint8_t) color["g"];
|
||||
main_color.blue = (uint8_t) color["b"];
|
||||
mode = SETCOLOR;
|
||||
}
|
||||
|
||||
if (root.containsKey("speed")) {
|
||||
uint8_t json_speed = constrain((uint8_t) root["speed"], 0, 255);
|
||||
if (json_speed != ws2812fx_speed) {
|
||||
ws2812fx_speed = json_speed;
|
||||
mode = SETSPEED;
|
||||
}
|
||||
}
|
||||
|
||||
if (root.containsKey("color_temp")) {
|
||||
//temp comes in as mireds, need to convert to kelvin then to RGB
|
||||
int color_temp = root["color_temp"];
|
||||
color_temp = (uint16_t) root["color_temp"];
|
||||
unsigned int kelvin = 1000000 / color_temp;
|
||||
|
||||
temp2rgb(kelvin);
|
||||
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);
|
||||
strip.setBrightness(brightness);
|
||||
mode = BRIGHTNESS;
|
||||
}
|
||||
|
||||
if (root.containsKey("effect")) {
|
||||
animation_on = true;
|
||||
effectString = String((const char *)root["effect"]);
|
||||
String effectString = root["effect"].asString();
|
||||
|
||||
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
|
||||
if(String(strip.getModeName(i)) == effectString) {
|
||||
mode = HOLD;
|
||||
strip.setColor(main_color.red, main_color.green, main_color.blue);
|
||||
strip.setMode(i);
|
||||
strip.start();
|
||||
mode = SET_MODE;
|
||||
ws2812fx_mode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsonBuffer.clear();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMQTT
|
||||
void onMqttMessage(char* topic, char* payload_in, AsyncMqttClientMessageProperties properties, size_t length, size_t index, size_t total) {
|
||||
DBG_OUTPUT_PORT.print("MQTT: Recieved ["); DBG_OUTPUT_PORT.print(topic);
|
||||
// DBG_OUTPUT_PORT.print("]: "); DBG_OUTPUT_PORT.println(payload_in);
|
||||
uint8_t * payload = (uint8_t *) malloc(length + 1);
|
||||
memcpy(payload, payload_in, length);
|
||||
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);
|
||||
memcpy(payload, payload_in, length);
|
||||
payload[length] = NULL;
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Message arrived [%s]\n", payload);
|
||||
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
if (strcmp(topic, mqtt_ha_state_in.c_str()) == 0) {
|
||||
if (!processJson((char*)payload)) {
|
||||
return;
|
||||
}
|
||||
sendState();
|
||||
|
||||
} 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);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
|
||||
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
|
||||
#ifdef ENABLE_MQTT
|
||||
} else if (strcmp(topic, (char *)mqtt_intopic) == 0) {
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
} else if (strcmp(topic, mqtt_intopic.c_str()) == 0) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// # ==> Set main color
|
||||
if (payload[0] == '#') {
|
||||
handleSetMainColor(payload);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set main color to [%u] [%u] [%u]\n", main_color.red, main_color.green, main_color.blue);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -703,7 +841,15 @@ void checkForRequests() {
|
|||
ws2812fx_speed = constrain(d, 0, 255);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set speed to [%u]\n", ws2812fx_speed);
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState);
|
||||
#endif
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// % ==> Set brightness
|
||||
|
@ -712,10 +858,18 @@ void checkForRequests() {
|
|||
brightness = constrain(b, 0, 255);
|
||||
strip.setBrightness(brightness);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set brightness to [%u]\n", brightness);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -723,10 +877,18 @@ void checkForRequests() {
|
|||
if (payload[0] == '*') {
|
||||
handleSetAllMode(payload);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set main color and light all LEDs [%s]\n", payload);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -734,20 +896,35 @@ void checkForRequests() {
|
|||
if (payload[0] == '!') {
|
||||
handleSetSingleLED(payload, 1);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set single LED in given color [%s]\n", payload);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
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);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
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);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set range of LEDS to single color: [%s]\n", payload);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// = ==> Activate named mode
|
||||
|
@ -755,9 +932,17 @@ void checkForRequests() {
|
|||
String str_mode = String((char *) &payload[0]);
|
||||
handleSetNamedMode(str_mode);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Activate named mode [%s]\n", payload);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -765,7 +950,13 @@ void checkForRequests() {
|
|||
if (payload[0] == '$') {
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Get status info.\n");
|
||||
DBG_OUTPUT_PORT.println("MQTT: Out: " + String(listStatusJSON()));
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, listStatusJSON());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
String liststat = (String) listStatusJSON();
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, liststat.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// ~ ==> Get WS2812 modes.
|
||||
|
@ -773,6 +964,7 @@ void checkForRequests() {
|
|||
// Hint: https://github.com/knolleary/pubsubclient/issues/110
|
||||
if (payload[0] == '~') {
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Get WS2812 modes.\n");
|
||||
#ifdef ENABLE_MQTT
|
||||
DBG_OUTPUT_PORT.printf("Error: Not implemented. Message too large for pubsubclient.");
|
||||
mqtt_client.publish(mqtt_outtopic, "ERROR: Not implemented. Message too large for pubsubclient.");
|
||||
//String json_modes = listModesJSON();
|
||||
|
@ -780,16 +972,28 @@ void checkForRequests() {
|
|||
|
||||
//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(), qospub, false, String("ERROR: Not implemented. Message too large for AsyncMQTT.").c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// / ==> Set WS2812 mode.
|
||||
if (payload[0] == '/') {
|
||||
handleSetWS2812FXMode(payload);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Set WS2812 mode [%s]\n", payload);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String(String("OK ") + String((char *)payload)).c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -799,11 +1003,12 @@ void checkForRequests() {
|
|||
free(payload);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
void mqtt_reconnect() {
|
||||
// Loop until we're reconnected
|
||||
while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) {
|
||||
mqtt_reconnect_retries++;
|
||||
DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d (%s) ...\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES, mqtt_clientid);
|
||||
DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES);
|
||||
// Attempt to connect
|
||||
if (mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_pass)) {
|
||||
DBG_OUTPUT_PORT.println("MQTT connected!");
|
||||
|
@ -813,11 +1018,10 @@ 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
|
||||
DBG_OUTPUT_PORT.printf("Homeassistant MQTT topic in: %s\n", mqtt_ha_state_in.c_str());
|
||||
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);
|
||||
#endif
|
||||
|
||||
DBG_OUTPUT_PORT.printf("MQTT topic in: %s\n", mqtt_intopic);
|
||||
|
@ -834,6 +1038,76 @@ void checkForRequests() {
|
|||
DBG_OUTPUT_PORT.printf("MQTT connection failed, giving up after %d tries ...\n", mqtt_reconnect_retries);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
void connectToWifi() {
|
||||
DBG_OUTPUT_PORT.println("Re-connecting to Wi-Fi...");
|
||||
WiFi.setSleepMode(WIFI_NONE_SLEEP);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin();
|
||||
}
|
||||
|
||||
void connectToMqtt() {
|
||||
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
|
||||
ha_send_data.detach();
|
||||
#endif
|
||||
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: ");
|
||||
DBG_OUTPUT_PORT.println(sessionPresent);
|
||||
char * message = new char[18 + strlen(HOSTNAME) + 1];
|
||||
strcpy(message, "McLighting ready: ");
|
||||
strcat(message, HOSTNAME);
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, message);
|
||||
//Subscribe
|
||||
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.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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
||||
DBG_OUTPUT_PORT.print("Disconnected from MQTT, reason: ");
|
||||
if (reason == AsyncMqttClientDisconnectReason::TLS_BAD_FINGERPRINT) {
|
||||
DBG_OUTPUT_PORT.println("Bad server fingerprint.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
|
||||
DBG_OUTPUT_PORT.println("TCP Disconnected.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION) {
|
||||
DBG_OUTPUT_PORT.println("Bad server fingerprint.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
|
||||
DBG_OUTPUT_PORT.println("MQTT Identifier rejected.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE) {
|
||||
DBG_OUTPUT_PORT.println("MQTT server unavailable.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS) {
|
||||
DBG_OUTPUT_PORT.println("MQTT malformed credentials.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) {
|
||||
DBG_OUTPUT_PORT.println("MQTT not authorized.");
|
||||
} else if (reason == AsyncMqttClientDisconnectReason::ESP8266_NOT_ENOUGH_SPACE) {
|
||||
DBG_OUTPUT_PORT.println("Not enough space on esp8266.");
|
||||
}
|
||||
if (WiFi.isConnected()) {
|
||||
mqttReconnectTimer.once(5, connectToMqtt);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -854,10 +1128,16 @@ void checkForRequests() {
|
|||
buttonState = false;
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =off").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = false;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -868,10 +1148,16 @@ void checkForRequests() {
|
|||
setModeByStateString(BTN_MODE_MEDIUM);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =fire flicker").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =fire flicker").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -881,10 +1167,16 @@ void checkForRequests() {
|
|||
setModeByStateString(BTN_MODE_LONG);
|
||||
#ifdef ENABLE_MQTT
|
||||
mqtt_client.publish(mqtt_outtopic, String("OK =fireworks random").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_AMQTT
|
||||
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =fireworks random").c_str());
|
||||
#endif
|
||||
#ifdef ENABLE_HOMEASSISTANT
|
||||
stateOn = true;
|
||||
sendState();
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -918,3 +1210,157 @@ void checkForRequests() {
|
|||
}
|
||||
}
|
||||
#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(7));
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(7)> jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.createObject();
|
||||
json["mode"] = static_cast<int>(mode);
|
||||
json["strip_mode"] = (int) strip.getMode();
|
||||
json["brightness"] = brightness;
|
||||
json["speed"] = ws2812fx_speed;
|
||||
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(7)+200);
|
||||
// StaticJsonBuffer<JSON_OBJECT_SIZE(7)+200> 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"];
|
||||
ws2812fx_speed = json["speed"];
|
||||
main_color.red = json["red"];
|
||||
main_color.green = json["green"];
|
||||
main_color.blue = json["blue"];
|
||||
|
||||
strip.setMode(ws2812fx_mode);
|
||||
strip.setSpeed(convertSpeed(ws2812fx_speed));
|
||||
strip.setBrightness(brightness);
|
||||
strip.setColor(main_color.red, main_color.green, main_color.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
|
||||
|
|
|
@ -3,6 +3,7 @@ light:
|
|||
name: "NeoPixel LEDs"
|
||||
state_topic: "home/McLighting01_ha/state/out"
|
||||
command_topic: "home/McLighting01_ha/state/in"
|
||||
on_command_type: 'first'
|
||||
effect: true
|
||||
effect_list:
|
||||
######
|
||||
|
@ -62,6 +63,7 @@ light:
|
|||
- "Tricolor Chase"
|
||||
- "ICU"
|
||||
brightness: true
|
||||
color_temp: true
|
||||
rgb: true
|
||||
optimistic: false
|
||||
qos: 0
|
||||
|
@ -77,7 +79,7 @@ input_number:
|
|||
|
||||
automation:
|
||||
- id: 71938579813759813757
|
||||
alias: NeoPixel Animation Speed
|
||||
alias: NeoPixel Animation Speed Send
|
||||
initial_state: true
|
||||
hide_entity: false
|
||||
trigger:
|
||||
|
@ -85,7 +87,18 @@ automation:
|
|||
platform: state
|
||||
action:
|
||||
- data_template:
|
||||
payload_template: '{{ trigger.to_state.state | int }}'
|
||||
payload_template: '{"speed": {{ trigger.to_state.state | int }}}'
|
||||
retain: true
|
||||
topic: home/McLighting01_ha/speed
|
||||
topic: home/McLighting01_ha/state/in
|
||||
service: mqtt.publish
|
||||
|
||||
- id: 93786598732698756967
|
||||
alias: NeoPixel Animation Speed Receive
|
||||
trigger:
|
||||
- platform: mqtt
|
||||
topic: home/McLighting01_ha/state/out
|
||||
action:
|
||||
- data_template:
|
||||
entity_id: input_number.neopixel_animation_speed
|
||||
value: '{{ trigger.payload_json.speed | int }}'
|
||||
service: input_number.set_value
|
Loading…
Reference in a new issue