diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index 669209b..9dba564 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -19,83 +19,93 @@ #include //https://github.com/Links2004/arduinoWebSockets #include -#ifdef ENABLE_BUTTON_GY33 - // needed for MCU +#if defined(ENABLE_BUTTON_GY33) +// *************************************************************************** +// Load libraries for GY33 and initialize color sensor +// *************************************************************************** #include //https://github.com/FabLab-Luenen/GY33_MCU/archive/master.zip ; //https://github.com/pasko-zh/brzo_i2c - // *************************************************************************** - // Initialize Color Sensor - // *************************************************************************** GY33_MCU tcs; #endif -// OTA -#ifdef ENABLE_OTA - #include - #include -#endif - -//SPIFFS Save -#if !defined(ENABLE_HOMEASSISTANT) and defined(ENABLE_STATE_SAVE_SPIFFS) - #include //https://github.com/bblanchon/ArduinoJson -#endif +#include //https://github.com/bblanchon/ArduinoJson // MQTT -#ifdef ENABLE_MQTT - #include - #ifdef ENABLE_HOMEASSISTANT - #include //https://github.com/bblanchon/ArduinoJson +#if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 +// *************************************************************************** +// Load libraries for PubSubClient +// *************************************************************************** + #include + WiFiClient espClient; + PubSubClient mqtt_client(espClient); + #endif + + #if ENABLE_MQTT == 1 +// *************************************************************************** +// Load libraries for Amqtt +// *************************************************************************** + #include //https://github.com/marvinroger/async-mqtt-client + //https://github.com/me-no-dev/ESPAsyncTCP + AsyncMqttClient amqttClient; + WiFiEventHandler wifiConnectHandler; + WiFiEventHandler wifiDisconnectHandler; #endif - - WiFiClient espClient; - PubSubClient mqtt_client(espClient); #endif -#ifdef ENABLE_AMQTT - #include //https://github.com/marvinroger/async-mqtt-client - //https://github.com/me-no-dev/ESPAsyncTCP - #ifdef ENABLE_HOMEASSISTANT - #include - #endif - - AsyncMqttClient amqttClient; - WiFiEventHandler wifiConnectHandler; - WiFiEventHandler wifiDisconnectHandler; -#endif - -#ifdef ARDUINOJSON_VERSION +#if defined(ARDUINOJSON_VERSION) #if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR == 7) #error "Install ArduinoJson v6.7.0-beta" #endif #endif -#ifdef ENABLE_E131 +#if defined(ENABLE_E131) +// *************************************************************************** +// Load libraries for E131 support +// *************************************************************************** #include //https://github.com/me-no-dev/ESPAsyncUDP #include //https://github.com/forkineye/ESPAsyncE131 ESPAsyncE131 e131(END_UNIVERSE - START_UNIVERSE + 1); #endif +#if defined(ENABLE_REMOTE) +// *************************************************************************** +// Load libraries for IR remote support +// *************************************************************************** + #include //https://github.com/markszabo/IRremoteESP8266 + #include + #include +#endif + // *************************************************************************** // Instanciate HTTP(80) / WebSockets(81) Server // *************************************************************************** ESP8266WebServer server(80); WebSocketsServer webSocket = WebSocketsServer(81); -#ifdef HTTP_OTA -#include -ESP8266HTTPUpdateServer httpUpdater; +// *************************************************************************** +// Include: OTA +// *************************************************************************** +#if defined(ENABLE_OTA) + #if ENABLE_OTA == 1 + #include + ESP8266HTTPUpdateServer httpUpdater; + #endif + #if ENABLE_OTA == 0 + #include + #include + #endif #endif // *************************************************************************** // Load libraries / Instanciate WS2812FX library // *************************************************************************** - #include // https://github.com/kitesurfer1404/WS2812FX - - #ifdef RGBW - WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRBW + NEO_KHZ800); - #else - WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800); - #endif +#if defined(RGBW) + WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRBW + NEO_KHZ800); +#else + WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800); +#endif +const uint8_t ws2812fx_options = SIZE_SMALL + FADE_MEDIUM; // WS2812FX setSegment OPTIONS, see: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md // Parameter 1 = number of pixels in strip // Parameter 2 = Arduino pin number (most are valid) @@ -110,32 +120,32 @@ ESP8266HTTPUpdateServer httpUpdater; // and minimize distance between Arduino and first pixel. Avoid connecting // on a live circuit...if you must, connect GND first. -#ifdef USE_WS2812FX_DMA // Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #ifdef RGBW - NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 4); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) - #else - NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) +#if defined(USE_WS2812FX_DMA) + #if USE_WS2812FX_DMA == 0// Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #include + #if defined(RGBW) + NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 4); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #else + NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #endif + //NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #endif - //NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) -#endif -#ifdef USE_WS2812FX_UART1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #ifdef RGBW - NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 4); - #else - NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 3); + #if USE_WS2812FX_DMA == 1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #include + #if defined(RGBW) + NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 4); + #else + NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 3); + #endif #endif -#endif -#ifdef USE_WS2812FX_UART2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #ifdef RGBW - NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 4); - #else - NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 3); + #if USE_WS2812FX_DMA == 2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #include + #if defined(RGBW) + NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 4); + #else + NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 3); + #endif #endif -#endif -#if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART) void DMA_Show(void) { if(dma.IsReadyToUpdate()) { memcpy(dma.getPixels(), strip.getPixels(), dma.getPixelsSize()); @@ -145,57 +155,38 @@ ESP8266HTTPUpdateServer httpUpdater; #endif // *************************************************************************** -// Load library "ticker" for blinking status led +// Load library "ticker" for blinking status led, mqtt send and save state // *************************************************************************** #include 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; + +#if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 1 + Ticker mqttReconnectTimer; + Ticker wifiReconnectTimer; + #endif + #if defined(ENABLE_HOMEASSISTANT) + Ticker ha_send_data; + #endif #endif + void tick() { //toggle state - int state = digitalRead(BUILTIN_LED); // get the current state of GPIO1 pin - digitalWrite(BUILTIN_LED, !state); // set pin to the opposite state + int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin + digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state } -#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; - } +#if defined(ENABLE_REMOTE) + IRrecv irrecv(ENABLE_REMOTE); + decode_results results; - 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 +Ticker settings_save_state; + // *************************************************************************** -// Saved state handling +// Saved state handling in WifiManager // *************************************************************************** // https://stackoverflow.com/questions/9072320/split-string-into-string-array String getValue(String data, char separator, int index) @@ -250,15 +241,15 @@ void saveConfigCallback () { // *************************************************************************** #include "request_handlers.h" +#if defined(ENABLE_TV) // *************************************************************************** -// Include: Color modes +// Include: TV mode // *************************************************************************** -#ifdef ENABLE_TV - #include "colormodes.h" + #include "mode_tv.h" #endif // *************************************************************************** -// MAIN +// MAIN Setup // *************************************************************************** void setup() { // system_update_cpu_freq(160); @@ -267,14 +258,14 @@ void setup() { EEPROM.begin(512); // set builtin led pin as output - pinMode(BUILTIN_LED, OUTPUT); + pinMode(LED_BUILTIN, OUTPUT); // button pin setup -#ifdef ENABLE_BUTTON - pinMode(BUTTON,INPUT_PULLUP); +#if defined(ENABLE_BUTTON) + pinMode(ENABLE_BUTTON,INPUT_PULLUP); #endif -#ifdef ENABLE_BUTTON_GY33 - pinMode(BUTTON_GY33, INPUT_PULLUP); +#if defined(ENABLE_BUTTON_GY33) + pinMode(ENABLE_BUTTON_GY33, INPUT_PULLUP); if (tcs.begin()) { DBG_OUTPUT_PORT.println("Found GY-33 sensor"); } else { @@ -311,14 +302,13 @@ DBG_OUTPUT_PORT.println("Starting...."); // Setup: Neopixel // *************************************************************************** strip.init(); - #if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART) + #if defined(USE_WS2812FX_DMA) dma.Initialize(); strip.setCustomShow(DMA_Show); #endif 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, main_color.white); +// parameters: index, start, stop, mode, color, speed, options + strip.setSegment(0, 0, NUMLEDS-1, FX_MODE_COMET, hex_colors, convertSpeed(ws2812fx_speed), ws2812fx_options); strip.start(); // *************************************************************************** @@ -327,21 +317,24 @@ DBG_OUTPUT_PORT.println("Starting...."); // 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 - #if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) - #if defined(ENABLE_STATE_SAVE_SPIFFS) and (defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)) - (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); - } + #if defined(ENABLE_MQTT) + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + (readConfigFS()) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Read success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Read failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + 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 #endif WiFiManagerParameter custom_mqtt_host("host", "MQTT hostname", mqtt_host, 64); WiFiManagerParameter custom_mqtt_port("port", "MQTT port", mqtt_port, 6); @@ -357,7 +350,7 @@ DBG_OUTPUT_PORT.println("Starting...."); //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode wifiManager.setAPCallback(configModeCallback); - #if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) + #if defined(ENABLE_MQTT) //set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback); @@ -372,13 +365,13 @@ DBG_OUTPUT_PORT.println("Starting...."); // Uncomment if you want to restart ESP8266 if it cannot connect to WiFi. // Value in brackets is in seconds that WiFiManger waits until restart - #ifdef WIFIMGR_PORTAL_TIMEOUT + #if defined(WIFIMGR_PORTAL_TIMEOUT) wifiManager.setConfigPortalTimeout(WIFIMGR_PORTAL_TIMEOUT); #endif // Uncomment if you want to set static IP // Order is: IP, Gateway and Subnet - #ifdef WIFIMGR_SET_MANUAL_IP + #if defined(WIFIMGR_SET_MANUAL_IP) wifiManager.setSTAStaticIPConfig(IPAddress(_ip[0], _ip[1], _ip[2], _ip[3]), IPAddress(_gw[0], _gw[1], _gw[2], _gw[3]), IPAddress(_sn[0], _sn[1], _sn[2], _sn[3])); #endif @@ -393,121 +386,128 @@ DBG_OUTPUT_PORT.println("Starting...."); delay(1000); //Will be removed when upgrading to standalone offline McLightingUI version } - #if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) + #if defined(ENABLE_MQTT) //read updated parameters strcpy(mqtt_host, custom_mqtt_host.getValue()); strcpy(mqtt_port, custom_mqtt_port.getValue()); strcpy(mqtt_user, custom_mqtt_user.getValue()); strcpy(mqtt_pass, custom_mqtt_pass.getValue()); - - //save the custom parameters to FS - #if defined(ENABLE_STATE_SAVE_SPIFFS) and (defined(ENABLE_MQTT) or defined(ENABLE_AMQTT)) - (writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!"); + + //save the custom parameters to FS/EEPROM + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + (writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + 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(); + } + #endif #endif - #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(); - } + + #if ENABLE_MQTT == 1 + wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); + wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); #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 :)"); ticker.detach(); //keep LED on - digitalWrite(BUILTIN_LED, LOW); + digitalWrite(LED_BUILTIN, LOW); + //switch LED off + //digitalWrite(LED_BUILTIN, HIGH); - - // *************************************************************************** - // Configure OTA - // *************************************************************************** - #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"); - }); - ArduinoOTA.onEnd([]() { - DBG_OUTPUT_PORT.println("Arduino OTA: End"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - DBG_OUTPUT_PORT.printf("Arduino OTA Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - DBG_OUTPUT_PORT.printf("Arduino OTA Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Auth Failed"); - else if (error == OTA_BEGIN_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Begin Failed"); - else if (error == OTA_CONNECT_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Connect Failed"); - 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(""); + #if defined(ENABLE_OTA) + #if ENABLE_OTA == 0 + // *************************************************************************** + // Configure Arduino 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"); + }); + ArduinoOTA.onEnd([]() { + DBG_OUTPUT_PORT.println("Arduino OTA: End"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + DBG_OUTPUT_PORT.printf("Arduino OTA Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + DBG_OUTPUT_PORT.printf("Arduino OTA Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Auth Failed"); + else if (error == OTA_BEGIN_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Begin Failed"); + else if (error == OTA_CONNECT_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Connect Failed"); + 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 + #if ENABLE_OTA == 1 + httpUpdater.setup(&server, "/update"); + #endif #endif - // *************************************************************************** // Configure MQTT // *************************************************************************** - #ifdef ENABLE_MQTT_HOSTNAME_CHIPID + #if defined(ENABLE_MQTT_HOSTNAME_CHIPID) snprintf(mqtt_clientid, 64, "%s-%08X", HOSTNAME, ESP.getChipId()); #endif - #ifdef ENABLE_MQTT - if (mqtt_host != "" && atoi(mqtt_port) > 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, atoi(mqtt_port)); - mqtt_client.setCallback(mqtt_callback); - } + #if defined(ENABLE_MQTT) + snprintf(mqtt_intopic, sizeof mqtt_intopic, "%s/in", HOSTNAME); + snprintf(mqtt_outtopic, sizeof mqtt_outtopic, "%s/out", HOSTNAME); + #if ENABLE_MQTT == 0 + if (mqtt_host != "" && atoi(mqtt_port) > 0) { + DBG_OUTPUT_PORT.printf("MQTT active: %s:%s\n", mqtt_host, mqtt_port); + mqtt_client.setServer(mqtt_host, atoi(mqtt_port)); + mqtt_client.setCallback(mqtt_callback); + } + #endif + + #if ENABLE_MQTT == 1 + if (mqtt_host != "" && atoi(mqtt_port) > 0) { + DBG_OUTPUT_PORT.printf("AMQTT active: %s:%s\n", mqtt_host, mqtt_port); + amqttClient.onConnect(onMqttConnect); + amqttClient.onDisconnect(onMqttDisconnect); + amqttClient.onMessage(onMqttMessage); + amqttClient.setServer(mqtt_host, atoi(mqtt_port)); + if (mqtt_user != "" or mqtt_pass != "") amqttClient.setCredentials(mqtt_user, mqtt_pass); + amqttClient.setClientId(mqtt_clientid); + + connectToMqtt(); + } + #endif + #if defined(ENABLE_HOMEASSISTANT) + snprintf(mqtt_ha_state_in, sizeof mqtt_ha_state_in, "home/%s_ha/state/in", HOSTNAME); + snprintf(mqtt_ha_state_out, sizeof mqtt_ha_state_out , "home/%s_ha/state/out", HOSTNAME); + #endif #endif - #ifdef ENABLE_AMQTT - if (mqtt_host != "" && atoi(mqtt_port) > 0) { - amqttClient.onConnect(onMqttConnect); - amqttClient.onDisconnect(onMqttDisconnect); - amqttClient.onMessage(onMqttMessage); - amqttClient.setServer(mqtt_host, atoi(mqtt_port)); - if (mqtt_user != "" or mqtt_pass != "") amqttClient.setCredentials(mqtt_user, mqtt_pass); - 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 // *************************************************************************** @@ -555,9 +555,9 @@ DBG_OUTPUT_PORT.println("Starting...."); }, handleFileUpload); //get heap status, analog input value and all GPIO statuses in one json call server.on("/esp_status", HTTP_GET, []() { - DynamicJsonDocument jsonBuffer; + const size_t bufferSize = JSON_OBJECT_SIZE(31) + 600; + DynamicJsonDocument jsonBuffer(bufferSize); JsonObject json = jsonBuffer.to(); - json["HOSTNAME"] = HOSTNAME; json["version"] = SKETCH_VERSION; json["heap"] = ESP.getFreeHeap(); @@ -571,67 +571,107 @@ DBG_OUTPUT_PORT.println("Starting...."); json["cpu_freq"] = ESP.getCpuFreqMHz(); json["chip_id"] = ESP.getFlashChipId(); #if defined(USE_WS2812FX_DMA) - json["animation_lib"] = "WS2812FX_DMA"; - json["pin"] = 3; - #elif defined(USE_WS2812FX_UART) - json["animation_lib"] = "WS2812FX_UART"; - json["pin"] = 2; + #if USE_WS2812FX_DMA == 0 + json["animation_lib"] = "WS2812FX_DMA"; + json["ws2812_pin"] = 3; + #endif + #if USE_WS2812FX_DMA == 1 + json["animation_lib"] = "WS2812FX_UART1"; + json["ws2812_pin"] = 2; + #endif + #if USE_WS2812FX_DMA == 2 + json["animation_lib"] = "WS2812FX_UART2"; + json["ws2812_pin"] = 1; + #endif #else json["animation_lib"] = "WS2812FX"; - json["pin"] = PIN; + json["ws2812_pin"] = PIN; #endif json["number_leds"] = NUMLEDS; - #ifdef ENABLE_BUTTON + #if defined(RGBW) + json["rgbw_mode"] = "ON"; + #else + json["rgbw_mode"] = "OFF"; + #endif + #if defined(ENABLE_BUTTON) json["button_mode"] = "ON"; + json["button_pin"] = ENABLE_BUTTON; #else json["button_mode"] = "OFF"; #endif - #ifdef ENABLE_AMQTT - json["amqtt"] = "ON"; + #if defined(ENABLE_BUTTON_GY33) + json["button_gy33"] = "ON"; + json["gy33_pin"] = ENABLE_BUTTON_GY33; + #else + json["button_gy33"] = "OFF"; #endif - #ifdef ENABLE_MQTT - json["mqtt"] = "ON"; + #if defined(ENABLE_REMOTE) + json["ir_remote"] = "ON"; + json["tsop_ir_pin"] = ENABLE_REMOTE; + #else + json["ir_remote"] = "OFF"; #endif - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + json["mqtt"] = "MQTT"; + #endif + #if ENABLE_MQTT == 1 + json["mqtt"] = "AMQTT"; + #endif + #else + json["mqtt"] = "OFF"; + #endif + #if defined(ENABLE_HOMEASSISTANT) json["home_assistant"] = "ON"; #else json["home_assistant"] = "OFF"; #endif - #ifdef ENABLE_LEGACY_ANIMATIONS + #if defined(ENABLE_LEGACY_ANIMATIONS) json["legacy_animations"] = "ON"; #else json["legacy_animations"] = "OFF"; #endif - #ifdef ENABLE_TV + #if defined(ENABLE_TV) json["tv_animation"] = "ON"; #else json["tv_animation"] = "OFF"; #endif - #ifdef ENABLE_E131 + #if defined(ENABLE_E131) json["e131_animations"] = "ON"; #else json["e131_animations"] = "OFF"; #endif - #ifdef HTTP_OTA - json["esp8266_http_updateserver"] = "ON"; + #if defined(ENABLE_OTA) + #if ENABLE_OTA == 0 + json["ota"] = "ARDUINO"; + #endif + #if ENABLE_OTA == 1 + json["ota"] = "HTTP"; + #endif + #else + json["ota"] = "OFF"; #endif - #ifdef ENABLE_OTA - json["arduino_ota"] = "ON"; - #endif - #ifdef ENABLE_STATE_SAVE_SPIFFS - json["state_save"] = "SPIFFS"; - #endif - #ifdef ENABLE_STATE_SAVE_EEPROM - json["state_save"] = "EEPROM"; + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + json["state_save"] = "SPIFFS"; + #endif + #if ENABLE_STATE_SAVE == 0 + json["state_save"] = "EEPROM"; + #endif + #else + json["state_save"] = "OFF"; #endif String json_str; serializeJson(json, json_str); + jsonBuffer.clear(); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "application/json", json_str); }); - +// *************************************************************************** +// Setup: SPIFFS Webserver handler +// *************************************************************************** //called when the url is not defined here //use it to load content from SPIFFS server.onNotFound([]() { @@ -669,63 +709,40 @@ DBG_OUTPUT_PORT.println("Starting...."); DBG_OUTPUT_PORT.printf("/format_spiffs\n"); server.send(200, "text/plain", "Formatting SPIFFS ..." ); SPIFFS.format(); - server.send(200, "text/plain", "Formatting SPIFFS complete" ); }); - // *************************************************************************** - // Setup: SPIFFS Webserver handler - // *************************************************************************** server.on("/set_brightness", []() { getArgs(); - mode = 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 + mode = SET_BRIGHTNESS; getStatusJSON(); }); server.on("/get_brightness", []() { - String str_brightness = String((int) (brightness / 2.55)); + char str_brightness[3]; + sprintf(str_brightness, "%i", (int) (brightness / 2.55)); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", str_brightness ); - DBG_OUTPUT_PORT.print("/get_brightness: "); - DBG_OUTPUT_PORT.println(str_brightness); + DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (brightness / 2.55)); }); server.on("/set_speed", []() { getArgs(); - mode = SETSPEED; - #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 + mode = SET_SPEED; getStatusJSON(); }); server.on("/get_speed", []() { - String str_speed = String(ws2812fx_speed); + char str_speed[3]; + sprintf(str_speed, "%i", ws2812fx_speed); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", str_speed ); - DBG_OUTPUT_PORT.print("/get_speed: "); - DBG_OUTPUT_PORT.println(str_speed); + DBG_OUTPUT_PORT.printf("/get_speed: %i\r\n", ws2812fx_speed); }); server.on("/get_switch", []() { server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", (mode == OFF) ? "0" : "1" ); - DBG_OUTPUT_PORT.printf("/get_switch: %s\n", (mode == OFF) ? "0" : "1"); + DBG_OUTPUT_PORT.printf("/get_switch: %s\r\n", (mode == OFF) ? "0" : "1"); }); server.on("/get_color", []() { @@ -736,211 +753,102 @@ DBG_OUTPUT_PORT.println("Starting...."); DBG_OUTPUT_PORT.print("/get_color: "); DBG_OUTPUT_PORT.println(rgbcolor); }); + + server.on("/get_color2", []() { + char rgbcolor[9]; + snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", back_color.white, back_color.red, back_color.green, back_color.blue); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", rgbcolor ); + DBG_OUTPUT_PORT.print("/get_color2: "); + DBG_OUTPUT_PORT.println(rgbcolor); + }); + + server.on("/get_color3", []() { + char rgbcolor[9]; + snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", xtra_color.white, xtra_color.red, xtra_color.green, xtra_color.blue); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", rgbcolor ); + DBG_OUTPUT_PORT.print("/get_color3: "); + DBG_OUTPUT_PORT.println(rgbcolor); + }); + server.on("/status", []() { getStatusJSON(); }); server.on("/off", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif 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 }); server.on("/auto", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - handleAutoStart(); - getArgs(); + mode = AUTO; getStatusJSON(); - #ifdef ENABLE_MQTT - mqtt_client.publish(mqtt_outtopic, String("OK =auto").c_str()); - #endif - #ifdef ENABLE_AMQTT - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =auto").c_str()); - #endif - #ifdef ENABLE_HOMEASSISTANT - stateOn = false; - #endif }); server.on("/all", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - ws2812fx_mode = FX_MODE_STATIC; - mode = SET_MODE; - //mode = ALL; getArgs(); + ws2812fx_mode = FX_MODE_STATIC; + mode = SET_ALL; 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_LEGACY_ANIMATIONS + #if defined(ENABLE_LEGACY_ANIMATIONS) server.on("/wipe", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = WIPE; getArgs(); + ws2812fx_mode = FX_MODE_COLOR_WIPE; + mode = SET_ALL; 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 }); server.on("/rainbow", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = RAINBOW; getArgs(); + ws2812fx_mode = FX_MODE_RAINBOW; + mode = SET_ALL; 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 }); - server.on("/rainbowCycle", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = RAINBOWCYCLE; + server.on("/rainbowcycle", []() { getArgs(); + ws2812fx_mode = FX_MODE_RAINBOW_CYCLE; + mode = SET_ALL; 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 }); server.on("/theaterchase", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = THEATERCHASE; getArgs(); + ws2812fx_mode = FX_MODE_THEATER_CHASE; + mode = SET_ALL; 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 }); - server.on("/twinkleRandom", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = TWINKLERANDOM; + server.on("/twinklerandom", []() { getArgs(); + ws2812fx_mode = FX_MODE_TWINKLE_RANDOM; + mode = SET_ALL; 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 }); - server.on("/theaterchaseRainbow", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = THEATERCHASERAINBOW; + server.on("/theaterchaserainbow", []() { getArgs(); + ws2812fx_mode = FX_MODE_THEATER_CHASE_RAINBOW; + mode = SET_ALL; 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 }); #endif - #ifdef ENABLE_E131 + #if defined(ENABLE_E131) server.on("/e131", []() { - #ifdef ENABLE_TV - exit_func = true; - #endif mode = E131; getStatusJSON(); - #ifdef ENABLE_MQTT - mqtt_client.publish(mqtt_outtopic, String("OK =e131").c_str()); - #endif - #ifdef ENABLE_AMQTT - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =e131").c_str()); - #endif - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif }); #endif - #ifdef ENABLE_TV + #if defined(ENABLE_TV) server.on("/tv", []() { - exit_func = true; 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 }); #endif @@ -952,23 +860,8 @@ DBG_OUTPUT_PORT.println("Starting...."); 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 HTTP_OTA - httpUpdater.setup(&server, "/update"); - #endif - server.begin(); // Start MDNS service @@ -976,234 +869,243 @@ DBG_OUTPUT_PORT.println("Starting...."); MDNS.addService("http", "tcp", 80); } - #ifdef ENABLE_E131 + #if defined(ENABLE_E131) // Choose one to begin listening for E1.31 data - // if (e131.begin(E131_UNICAST)) // Listen via Unicast + // if (e131.begin(E131_UNICAST)) // Listen via Unicast if (e131.begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) // Listen via Multicast DBG_OUTPUT_PORT.println(F("Listening for data...")); else DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***")); #endif - #ifdef ENABLE_STATE_SAVE_SPIFFS - (readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + (readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + // Load state string from EEPROM + String saved_state_string = readEEPROM(256, 66); + String chk = getValue(saved_state_string, '|', 0); + if (chk == "STA") { + DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str()); + setModeByStateString(saved_state_string); + mode = SET_ALL; + } + #endif #endif - - #ifdef ENABLE_STATE_SAVE_EEPROM - // Load state string from EEPROM - String saved_state_string = readEEPROM(256, 36); - String chk = getValue(saved_state_string, '|', 0); - if (chk == "STA") { - DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str()); - setModeByStateString(saved_state_string); - } - sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white); - #endif - - #ifdef ENABLE_BUTTON_GY33 + #if defined(ENABLE_BUTTON_GY33) tcs.setConfig(MCU_LED_06, MCU_WHITE_ON); // delay(2000); // tcs.setConfig(MCU_LED_OFF, MCU_WHITE_OFF); #endif + prevmode = mode; + #if defined(ENABLE_REMOTE) + irrecv.enableIRIn(); // Start the receiver + sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white, back_color.red, back_color.green, back_color.blue, back_color.white, xtra_color.red, xtra_color.green, xtra_color.blue,xtra_color.white); + #endif } - +// *************************************************************************** +// MAIN Loop +// *************************************************************************** void loop() { - #ifdef ENABLE_BUTTON + #if defined(ENABLE_BUTTON) button(); #endif - #ifdef ENABLE_BUTTON_GY33 + #if defined(ENABLE_BUTTON_GY33) button_gy33(); #endif server.handleClient(); webSocket.loop(); - #ifdef ENABLE_OTA - ArduinoOTA.handle(); + #if defined(ENABLE_OTA) + #if ENABLE_OTA == 0 + ArduinoOTA.handle(); + #endif #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 + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + if (WiFi.status() != WL_CONNECTED) { + #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); - #endif - DBG_OUTPUT_PORT.println("MQTT disconnected, reconnecting!"); - mqtt_reconnect(); - } else { - mqtt_client.loop(); + #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()) { + #if defined(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 #endif + // *************************************************************************** // Simple statemachine that handles the different modes - if (mode == OFF) { - if(strip.isRunning()) strip.stop(); //should clear memory - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - - #ifdef ENABLE_TV - if (mode == TV) { - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - if(!strip.isRunning()) strip.start(); - tv(); - } - #endif - - #ifdef ENABLE_E131 - if (mode == E131) { - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - handleE131(); - } - #endif - if (mode == SET_MODE) { - DBG_OUTPUT_PORT.printf("SET_MODE: %d %d\n", ws2812fx_mode, mode); - strip.setMode(ws2812fx_mode); - //strip.trigger(); // is done later anyway, why do it more than once? - prevmode = SET_MODE; - mode = SETCOLOR; - } - if (mode == SETCOLOR) { - strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - mode = (prevmode == SET_MODE) ? SETSPEED : prevmode; - if (mode == HOLD) strip.trigger(); - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == SETSPEED) { - strip.setSpeed(convertSpeed(ws2812fx_speed)); - mode = (prevmode == SET_MODE) ? BRIGHTNESS : prevmode; - if (mode == HOLD) strip.trigger(); - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == BRIGHTNESS) { - strip.setBrightness(brightness); - mode = (prevmode == SET_MODE) ? HOLD : prevmode; - if (mode == HOLD) strip.trigger(); - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - #ifdef ENABLE_LEGACY_ANIMATIONS - if (mode == WIPE) { - //strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - strip.setMode(FX_MODE_COLOR_WIPE); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == RAINBOW) { - strip.setMode(FX_MODE_RAINBOW); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == RAINBOWCYCLE) { - strip.setMode(FX_MODE_RAINBOW_CYCLE); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == THEATERCHASE) { - //strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - strip.setMode(FX_MODE_THEATER_CHASE); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == TWINKLERANDOM) { - //strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - strip.setMode(FX_MODE_TWINKLE_RANDOM); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - if (mode == THEATERCHASERAINBOW) { - strip.setMode(FX_MODE_THEATER_CHASE_RAINBOW); - strip.trigger(); - mode = HOLD; - #ifdef ENABLE_STATE_SAVE_SPIFFS - if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); - #endif - } - #endif - - if (mode == HOLD || mode == CUSTOM) { - #ifdef ENABLE_TV - if (exit_func) { - exit_func = false; - } - #endif + // *************************************************************************** + if ((mode != OFF) && (mode != TV) && (mode != E131)) { // strip.start() is only needed for modes with WS2812FX functionality if(!strip.isRunning()) strip.start(); - if (prevmode == SET_MODE) prevmode = HOLD; + } + + if ((mode == OFF) || (mode == TV) || (mode == E131)) { + if(strip.isRunning()) { + strip.strip_off(); // Workaround: to be shure, + delay(10); // that strip is really off. Sometimes strip.stop isn't enought + strip.stop(); // should clear memory + } else { + if (prevmode != mode) { // Start temporarily to clear strip + strip.start(); + strip.strip_off(); // Workaround: to be shure, + delay(10); // that strip is really off. Sometimes strip.stop isn't enought + strip.stop(); // should clear memory + } + } } - - // Only for modes with WS2812FX functionality - #ifdef ENABLE_TV - if (mode != TV && mode != CUSTOM) { - #else - if (mode != CUSTOM) { - #endif + + if (( mode == AUTO) || (mode == HOLD)) { // strip.service() is only needed for modes with WS2812FX functionality strip.service(); } - - #ifdef ENABLE_STATE_SAVE_SPIFFS - if (updateStateFS) { - (writeStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); + + if ((prevmode == AUTO) && (mode != AUTO)) { handleAutoStop(); } // stop auto mode + + if (mode == OFF) { + #if defined(ENABLE_MQTT) + if (prevmode != mode) { sprintf(mqtt_buf, "OK =off", ""); } + #endif + } + + if (mode == AUTO) { + if (prevmode != mode) { + handleAutoStart(); + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK =auto", ""); + #endif + } + } + + #if defined(ENABLE_TV) + if (mode == TV) { + handleTV(); + #if defined(ENABLE_MQTT) + if (prevmode != mode) { sprintf(mqtt_buf, "OK =tv", ""); } + #endif } #endif - - #ifdef ENABLE_STATE_SAVE_EEPROM - // Check for state changes - sprintf(current_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, strip.getMode(), ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white); - - 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); - time_statechange = millis(); - state_save_requested = true; + + #if defined(ENABLE_E131) + if (mode == E131) { + handleE131(); + #if defined(ENABLE_MQTT) + if (prevmode != mode) { sprintf(mqtt_buf, "OK =e131", ""); } + #endif } - if (state_save_requested && time_statechange + timeout_statechange_save <= millis()) { - time_statechange = 0; - state_save_requested = false; - writeEEPROM(256, 36, last_state); // 256 --> last_state (reserved 36 bytes) - EEPROM.commit(); + #endif + + if (mode == SET_ALL) { + mode = HOLD; + if ((prevmode == OFF) || (prevmode == AUTO) || (prevmode == TV) || (prevmode == E131)) { setModeByStateString(last_state); } + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK /%i", ws2812fx_mode); + #endif + strip.setMode(ws2812fx_mode); + convertColors(); + strip.setColors(0, hex_colors); + strip.setSpeed(convertSpeed(ws2812fx_speed)); + strip.setBrightness(brightness); + prevmode = SET_ALL; + strip.trigger(); + } + + if (mode == SET_MODE) { + mode = HOLD; + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK /%i", ws2812fx_mode); + #endif + strip.setMode(ws2812fx_mode); + prevmode = SET_MODE; + strip.trigger(); + } + + if (mode == SET_COLOR) { + convertColors(); + strip.setColors(0, hex_colors); + mode = prevmode; + prevmode = SET_COLOR; + if (mode == HOLD) strip.trigger(); + } + if (mode == SET_SPEED) { + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK ?%i", ws2812fx_speed); + #endif + strip.setSpeed(convertSpeed(ws2812fx_speed)); + mode = prevmode; + prevmode = SET_SPEED; + if (mode == HOLD) strip.trigger(); + } + if (mode == SET_BRIGHTNESS) { + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK %%%i", brightness); + #endif + strip.setBrightness(brightness); + mode = prevmode; + prevmode = SET_BRIGHTNESS; + if (mode == HOLD) strip.trigger(); + } + + if (prevmode != mode) { + if (prevmode != AUTO) { // do not save if AUTO Mode was set + #if defined(ENABLE_STATE_SAVE) + if(!settings_save_state.active()) settings_save_state.once(3, tickerSaveState); + #endif + snprintf(last_state, sizeof last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", prevmode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white, back_color.red, back_color.green, back_color.blue, back_color.white, xtra_color.red, xtra_color.green, xtra_color.blue, xtra_color.white); } + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + mqtt_client.publish(mqtt_outtopic, mqtt_buf); + #endif + #if ENABLE_MQTT == 1 + amqttClient.publish(mqtt_outtopic, qospub, false, mqtt_buf); + #endif + #if defined(ENABLE_HOMEASSISTANT) + if(!ha_send_data.active()) ha_send_data.once(3, tickerSendState); + #endif + #endif + } + #if defined(ENABLE_STATE_SAVE) + if (updateState){ + #if ENABLE_STATE_SAVE == 1 + (writeStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + writeEEPROM(256, 66, last_state); // 256 --> last_state (reserved 66 bytes) + EEPROM.commit(); + updateState = false; + settings_save_state.detach(); + #endif + #endif + } + #if defined(ENABLE_MQTT) + #if defined(ENABLE_HOMEASSISTANT) + if (new_ha_mqtt_msg) sendState(); + #endif + #endif + + prevmode = mode; + + #if defined(ENABLE_REMOTE) + handleRemote(); #endif } diff --git a/Arduino/McLighting/McLighting.ino.nodemcu.bin b/Arduino/McLighting/McLighting.ino.nodemcu.bin deleted file mode 100644 index 5c0627b..0000000 Binary files a/Arduino/McLighting/McLighting.ino.nodemcu.bin and /dev/null differ diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index 8f192e2..64458c0 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -1,101 +1,97 @@ -#define USE_WS2812FX_DMA // Uses PIN is ignored & set to RX/GPIO3 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX -//#define USE_WS2812FX_UART1 // Uses PIN is ignored & set to D4/GPIO2 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX -//#define USE_WS2812FX_UART2 // Uses PIN is ignored & set to TX/GPIO1 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX +; +#define USE_WS2812FX_DMA 0 // 0 = Used PIN is ignored & set to RX/GPIO3; 1 = Used PIN is ignored & set to D4/GPIO2; 2 = Uses PIN is ignored & set to TX/GPIO1; Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX // Neopixel #define PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached #define NUMLEDS 144 // 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 14 // Input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button. -#define BUTTON_GY33 12 // Input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button. +#define LED_BUILTIN 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192 #define RGBW // If defined, use RGBW Strips -const char HOSTNAME[] = "McLightingRGBW"; // Friedly hostname +const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname -#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 -//#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT or ENABLE_AMQTT must be active -#define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control -//#define ENABLE_BUTTON_GY33 // If defined, enable button handling code for GY-33 color sensor to scan color -//#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth -#define ENABLE_LEGACY_ANIMATIONS // Enable Legacy Animations -#define ENABLE_E131 // E1.31 implementation You have to uncomment #define USE_WS2812FX_DMA -#define ENABLE_TV // Enable TV Animation +#define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code. +#define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client +//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname +#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active +#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth +#define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button. +//#define ENABLE_BUTTON_GY33 12 // If defined, enable button handling code for GY-33 color sensor to scan color. The value defines the input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button. +//#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out -#ifdef ENABLE_E131 +#define ENABLE_STATE_SAVE 1 // If defined, save state on reboot, if set to 0 in EEPROM, if set to 1 on SPIFFS + +#define ENABLE_LEGACY_ANIMATIONS // Enable Legacy Animations +#define ENABLE_E131 // E1.31 implementation You have to uncomment #define USE_WS2812FX_DMA and set it to 0 +#define ENABLE_TV // Enable TV Animation + +#if defined(ENABLE_E131) #define START_UNIVERSE 1 // First DMX Universe to listen for #define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE #endif +#if defined(ENABLE_REMOTE) + int selected_color = 1; + int chng = 1; + uint64_t last_remote_cmd; + enum RMT_BTN {ON_OFF, MODE_UP, MODE_DOWN, RED_UP, RED_DOWN, GREEN_UP, GREEN_DOWN, BLUE_UP, BLUE_DOWN, WHITE_UP, WHITE_DOWN, BRIGHTNESS_UP, BRIGHTNESS_DOWN, SPEED_UP, SPEED_DOWN, COL_M, COL_B, COL_X, AUTOMODE, CUST_1, CUST_2, CUST_3, CUST_4, CUST_5, REPEATCMD, BTN_CNT}; + // Change your IR Commands here. You can see them in console, after you pressed a button on the remote + uint64_t rmt_commands[BTN_CNT] = {0xF7C03F, 0xF7708F, 0xF7F00F, 0xF720DF, 0xF710EF, 0xF7A05F, 0xF7906F, 0xF7609F, 0xF750AF, 0xF7E01F, 0xF7D02F, 0xF730CF, 0xF7B04F, 0xF748B7, 0xF7C837, 0xF700FF, 0xF7807F, 0xF740BF, 0xF708F7, 0xF78877, 0xF728D7, 0xF7A857, 0xF76897, 0xF7E817, 0xFFFFFFFFFFFFFFFF}; +#endif //#define WIFIMGR_PORTAL_TIMEOUT 180 //#define WIFIMGR_SET_MANUAL_IP -#ifdef WIFIMGR_SET_MANUAL_IP +#if defined(WIFIMGR_SET_MANUAL_IP) uint8_t _ip[4] = {192,168,0,128}; uint8_t _gw[4] = {192,168,0,1}; uint8_t _sn[4] = {255,255,255,0}; #endif -#ifdef MQTT_HOME_ASSISTANT_SUPPORT +#if defined(MQTT_HOME_ASSISTANT_SUPPORT) #define MQTT_HOME_ASSISTANT_0_84_SUPPORT // Comment if using HA version < 0.84 #endif -#if defined(USE_WS2812FX_DMA) and defined(USE_WS2812FX_UART) -#error "Cant have both DMA and UART method." -#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)) ) +#if defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT) #error "To use HA, you have to either enable PubCubClient or AsyncMQTT" #endif -#if ( !defined(ENABLE_HOMEASSISTANT) and defined(MQTT_HOME_ASSISTANT_SUPPORT) ) +#if !defined(ENABLE_HOMEASSISTANT) and defined(MQTT_HOME_ASSISTANT_SUPPORT) #error "To use HA support, you have to either enable Homeassistant component" #endif // parameters for automatically cycling favorite patterns -uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds) - {0xff000000, 120, 1, 5}, // blink red for 5 seconds - {0x00ff0000, 120, 3, 10}, // wipe green for 10 seconds - {0x0000ff00, 196, 14, 5}, // dual scan blue for 5 seconds - {0x0000ff00, 196, 46, 15} // fireworks for 15 seconds +uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mode, duration (seconds) + {0xff000000, 0x00ff0000, 0x00000000, 200, 1, 5}, // blink red/geen for 5 seconds + {0x00ff0000, 0x0000ff00, 0x00000000, 200, 3, 10}, // wipe green/blue for 10 seconds + {0x0000ff00, 0xff000000, 0x00000000, 60, 14, 10}, // dual scan blue on red for 10 seconds + {0x0000ff00, 0xff000000, 0x00000000, 40, 45, 15}, // fireworks blue/red for 15 seconds + {0xff000000, 0x00ff0000, 0x0000ff00, 40, 54, 15} // tricolor chase red/green/blue for 15 seconds }; -#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) - #ifdef ENABLE_MQTT +#if defined(ENABLE_MQTT) + char mqtt_buf[80]; + char mqtt_intopic[strlen(HOSTNAME) + 3 + 1]; // Topic in will be: /in + char mqtt_outtopic[strlen(HOSTNAME) + 4 + 1]; // Topic out will be: /out + #if ENABLE_MQTT == 0 #define MQTT_MAX_PACKET_SIZE 2048 #define MQTT_MAX_RECONNECT_TRIES 4 - int mqtt_reconnect_retries = 0; - char mqtt_intopic[strlen(HOSTNAME) + 4 + 5]; // Topic in will be: /in - char mqtt_outtopic[strlen(HOSTNAME) + 5 + 5]; // Topic out will be: /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"; + #if ENABLE_MQTT == 1 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"; - + #if defined(ENABLE_HOMEASSISTANT) + char mqtt_ha_state_in[5 + strlen(HOSTNAME) + 12 + 1]; // Topic in will be: home/_ha/state/in" + char mqtt_ha_state_out[5 + strlen(HOSTNAME) + 13 + 1]; // Topic in will be: home/_ha/state/out" const char* on_cmd = "ON"; const char* off_cmd = "OFF"; - bool stateOn = false; - bool animation_on = false; bool new_ha_mqtt_msg = false; uint16_t color_temp = 327; // min is 154 and max is 500 #endif - //#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname - #ifdef ENABLE_MQTT_HOSTNAME_CHIPID + #if defined(ENABLE_MQTT_HOSTNAME_CHIPID) char mqtt_clientid[64]; #else const char* mqtt_clientid = HOSTNAME; @@ -114,16 +110,8 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds) #define DBG_OUTPUT_PORT Serial // Set debug output port // List of all color modes -#ifdef ENABLE_LEGACY_ANIMATIONS - enum MODE {OFF, AUTO, TV, E131, SET_MODE, HOLD, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW}; - MODE mode = RAINBOW; // Standard mode that is active when software starts -#else - enum MODE {OFF, AUTO, TV, E131, SET_MODE, HOLD, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS}; - MODE mode = SET_MODE; // Standard mode that is active when software starts -#endif -#ifdef ENABLE_TV - bool exit_func = false; // Global helper variable to get out of the color modes when mode changes -#endif +enum MODE {OFF, AUTO, TV, E131, CUSTOM, HOLD, SET_ALL, SET_MODE, SET_COLOR, SET_SPEED, SET_BRIGHTNESS}; +MODE mode = SET_MODE; // Standard mode that is active when software starts MODE prevmode = mode; int ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster @@ -133,6 +121,7 @@ int ws2812fx_mode = 0; // Helper variable to set WS2812FX modes bool shouldSaveConfig = false; // For WiFiManger custom config +uint32_t hex_colors[3] = {}; // Color array for setting WS2812FX struct ledstate // Data structure to store a state of a single led { uint8_t red; @@ -144,33 +133,19 @@ struct ledstate // Data structure to store a state of a single le 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, 0 }; // Store the "main color" of the strip used in single color modes +LEDState back_color = { 0, 0, 0, 0 }; // Store the "2nd color" of the strip used in single color modes +LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes - -#define ENABLE_STATE_SAVE_SPIFFS // If defined, saves state on SPIFFS -//#define ENABLE_STATE_SAVE_EEPROM // If defined, save state on reboot - -char beforeoffauto_state[36]; // Keeps the state representation before auto mode -#ifdef ENABLE_STATE_SAVE_EEPROM - char current_state[36]; // Keeps the current state representation - char last_state[36]; // 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 +char last_state[67]; // Keeps the state representation before auto or off mode +bool updateState = false; // Button handling -#if defined(ENABLE_BUTTON) || defined(ENABLE_BUTTON_GY33) - boolean buttonState = false; -#endif - -#ifdef ENABLE_BUTTON - #define BTN_MODE_SHORT "STA| 1| 0|245|196| 0| 0| 0|255" // Static white - #define BTN_MODE_MEDIUM "STA| 1| 48|245|196|255|102| 0| 0" // Fire flicker - #define BTN_MODE_LONG "STA| 1| 46|253|196|255|102| 0| 0" // Fireworks random +#if defined(ENABLE_BUTTON) +//#define BTN_MODE_SHORT "STA|mo|fxm| h| s| r1| g1| b1| w1| r2| g2| b2| w2| r3| g3| b3| w3" // Example + #define BTN_MODE_SHORT "STA| 5| 0|255|196| 0| 0| 0|255| 0| 0| 0| 0| 0| 0| 0| 0" // Static white + #define BTN_MODE_MEDIUM "STA| 5| 48|200|196|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fire flicker + #define BTN_MODE_LONG "STA| 5| 46|200|196|255|102| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0" // Fireworks random unsigned long keyPrevMillis = 0; const unsigned long keySampleIntervalMs = 25; byte longKeyPressCountMax = 80; // 80 * 25 = 2000 ms @@ -179,7 +154,7 @@ char beforeoffauto_state[36]; // Keeps the state representation befor byte prevKeyState = HIGH; // button is active low #endif -#ifdef ENABLE_BUTTON_GY33 +#if defined(ENABLE_BUTTON_GY33) unsigned long keyPrevMillis_gy33 = 0; const unsigned long keySampleIntervalMs_gy33 = 25; byte longKeyPressCountMax_gy33 = 80; // 80 * 25 = 2000 ms diff --git a/Arduino/McLighting/colormodes.h b/Arduino/McLighting/mode_tv.h similarity index 75% rename from Arduino/McLighting/colormodes.h rename to Arduino/McLighting/mode_tv.h index 039c464..7871484 100644 --- a/Arduino/McLighting/colormodes.h +++ b/Arduino/McLighting/mode_tv.h @@ -1,100 +1,78 @@ -// *************************************************************************** -// Color modes -// *************************************************************************** - -int dipInterval = 10; -int darkTime = 250; -unsigned long currentDipTime; -unsigned long dipStartTime; -unsigned long currentMillis; -int ledState = LOW; -long previousMillis = 0; -int led = 5; -int interval = 2000; -int twitch = 50; -int dipCount = 0; -int analogLevel = 100; -boolean timeToDip = false; -int ledStates[NUMLEDS]; - - -void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) { - // Source: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/ - uint8_t temp[5], n = (index >> 8) % 3; - temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255); - temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); - temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); - - strip.setPixelColor(myled, temp[n + 2], temp[n + 1], temp[n], 0); -} - - -void updateLed (int led, int brightness) { - ledStates[led] = brightness; - - for (int i=0; i interval) - { - previousMillis = currentMillis; - //interval = random(750,4001);//Adjusts the interval for more/less frequent random light changes - interval = random(1000-(ws2812fx_speed*2),5001-(ws2812fx_speed*8)); - twitch = random(40,100);// Twitch provides motion effect but can be a bit much if too high - dipCount = dipCount++; - } - if(currentMillis-previousMillis dipInterval) - { - DBG_OUTPUT_PORT.println("dip"); - timeToDip = true; - dipCount = 0; - dipStartTime = millis(); - darkTime = random(50,150); - dipInterval = random(5,250);// cycles of flicker - } - //strip.show(); - } - } - else - { - DBG_OUTPUT_PORT.println("Dip Time"); - currentDipTime = millis(); - if (currentDipTime - dipStartTime < darkTime) - { - for (int i=3; i> 8) % 3; + temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255); + temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); + temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); + strip.setPixelColor(myled, temp[n + 2], temp[n + 1], temp[n], 0); +} + + +void updateLed (int led, int brightness) { + ledStates[led] = brightness; + for (int i=0; i interval) { + previousMillis = currentMillis; + //interval = random(750,4001);//Adjusts the interval for more/less frequent random light changes + interval = random(1000-(ws2812fx_speed*2),5001-(ws2812fx_speed*8)); + twitch = random(40,100);// Twitch provides motion effect but can be a bit much if too high + dipCount = dipCount++; + } + if(currentMillis-previousMillis dipInterval) { + DBG_OUTPUT_PORT.println("dip"); + timeToDip = true; + dipCount = 0; + dipStartTime = millis(); + darkTime = random(50,150); + dipInterval = random(5,250);// cycles of flicker + } + } + } else { + DBG_OUTPUT_PORT.println("Dip Time"); + currentDipTime = millis(); + if (currentDipTime - dipStartTime < darkTime) { + for (int i=3; i NUMLEDS) ? (NUMLEDS - multipacketOffset) : 128; + #else*/ + uint16_t multipacketOffset = (universe - START_UNIVERSE) * 170; //if more than 170 LEDs * 3 colors = 510 channels, client will send in next higher universe if (NUMLEDS <= multipacketOffset) return; uint16_t len = (170 + multipacketOffset > NUMLEDS) ? (NUMLEDS - multipacketOffset) : 170; +/* #endif */ for (uint16_t i = 0; i < len; i++){ uint16_t j = i * 3; - strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2]); +/* #if defined(RGBW) + strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], data[j + 3]); + #else */ + strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], 0); +/* #endif */ } strip.show(); - checkForRequests(); } } #endif -#ifdef ENABLE_HOMEASSISTANT -void tickerSendState(){ - new_ha_mqtt_msg = true; +// Call convertColors whenever main_color, back_color or xtra_color changes. +void convertColors() { + hex_colors[0] = (uint32_t)(main_color.white << 24) | (main_color.red << 16) | (main_color.green << 8) | main_color.blue; + hex_colors[1] = (uint32_t)(back_color.white << 24) | (back_color.red << 16) | (back_color.green << 8) | back_color.blue; + hex_colors[2] = (uint32_t)(xtra_color.white << 24) | (xtra_color.red << 16) | (xtra_color.green << 8) | xtra_color.blue; } -#endif -#ifdef ENABLE_STATE_SAVE_SPIFFS -void tickerSpiffsSaveState(){ - updateStateFS = true; -} -#endif void getArgs() { if (server.arg("rgb") != "") { @@ -67,6 +74,46 @@ void getArgs() { main_color.white = server.arg("w").toInt(); } } + if (server.arg("rgb2") != "") { + uint32_t rgb2 = (uint32_t) strtoul(server.arg("rgb2").c_str(), NULL, 16); + back_color.white = ((rgb2 >> 24) & 0xFF); + back_color.red = ((rgb2 >> 16) & 0xFF); + back_color.green = ((rgb2 >> 8) & 0xFF); + back_color.blue = ((rgb2 >> 0) & 0xFF); + } else { + if ((server.arg("r2") != "") && (server.arg("r2").toInt() >= 0) && (server.arg("r2").toInt() <= 255)) { + back_color.red = server.arg("r2").toInt(); + } + if ((server.arg("g2") != "") && (server.arg("g2").toInt() >= 0) && (server.arg("g2").toInt() <= 255)) { + back_color.green = server.arg("g2").toInt(); + } + if ((server.arg("b2") != "") && (server.arg("b2").toInt() >= 0) && (server.arg("b2").toInt() <= 255)) { + back_color.blue = server.arg("b2").toInt(); + } + if ((server.arg("w2") != "") && (server.arg("w2").toInt() >= 0) && (server.arg("w2").toInt() <= 255)){ + back_color.white = server.arg("w2").toInt(); + } + } + if (server.arg("rgb3") != "") { + uint32_t rgb3 = (uint32_t) strtoul(server.arg("rgb3").c_str(), NULL, 16); + xtra_color.white = ((rgb3 >> 24) & 0xFF); + xtra_color.red = ((rgb3 >> 16) & 0xFF); + xtra_color.green = ((rgb3 >> 8) & 0xFF); + xtra_color.blue = ((rgb3 >> 0) & 0xFF); + } else { + if ((server.arg("r3") != "") && (server.arg("r3").toInt() >= 0) && (server.arg("r3").toInt() <= 255)) { + xtra_color.red = server.arg("r3").toInt(); + } + if ((server.arg("g3") != "") && (server.arg("g3").toInt() >= 0) && (server.arg("g3").toInt() <= 255)) { + xtra_color.green = server.arg("g3").toInt(); + } + if ((server.arg("b3") != "") && (server.arg("b3").toInt() >= 0) && (server.arg("b3").toInt() <= 255)) { + xtra_color.blue = server.arg("b3").toInt(); + } + if ((server.arg("w3") != "") && (server.arg("w3").toInt() >= 0) && (server.arg("w3").toInt() <= 255)){ + xtra_color.white = server.arg("w3").toInt(); + } + } if ((server.arg("s") != "") && (server.arg("s").toInt() >= 0) && (server.arg("s").toInt() <= 255)) { ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255); } @@ -85,21 +132,17 @@ void getArgs() { main_color.green = constrain(main_color.green, 0, 255); main_color.blue = constrain(main_color.blue, 0, 255); main_color.white = constrain(main_color.white, 0, 255); - - DBG_OUTPUT_PORT.print("Mode: "); - DBG_OUTPUT_PORT.print(mode); - DBG_OUTPUT_PORT.print(", Color: "); - DBG_OUTPUT_PORT.print(main_color.red); - DBG_OUTPUT_PORT.print(", "); - DBG_OUTPUT_PORT.print(main_color.green); - DBG_OUTPUT_PORT.print(", "); - DBG_OUTPUT_PORT.print(main_color.blue); - DBG_OUTPUT_PORT.print(", "); - DBG_OUTPUT_PORT.print(main_color.white); - DBG_OUTPUT_PORT.print(", Speed:"); - DBG_OUTPUT_PORT.print(ws2812fx_speed); - DBG_OUTPUT_PORT.print(", Brightness:"); - DBG_OUTPUT_PORT.println(brightness); + back_color.red = constrain(back_color.red, 0, 255); + back_color.green = constrain(back_color.green, 0, 255); + back_color.blue = constrain(back_color.blue, 0, 255); + back_color.white = constrain(back_color.white, 0, 255); + xtra_color.red = constrain(xtra_color.red, 0, 255); + xtra_color.green = constrain(xtra_color.green, 0, 255); + xtra_color.blue = constrain(xtra_color.blue, 0, 255); + xtra_color.white = constrain(xtra_color.white, 0, 255); + convertColors(); + DBG_OUTPUT_PORT.print("Get Args: "); + DBG_OUTPUT_PORT.println(listStatusJSON()); } @@ -126,12 +169,26 @@ void handleSetMainColor(uint8_t * mypayload) { main_color.red = ((rgb >> 16) & 0xFF); main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 0) & 0xFF); -// strip.setColor(main_color.red, main_color.green, main_color.blue); - #ifdef ENABLE_TV - exit_func = true; - #endif - prevmode = mode; - mode = SETCOLOR; + mode = SET_COLOR; +} + +void handleSetBackColor(uint8_t * mypayload) { + // decode rgb data + uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[2], NULL, 16); + back_color.white = ((rgb >> 24) & 0xFF); + back_color.red = ((rgb >> 16) & 0xFF); + back_color.green = ((rgb >> 8) & 0xFF); + back_color.blue = ((rgb >> 0) & 0xFF); + mode = SET_COLOR; +} +void handleSetXtraColor(uint8_t * mypayload) { + // decode rgb data + uint32_t rgb = (uint32_t) strtoul((const char *) &mypayload[3], NULL, 16); + xtra_color.white = ((rgb >> 24) & 0xFF); + xtra_color.red = ((rgb >> 16) & 0xFF); + xtra_color.green = ((rgb >> 8) & 0xFF); + xtra_color.blue = ((rgb >> 0) & 0xFF); + mode = SET_COLOR; } void handleSetAllMode(uint8_t * mypayload) { @@ -142,11 +199,8 @@ void handleSetAllMode(uint8_t * mypayload) { main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 0) & 0xFF); DBG_OUTPUT_PORT.printf("WS: Set all leds to main color: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white); - #ifdef ENABLE_TV - exit_func = true; - #endif ws2812fx_mode = FX_MODE_STATIC; - mode = SET_MODE; + mode = SET_ALL; } void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { @@ -175,9 +229,6 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { strip.setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white); strip.show(); } - #ifdef ENABLE_TV - exit_func = true; - #endif mode = CUSTOM; } @@ -228,11 +279,10 @@ void handleRangeDifferentColors(uint8_t * mypayload) { } void setModeByStateString(String saved_state_string) { -#ifdef ENABLE_TV - exit_func = true; -#endif String str_mode = getValue(saved_state_string, '|', 1); mode = static_cast(str_mode.toInt()); + DBG_OUTPUT_PORT.print("mode: "); + DBG_OUTPUT_PORT.println(mode); String str_ws2812fx_mode = getValue(saved_state_string, '|', 2); ws2812fx_mode = str_ws2812fx_mode.toInt(); String str_ws2812fx_speed = getValue(saved_state_string, '|', 3); @@ -247,123 +297,117 @@ void setModeByStateString(String saved_state_string) { main_color.blue = str_blue.toInt(); String str_white = getValue(saved_state_string, '|', 8); main_color.white = str_white.toInt(); - DBG_OUTPUT_PORT.printf("Mode: %d\n", mode); - DBG_OUTPUT_PORT.printf("ws2812fx_mode: %d\n", ws2812fx_mode); - DBG_OUTPUT_PORT.printf("ws2812fx_speed: %d\n", ws2812fx_speed); - DBG_OUTPUT_PORT.printf("brightness: %d\n", brightness); - DBG_OUTPUT_PORT.printf("main_color.red: %d\n", main_color.red); - DBG_OUTPUT_PORT.printf("main_color.green: %d\n", main_color.green); - DBG_OUTPUT_PORT.printf("main_color.blue: %d\n", main_color.blue); - DBG_OUTPUT_PORT.printf("main_color.white: %d\n", main_color.white); - - strip.setMode(ws2812fx_mode); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - strip.setBrightness(brightness); - strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - strip.trigger(); + str_red = getValue(saved_state_string, '|', 9); + back_color.red = str_red.toInt(); + str_green = getValue(saved_state_string, '|', 10); + back_color.green = str_green.toInt(); + str_blue = getValue(saved_state_string, '|', 11); + back_color.blue = str_blue.toInt(); + str_white = getValue(saved_state_string, '|', 12); + back_color.white = str_white.toInt(); + str_red = getValue(saved_state_string, '|', 13); + xtra_color.red = str_red.toInt(); + str_green = getValue(saved_state_string, '|', 14); + xtra_color.green = str_green.toInt(); + str_blue = getValue(saved_state_string, '|', 15); + xtra_color.blue = str_blue.toInt(); + str_white = getValue(saved_state_string, '|', 16); + xtra_color.white = str_white.toInt(); + convertColors(); + DBG_OUTPUT_PORT.print("Set to state: "); + DBG_OUTPUT_PORT.println(listStatusJSON()); } -void handleSetNamedMode(String str_mode) { -#ifdef ENABLE_TV - exit_func = true; -#endif - - if (str_mode.startsWith("=off") or str_mode.startsWith("/off")) { +#if defined(ENABLE_LEGACY_ANIMATIONS) +void handleSetNamedMode(uint8_t * mypayload) { + if (strcmp((char *) &mypayload[1], "off") == 0) { mode = OFF; - #ifdef ENABLE_HOMEASSISTANT - stateOn = false; - #endif } - -#ifdef ENABLE_TV - if (str_mode.startsWith("=tv") or str_mode.startsWith("/tv")) { + + #if defined(ENABLE_TV) + if (strcmp((char *) &mypayload[1], "tv") == 0) { mode = TV; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif } -#endif + #endif -#ifdef ENABLE_E131 - if (str_mode.startsWith("=e131") or str_mode.startsWith("/e131")) { - if(strip.isRunning()) strip.stop(); + #if defined(ENABLE_E131) + if (strcmp((char *) &mypayload[1], "e131") == 0) { mode = E131; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif } -#endif - -#ifdef ENABLE_LEGACY_ANIMATIONS - if (str_mode.startsWith("=auto")) { + #endif + + if (strcmp((char *) &mypayload[1], "auto") == 0) { mode = AUTO; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif } - if (str_mode.startsWith("=all")) { + if (strcmp((char *) &mypayload[1], "all") == 0) { ws2812fx_mode = FX_MODE_STATIC; + mode = SET_ALL; + } + if (strcmp((char *) &mypayload[1], "wipe") == 0) { + ws2812fx_mode = FX_MODE_COLOR_WIPE; mode = SET_MODE; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif } - if (str_mode.startsWith("=wipe")) { - mode = WIPE; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif + if (strcmp((char *) &mypayload[1], "rainbow") == 0) { + ws2812fx_mode = FX_MODE_RAINBOW; + mode = SET_MODE; } - if (str_mode.startsWith("=rainbow")) { - mode = RAINBOW; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif + if (strcmp((char *) &mypayload[1], "rainbowCycle") == 0) { + ws2812fx_mode = FX_MODE_RAINBOW_CYCLE; + mode = SET_MODE; } - if (str_mode.startsWith("=rainbowCycle")) { - mode = RAINBOWCYCLE; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif + if (strcmp((char *) &mypayload[1], "theaterchase") == 0) { + ws2812fx_mode = FX_MODE_THEATER_CHASE; + mode = SET_MODE; } - if (str_mode.startsWith("=theaterchase")) { - mode = THEATERCHASE; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif + if (strcmp((char *) &mypayload[1], "twinkleRandom") == 0) { + ws2812fx_mode = FX_MODE_TWINKLE_RANDOM; + mode = SET_MODE; } - if (str_mode.startsWith("=twinkleRandom")) { - mode = TWINKLERANDOM; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif - } - if (str_mode.startsWith("=theaterchaseRainbow")) { - mode = THEATERCHASERAINBOW; - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - #endif + if (strcmp((char *) &mypayload[1], "theaterchaseRainbow") == 0) { + ws2812fx_mode = FX_MODE_THEATER_CHASE_RAINBOW; + mode = SET_MODE; } #endif } + void handleSetWS2812FXMode(uint8_t * mypayload) { - uint8_t ws2812fx_mode_tmp = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10); - ws2812fx_mode = constrain(ws2812fx_mode_tmp, 0, strip.getModeCount() - 1); - #ifdef ENABLE_TV - exit_func = true; - #endif - mode = SET_MODE; + if (isDigit(mypayload[1])) { + ws2812fx_mode = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10); + ws2812fx_mode = constrain(ws2812fx_mode, 0, strip.getModeCount() - 1); + mode = SET_MODE; + } else { + if (strcmp((char *) &mypayload[1], "off") == 0) { + mode = OFF; + } + + if (strcmp((char *) &mypayload[1], "auto") == 0) { + mode = AUTO; + } + + #if defined(ENABLE_TV) + if (strcmp((char *) &mypayload[1], "tv") == 0) { + mode = TV; + } + #endif + + #if defined(ENABLE_E131) + if (strcmp((char *) &mypayload[1], "e131") == 0) { + mode = E131; + } + #endif + } } String listStatusJSON(void) { - uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode(); - - const size_t bufferSize = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(6) + 500; + //uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode(); + const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(6) + 150; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject root = jsonBuffer.to(); root["mode"] = (uint8_t) mode; - root["ws2812fx_mode"] = tmp_mode; - root["ws2812fx_mode_name"] = strip.getModeName(tmp_mode); + root["ws2812fx_mode"] = ws2812fx_mode; + root["ws2812fx_mode_name"] = strip.getModeName(ws2812fx_mode); + //root["ws2812fx_mode"] = tmp_mode; + //root["ws2812fx_mode_name"] = strip.getModeName(tmp_mode); root["speed"] = ws2812fx_speed; root["brightness"] = brightness; JsonArray color = root.createNestedArray("color"); @@ -371,10 +415,17 @@ String listStatusJSON(void) { color.add(main_color.red); color.add(main_color.green); color.add(main_color.blue); - + color.add(back_color.white); + color.add(back_color.red); + color.add(back_color.green); + color.add(back_color.blue); + color.add(xtra_color.white); + color.add(xtra_color.red); + color.add(xtra_color.green); + color.add(xtra_color.blue); String json; serializeJson(root, json); - + jsonBuffer.clear(); return json; } @@ -384,32 +435,31 @@ void getStatusJSON() { } String listModesJSON(void) { - const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2) + 1000; + const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount() + 3) + (strip.getModeCount() + 3)*JSON_OBJECT_SIZE(2) + 2000; DynamicJsonDocument jsonBuffer(bufferSize); - JsonArray json = jsonBuffer.to(); - JsonObject objectoff = json.createNestedObject(); + JsonArray root = jsonBuffer.to(); + JsonObject objectoff = root.createNestedObject(); objectoff["mode"] = "off"; objectoff["name"] = "OFF"; - #ifdef ENABLE_TV - JsonObject objecttv = json.createNestedObject(); + #if defined(ENABLE_TV) + JsonObject objecttv = root.createNestedObject(); objecttv["mode"] = "tv"; objecttv["name"] = "TV"; #endif - #ifdef ENABLE_E131 - JsonObject objecte131 = json.createNestedObject(); + #if defined(ENABLE_E131) + JsonObject objecte131 = root.createNestedObject(); objecte131["mode"] = "e131"; objecte131["name"] = "E131"; #endif for (uint8_t i = 0; i < strip.getModeCount(); i++) { - JsonObject object = json.createNestedObject(); + JsonObject object = root.createNestedObject(); object["mode"] = i; object["name"] = strip.getModeName(i); } - JsonObject object = json.createNestedObject(); - - String json_str; - serializeJson(json, json_str); - return json_str; + String json; + serializeJson(root, json); + jsonBuffer.clear(); + return json; } void getModesJSON() { @@ -460,15 +510,18 @@ void handleNotFound() { server.send ( 404, "text/plain", message ); } -// automatic cycling +// *************************************************************************** +// Functions and variables for automatic cycling +// *************************************************************************** Ticker autoTicker; int autoCount = 0; void autoTick() { - strip.setColor(autoParams[autoCount][0]); - strip.setSpeed(convertSpeed((uint8_t)autoParams[autoCount][1])); - strip.setMode((uint8_t)autoParams[autoCount][2]); - autoTicker.once((float)autoParams[autoCount][3], autoTick); + uint32_t setcolors[] = {autoParams[autoCount][0],autoParams[autoCount][1],autoParams[autoCount][2]}; + strip.setColors(0, setcolors); + strip.setSpeed(convertSpeed((uint8_t)autoParams[autoCount][3])); + strip.setMode((uint8_t)autoParams[autoCount][4]); + autoTicker.once((float)autoParams[autoCount][5], autoTick); DBG_OUTPUT_PORT.print("autoTick "); DBG_OUTPUT_PORT.println(autoCount); @@ -477,26 +530,19 @@ void autoTick() { } void handleAutoStart() { - if (mode!=AUTO) { - #ifdef ENABLE_TV - exit_func = true; - #endif - sprintf(beforeoffauto_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, strip.getMode(), ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white); - mode = AUTO; - autoCount = 0; - autoTick(); - strip.start(); - } + DBG_OUTPUT_PORT.println("Starting AUTO mode."); + autoCount = 0; + autoTick(); } void handleAutoStop() { - if (mode==AUTO) { + DBG_OUTPUT_PORT.println("Stopping AUTO mode."); autoTicker.detach(); - strip.stop(); - setModeByStateString(beforeoffauto_state); - } } +// *************************************************************************** +// Functions and variables +// *************************************************************************** void Dbg_Prefix(bool mqtt, uint8_t num) { if (mqtt == true) { DBG_OUTPUT_PORT.print("MQTT: "); @@ -507,70 +553,39 @@ void Dbg_Prefix(bool mqtt, uint8_t num) { } void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { - // # ==> Set main color + // # ==> Set main color - ## ==> Set 2nd color - ### ==> Set 3rd color if (payload[0] == '#') { - handleSetMainColor(payload); - Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set main color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white); - #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; - if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState); + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK %s", payload); #endif + if (payload[2] == '#') { + handleSetXtraColor(payload); + DBG_OUTPUT_PORT.printf("Set 3rd color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", xtra_color.red, xtra_color.green, xtra_color.blue, xtra_color.white); + } else if (payload[1] == '#') { + handleSetBackColor(payload); + DBG_OUTPUT_PORT.printf("Set 2nd color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", back_color.red, back_color.green, back_color.blue, back_color.white); + } else { + handleSetMainColor(payload); + DBG_OUTPUT_PORT.printf("Set main color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white); + } } // ? ==> Set speed if (payload[0] == '?') { uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10); ws2812fx_speed = constrain(d, 0, 255); - #ifdef ENABLE_TV - exit_func = true; - #endif - prevmode = mode; - mode = SETSPEED; + mode = SET_SPEED; Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set speed to: [%u]\n", ws2812fx_speed); - #ifdef ENABLE_HOMEASSISTANT - stateOn = true; - 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 if (payload[0] == '%') { uint8_t b = (uint8_t) strtol((const char *) &payload[1], NULL, 10); brightness = constrain(b, 0, 255); - #ifdef ENABLE_TV - exit_func = true; - #endif - prevmode = mode; - mode = BRIGHTNESS; + mode = SET_BRIGHTNESS; Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("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; - 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) @@ -578,45 +593,26 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { handleSetAllMode(payload); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("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; - 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); Dbg_Prefix(mqtt, num); + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK %s", payload); + #endif DBG_OUTPUT_PORT.printf("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); Dbg_Prefix(mqtt, num); + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK %s", payload); + #endif DBG_OUTPUT_PORT.printf("Set multiple LEDs 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 range of LEDs in the given color @@ -624,36 +620,18 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { handleRangeDifferentColors(payload); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set range of LEDs in given color [%s]\n", 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()); + #if defined(ENABLE_MQTT) + sprintf(mqtt_buf, "OK %s", payload); #endif } - #ifdef ENABLE_LEGACY_ANIMATIONS + #if defined(ENABLE_LEGACY_ANIMATIONS) // = ==> Activate named mode if (payload[0] == '=') { // we get mode data - String str_mode = String((char *) &payload[0]); - - handleSetNamedMode(str_mode); + handleSetNamedMode(payload); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Activated mode [%u]!\n", mode); - #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 - 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 } #endif @@ -662,11 +640,13 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { String json = listStatusJSON(); if (mqtt == true) { DBG_OUTPUT_PORT.print("MQTT: "); - #ifdef ENABLE_MQTT - mqtt_client.publish(mqtt_outtopic, json.c_str()); - #endif - #ifdef ENABLE_AMQTT - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, json.c_str()); + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + mqtt_client.publish(mqtt_outtopic, json.c_str()); + #endif + #if ENABLE_MQTT == 1 + amqttClient.publish(mqtt_outtopic, qospub, false, json.c_str()); + #endif #endif } else { DBG_OUTPUT_PORT.print("WS: "); @@ -681,19 +661,21 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { String json = listModesJSON(); if (mqtt == true) { DBG_OUTPUT_PORT.print("MQTT: "); - #ifdef ENABLE_MQTT - // TODO: Fix this, doesn't return anything. Too long? - // Hint: https://github.com/knolleary/pubsubclient/issues/110 - 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, json.c_str()); + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + // TODO: Fix this, doesn't return anything. Too long? + // Hint: https://github.com/knolleary/pubsubclient/issues/110 + 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 + #if ENABLE_MQTT == 1 + amqttClient.publish(mqtt_outtopic, qospub, false, json.c_str()); + #endif #endif } else { DBG_OUTPUT_PORT.print("WS: "); @@ -707,23 +689,8 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { // / ==> Set WS2812 mode. if (payload[0] == '/') { handleSetWS2812FXMode(payload); - String str_mode = String((char *) &payload[0]); - handleSetNamedMode(str_mode); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("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; - 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 } } @@ -752,138 +719,138 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght // start auto cycling if (strcmp((char *)payload, "start") == 0 ) { - handleAutoStart(); + mode = AUTO; webSocket.sendTXT(num, "OK"); } // stop auto cycling if (strcmp((char *)payload, "stop") == 0 ) { - handleAutoStop(); + mode = SET_ALL; webSocket.sendTXT(num, "OK"); } break; } } -#if defined(ENABLE_TV) || defined(ENABLE_E131) - void checkForRequests() { - webSocket.loop(); - server.handleClient(); - #ifdef ENABLE_MQTT - mqtt_client.loop(); - #endif - } -#endif - - // *************************************************************************** // MQTT callback / connection handler // *************************************************************************** -#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) +#if defined(ENABLE_MQTT) - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_HOMEASSISTANT) + void tickerSendState(){ + new_ha_mqtt_msg = true; + } LEDState temp2rgb(unsigned int kelvin) { - int tmp_internal = kelvin / 100.0; - LEDState tmp_color; + int tmp_internal = kelvin / 100.0; + LEDState tmp_color; - // red - if (tmp_internal <= 66) { - tmp_color.red = 255; - } else { - float tmp_red = 329.698727446 * pow(tmp_internal - 60, -0.1332047592); - if (tmp_red < 0) { - tmp_color.red = 0; - } else if (tmp_red > 255) { - tmp_color.red = 255; - } else { - tmp_color.red = tmp_red; - } - } - - // green - if (tmp_internal <= 66) { - float tmp_green = 99.4708025861 * log(tmp_internal) - 161.1195681661; - if (tmp_green < 0) { - tmp_color.green = 0; - } else if (tmp_green > 255) { - tmp_color.green = 255; - } else { - tmp_color.green = tmp_green; - } - } else { - float tmp_green = 288.1221695283 * pow(tmp_internal - 60, -0.0755148492); - if (tmp_green < 0) { - tmp_color.green = 0; - } else if (tmp_green > 255) { - tmp_color.green = 255; - } else { - tmp_color.green = tmp_green; - } - } - - // blue - if (tmp_internal >= 66) { - tmp_color.blue = 255; - } else if (tmp_internal <= 19) { - tmp_color.blue = 0; - } else { - float tmp_blue = 138.5177312231 * log(tmp_internal - 10) - 305.0447927307; - if (tmp_blue < 0) { - tmp_color.blue = 0; - } else if (tmp_blue > 255) { - tmp_color.blue = 255; - } else { - tmp_color.blue = tmp_blue; - } - } - return tmp_color; - } - - void sendState() { - const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 500; - DynamicJsonDocument jsonBuffer(bufferSize); - JsonObject root = jsonBuffer.to(); - - 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; - color["w"] = main_color.white; - - 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 - #if defined(ENABLE_HOMEASSISTANT) - if (mode == OFF){ - root["effect"] = "OFF"; - } else { - if (mode == TV){ - root["effect"] = "TV"; + // red + if (tmp_internal <= 66) { + tmp_color.red = 255; + } else { + float tmp_red = 329.698727446 * pow(tmp_internal - 60, -0.1332047592); + if (tmp_red < 0) { + tmp_color.red = 0; + } else if (tmp_red > 255) { + tmp_color.red = 255; } else { - if (mode == E131){ - root["effect"] = "E131"; - } else { - root["effect"] = strip.getModeName(strip.getMode()); - } + tmp_color.red = tmp_red; } - } - #endif + } + + // green + if (tmp_internal <= 66) { + float tmp_green = 99.4708025861 * log(tmp_internal) - 161.1195681661; + if (tmp_green < 0) { + tmp_color.green = 0; + } else if (tmp_green > 255) { + tmp_color.green = 255; + } else { + tmp_color.green = tmp_green; + } + } else { + float tmp_green = 288.1221695283 * pow(tmp_internal - 60, -0.0755148492); + if (tmp_green < 0) { + tmp_color.green = 0; + } else if (tmp_green > 255) { + tmp_color.green = 255; + } else { + tmp_color.green = tmp_green; + } + } + + // blue + if (tmp_internal >= 66) { + tmp_color.blue = 255; + } else if (tmp_internal <= 19) { + tmp_color.blue = 0; + } else { + float tmp_blue = 138.5177312231 * log(tmp_internal - 10) - 305.0447927307; + if (tmp_blue < 0) { + tmp_color.blue = 0; + } else if (tmp_blue > 255) { + tmp_color.blue = 255; + } else { + tmp_color.blue = tmp_blue; + } + } + return tmp_color; + } + + void sendState() { + const size_t bufferSize = JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) + 1000; + DynamicJsonDocument jsonBuffer(bufferSize); + JsonObject root = jsonBuffer.to(); + root["state"] = (mode != OFF) ? on_cmd : off_cmd; + JsonObject color = root.createNestedObject("color"); + color["r"] = main_color.red; + color["g"] = main_color.green; + color["b"] = main_color.blue; + color["w"] = main_color.white; + color["r2"] = back_color.red; + color["g2"] = back_color.green; + color["b2"] = back_color.blue; + color["w2"] = back_color.white; + color["r3"] = xtra_color.red; + color["g3"] = xtra_color.green; + color["b3"] = xtra_color.blue; + color["w3"] = xtra_color.white; + 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 + #if defined(ENABLE_HOMEASSISTANT) + if (mode == OFF){ + root["effect"] = "OFF"; + } else { + if (mode == AUTO){ + root["effect"] = "AUTO"; + } else { + if (mode == TV){ + root["effect"] = "TV"; + } else { + if (mode == E131){ + root["effect"] = "E131"; + } else { + root["effect"] = strip.getModeName(strip.getMode()); + } + } + } + } + #endif char buffer[measureJson(root) + 1]; serializeJson(root, 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); + jsonBuffer.clear(); + #if ENABLE_MQTT == 0 + mqtt_client.publish(mqtt_ha_state_out, buffer, true); + DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out, 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); + #if ENABLE_MQTT == 1 + amqttClient.publish(mqtt_ha_state_out, 1, true, buffer); + DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out, buffer); #endif new_ha_mqtt_msg = false; ha_send_data.detach(); @@ -891,12 +858,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } bool processJson(char* message) { - const size_t bufferSize = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + 150; + const size_t bufferSize = JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(12) + 500; DynamicJsonDocument jsonBuffer(bufferSize); DeserializationError error = deserializeJson(jsonBuffer, message); if (error) { DBG_OUTPUT_PORT.print("parseObject() failed: "); DBG_OUTPUT_PORT.println(error.c_str()); + jsonBuffer.clear(); return false; } //DBG_OUTPUT_PORT.println("JSON ParseObject() done!"); @@ -904,15 +872,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght if (root.containsKey("state")) { const char* state_in = root["state"]; - if (strcmp(state_in, on_cmd) == 0 and !(animation_on)) { - stateOn = true; - ws2812fx_mode = FX_MODE_STATIC; - mode = SET_MODE; + if (strcmp(state_in, on_cmd) == 0) { + mode = SET_ALL; } else if (strcmp(state_in, off_cmd) == 0) { - stateOn = false; - animation_on = false; mode = OFF; + jsonBuffer.clear(); return true; } } @@ -923,17 +888,22 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght main_color.green = (uint8_t) color["g"]; main_color.blue = (uint8_t) color["b"]; main_color.white = (uint8_t) color["w"]; - prevmode = mode; - mode = SETCOLOR; + back_color.red = (uint8_t) color["r2"]; + back_color.green = (uint8_t) color["g2"]; + back_color.blue = (uint8_t) color["b2"]; + back_color.white = (uint8_t) color["w2"]; + xtra_color.red = (uint8_t) color["r3"]; + xtra_color.green = (uint8_t) color["g3"]; + xtra_color.blue = (uint8_t) color["b3"]; + xtra_color.white = (uint8_t) color["w3"]; + mode = SET_COLOR; } if (root.containsKey("speed")) { uint8_t json_speed = constrain((uint8_t) root["speed"], 0, 255); if (json_speed != ws2812fx_speed) { ws2812fx_speed = json_speed; - //if(stateOn) mode = SETSPEED; - prevmode = mode; - mode = SETSPEED; + mode = SET_SPEED; } } @@ -942,30 +912,37 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght color_temp = (uint16_t) root["color_temp"]; unsigned int kelvin = 1000000 / color_temp; main_color = temp2rgb(kelvin); - prevmode = mode; - mode = SETCOLOR; + mode = SET_COLOR; } if (root.containsKey("brightness")) { uint8_t json_brightness = constrain((uint8_t) root["brightness"], 0, 255); //fix #224 if (json_brightness != brightness) { - prevmode = mode; - mode = BRIGHTNESS; + mode = SET_BRIGHTNESS; } } if (root.containsKey("effect")) { - animation_on = true; String effectString = root["effect"].as(); - - for (uint8_t i = 0; i < strip.getModeCount(); i++) { - #if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT) - if(effectString == "E131"){ - if(strip.isRunning()) strip.stop(); - mode = E131; - break; + #if defined(ENABLE_HOMEASSISTANT) + if(effectString == "OFF"){ + mode = OFF; } - #endif + if(effectString == "AUTO"){ + mode = AUTO; + } + #endif + #if defined(ENABLE_TV) and defined(ENABLE_HOMEASSISTANT) + if(effectString == "TV"){ + mode = TV; + } + #endif + #if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT) + if(effectString == "E131"){ + mode = E131; + } + #endif + for (uint8_t i = 0; i < strip.getModeCount(); i++) { if(String(strip.getModeName(i)) == effectString) { mode = SET_MODE; ws2812fx_mode = i; @@ -978,7 +955,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } #endif - #ifdef ENABLE_AMQTT + #if ENABLE_MQTT == 1 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); @@ -988,39 +965,37 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght DBG_OUTPUT_PORT.printf("]: %s\n", payload); #endif - #ifdef ENABLE_MQTT + #if ENABLE_MQTT == 0 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] = 0; 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 defined(ENABLE_HOMEASSISTANT) + if (strcmp(topic, mqtt_ha_state_in) == 0) { if (!processJson((char*)payload)) { return; } 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 + #if ENABLE_MQTT == 0 } else if (strcmp(topic, (char *)mqtt_intopic) == 0) { - #endif - #ifdef ENABLE_AMQTT - } else if (strcmp(topic, mqtt_intopic.c_str()) == 0) { #endif + #if ENABLE_MQTT == 1 + } else if (strcmp(topic, mqtt_intopic) == 0) { + #endif #endif checkpayload(payload, true); - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_HOMEASSISTANT) } #endif free(payload); } - #ifdef ENABLE_MQTT + #if ENABLE_MQTT == 0 void mqtt_reconnect() { // Loop until we're reconnected while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { @@ -1036,14 +1011,15 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght mqtt_client.publish(mqtt_outtopic, message); // ... and resubscribe mqtt_client.subscribe(mqtt_intopic, qossub); - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); - mqtt_client.subscribe(mqtt_ha_state_in.c_str(), qossub); - #ifdef MQTT_HOME_ASSISTANT_SUPPORT - DynamicJsonDocument jsonBuffer(JSON_ARRAY_SIZE(strip.getModeCount()) + JSON_OBJECT_SIZE(12) + 1500); + mqtt_client.subscribe(mqtt_ha_state_in, qossub); + #if defined(MQTT_HOME_ASSISTANT_SUPPORT) + const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; + DynamicJsonDocument jsonBuffer(bufferSize); JsonObject json = jsonBuffer.to(); json["name"] = HOSTNAME; - #ifdef MQTT_HOME_ASSISTANT_0_84_SUPPORT + #if defined(MQTT_HOME_ASSISTANT_0_84_SUPPORT) json["schema"] = "json"; #else json["platform"] = "mqtt_json"; @@ -1057,20 +1033,20 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght json["color_temp"] = "true"; json["effect"] = "true"; JsonArray effect_list = json.createNestedArray("effect_list"); + effect_list.add("OFF"); + effect_list.add("AUTO"); + #if defined(ENABLE_TV) + effect_list.add("TV"); + #endif + #if defined(ENABLE_E131) + effect_list.add("E131"); + #endif for (uint8_t i = 0; i < strip.getModeCount(); i++) { effect_list.add(strip.getModeName(i)); } - #ifdef MQTT_HOME_ASSISTANT_SUPPORT - effect_list.add("OFF"); - #ifdef ENABLE_TV - effect_list.add("TV"); - #endif - #ifdef ENABLE_E131 - effect_list.add("E131"); - #endif - #endif char buffer[measureJson(json) + 1]; serializeJson(json, buffer, sizeof(buffer)); + jsonBuffer.clear(); mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true); #endif #endif @@ -1090,7 +1066,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } } #endif - #ifdef ENABLE_AMQTT + #if ENABLE_MQTT == 1 void connectToWifi() { DBG_OUTPUT_PORT.println("Re-connecting to Wi-Fi..."); WiFi.setSleepMode(WIFI_NONE_SLEEP); @@ -1110,7 +1086,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { DBG_OUTPUT_PORT.println("Disconnected from Wi-Fi."); - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); #endif mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi @@ -1124,19 +1100,20 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght char * message = new char[18 + strlen(HOSTNAME) + 1]; strcpy(message, "McLighting ready: "); strcat(message, HOSTNAME); - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, message); + amqttClient.publish(mqtt_outtopic, qospub, false, message); //Subscribe - uint16_t packetIdSub1 = amqttClient.subscribe((char *)mqtt_intopic.c_str(), qossub); + uint16_t packetIdSub1 = amqttClient.subscribe((char *)mqtt_intopic, qossub); DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub1); - #ifdef ENABLE_HOMEASSISTANT + #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); - uint16_t packetIdSub2 = amqttClient.subscribe((char *)mqtt_ha_state_in.c_str(), qossub); + uint16_t packetIdSub2 = amqttClient.subscribe((char *)mqtt_ha_state_in, qossub); DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub2); - #ifdef MQTT_HOME_ASSISTANT_SUPPORT - DynamicJsonDocument jsonBuffer(JSON_ARRAY_SIZE(strip.getModeCount()) + JSON_OBJECT_SIZE(12) + 1500); + #if defined(MQTT_HOME_ASSISTANT_SUPPORT) + const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; + DynamicJsonDocument jsonBuffer(bufferSize); JsonObject json = jsonBuffer.to(); json["name"] = HOSTNAME; - #ifdef MQTT_HOME_ASSISTANT_0_84_SUPPORT + #if defined(MQTT_HOME_ASSISTANT_0_84_SUPPORT) json["schema"] = "json"; #else json["platform"] = "mqtt_json"; @@ -1150,21 +1127,20 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght json["color_temp"] = "true"; json["effect"] = "true"; JsonArray effect_list = json.createNestedArray("effect_list"); + effect_list.add("OFF"); + effect_list.add("AUTO"); + #if defined(ENABLE_TV) + effect_list.add("TV"); + #endif + #if defined(ENABLE_E131) + effect_list.add("E131"); + #endif for (uint8_t i = 0; i < strip.getModeCount(); i++) { effect_list.add(strip.getModeName(i)); } - #ifdef MQTT_HOME_ASSISTANT_SUPPORT - effect_list.add("OFF"); - #ifdef ENABLE_TV - effect_list.add("TV"); - #endif - #ifdef ENABLE_E131 - effect_list.add("E131"); - #endif - #endif char buffer[measureJson(json) + 1]; serializeJson(json, buffer, sizeof(buffer)); - DBG_OUTPUT_PORT.println(buffer); + jsonBuffer.clear(); amqttClient.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), qospub, true, buffer); #endif #endif @@ -1200,41 +1176,14 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght // *************************************************************************** // Button management // *************************************************************************** -#ifdef ENABLE_BUTTON +#if defined(ENABLE_BUTTON) void shortKeyPress() { DBG_OUTPUT_PORT.printf("Short button press\n"); - if (buttonState == false) { + if (mode == OFF) { setModeByStateString(BTN_MODE_SHORT); - buttonState = true; - #ifdef ENABLE_MQTT - mqtt_client.publish(mqtt_outtopic, String("OK =static white").c_str()); - #endif - #ifdef ENABLE_AMQTT - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =static white").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 + mode = SET_ALL; } else { mode = OFF; - 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; - 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 } } @@ -1242,45 +1191,21 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght void mediumKeyPress() { DBG_OUTPUT_PORT.printf("Medium button press\n"); 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; - 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 + mode = SET_ALL; } // called when button is kept pressed for 2 seconds or more void longKeyPress() { DBG_OUTPUT_PORT.printf("Long button press\n"); 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; - 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 + mode = SET_ALL; } void button() { if (millis() - keyPrevMillis >= keySampleIntervalMs) { keyPrevMillis = millis(); - byte currKeyState = digitalRead(BUTTON); + byte currKeyState = digitalRead(ENABLE_BUTTON); if ((prevKeyState == HIGH) && (currKeyState == LOW)) { // key goes from not pressed to pressed @@ -1307,7 +1232,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } #endif -#ifdef ENABLE_BUTTON_GY33 +#if defined(ENABLE_BUTTON_GY33) void shortKeyPress_gy33() { DBG_OUTPUT_PORT.printf("Short GY-33 button press\n"); // tcs.setConfig(MCU_LED_04, MCU_WHITE_OFF); @@ -1320,26 +1245,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght DBG_OUTPUT_PORT.printf("Colors: R: [%d] G: [%d] B: [%d] Color: [%d] Conf: [%d]\n", (int)r, (int)g, (int)b, (int)col, (int)conf); main_color.red = (pow((r/255.0), 2.5)*255); main_color.green = (pow((g/255.0), 2.5)*255); main_color.blue = (pow((b/255.0), 2.5)*255);main_color.white = 0; ws2812fx_mode = 0; - mode = SET_MODE; - buttonState = true; - #ifdef ENABLE_MQTT - mqtt_client.publish(mqtt_outtopic, String("OK =static GY-33").c_str()); - #endif - #ifdef ENABLE_AMQTT - amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =static GY-33").c_str()); - #endif - #ifdef ENABLE_HOMEASSISTANT - 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 + mode = SET_ALL; // tcs.setConfig(MCU_LED_OFF, MCU_WHITE_OFF); } // called when button is kept pressed for less than 2 seconds void mediumKeyPress_gy33() { - tcs.setConfig(MCU_LED_06, MCU_WHITE_ON); + tcs.setConfig(MCU_LED_06, MCU_WHITE_OFF); } // called when button is kept pressed for 2 seconds or more @@ -1351,7 +1263,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght if (millis() - keyPrevMillis_gy33 >= keySampleIntervalMs_gy33) { keyPrevMillis_gy33 = millis(); - byte currKeyState_gy33 = digitalRead(BUTTON_GY33); + byte currKeyState_gy33 = digitalRead(ENABLE_BUTTON_GY33); if ((prevKeyState_gy33 == HIGH) && (currKeyState_gy33 == LOW)) { // key goes from not pressed to pressed @@ -1378,165 +1290,491 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } #endif -#ifdef ENABLE_STATE_SAVE_SPIFFS -bool updateFS = false; -#if defined(ENABLE_MQTT) or defined(ENABLE_AMQTT) -// Write configuration to FS JSON -bool writeConfigFS(bool saveConfig){ - if (saveConfig) { - //FS save - updateFS = true; - DBG_OUTPUT_PORT.print("Saving config: "); - DynamicJsonDocument jsonBuffer; - JsonObject json = jsonBuffer.to(); - 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"); - - serializeJson(json, DBG_OUTPUT_PORT); - serializeJson(json, configFile); - configFile.close(); - updateFS = false; - return true; - //end save - } else { - DBG_OUTPUT_PORT.println("SaveConfig is False!"); - return false; +#if defined(ENABLE_STATE_SAVE) + void tickerSaveState(){ + updateState = true; } -} - -// 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 buf(new char[size]); - configFile.readBytes(buf.get(), size); - DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(4)+300); - DeserializationError error = deserializeJson(jsonBuffer, buf.get()); - DBG_OUTPUT_PORT.print("Config: "); - if (!error) { - DBG_OUTPUT_PORT.println(" Parsed!"); - JsonObject json = jsonBuffer.as(); - serializeJson(json, DBG_OUTPUT_PORT); - 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.print("Failed to load json config: "); - DBG_OUTPUT_PORT.println(error.c_str()); - } - } 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; -} -#endif - -bool writeStateFS(){ - updateFS = true; - //save the strip state to FS JSON - DBG_OUTPUT_PORT.print("Saving cfg: "); - DynamicJsonDocument jsonBuffer; - JsonObject json = jsonBuffer.to(); - json["mode"] = static_cast(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; - json["white"] = main_color.white; - - //SPIFFS.remove("/stripstate.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; - } - serializeJson(json, DBG_OUTPUT_PORT); - serializeJson(json, 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 buf(new char[size]); - configFile.readBytes(buf.get(), size); - DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(7)+200); - DeserializationError error = deserializeJson(jsonBuffer, buf.get()); - if (!error) { - JsonObject json = jsonBuffer.as(); - serializeJson(json, DBG_OUTPUT_PORT); - mode = static_cast((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"]; - main_color.white = json["white"]; - - strip.setMode(ws2812fx_mode); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - strip.setBrightness(brightness); - strip.setColor(main_color.red, main_color.green, main_color.blue, main_color.white); - - #ifdef ENABLE_E131 - if (mode == E131) { - strip.stop(); - } - #endif + #if ENABLE_STATE_SAVE == 1 + bool updateFS = false; + + #if defined(ENABLE_MQTT) + // Write configuration to FS JSON + bool writeConfigFS(bool saveConfig){ + if (saveConfig) { + //FS save + updateFS = true; + DBG_OUTPUT_PORT.print("Saving config: "); + const size_t bufferSize = JSON_OBJECT_SIZE(4) + 150; + DynamicJsonDocument jsonBuffer(bufferSize); + JsonObject json = jsonBuffer.to(); + json["mqtt_host"] = mqtt_host; + json["mqtt_port"] = mqtt_port; + json["mqtt_user"] = mqtt_user; + json["mqtt_pass"] = mqtt_pass; - updateFS = false; - return true; - } else { - DBG_OUTPUT_PORT.println("Failed to parse JSON!"); + //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"); + + serializeJson(json, DBG_OUTPUT_PORT); + serializeJson(json, configFile); + jsonBuffer.clear(); + configFile.close(); + updateFS = false; + return true; + //end save + } else { + DBG_OUTPUT_PORT.println("SaveConfig is False!"); + return false; + } } - } else { - DBG_OUTPUT_PORT.println("Failed to open \"/stripstate.json\""); + + // 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 buf(new char[size]); + configFile.readBytes(buf.get(), size); + const size_t bufferSize = JSON_OBJECT_SIZE(4) + 150; + DynamicJsonDocument jsonBuffer(bufferSize); + DeserializationError error = deserializeJson(jsonBuffer, buf.get()); + DBG_OUTPUT_PORT.print("Config: "); + if (!error) { + DBG_OUTPUT_PORT.println(" Parsed!"); + JsonObject json = jsonBuffer.as(); + serializeJson(json, DBG_OUTPUT_PORT); + 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; + jsonBuffer.clear(); + return true; + } else { + DBG_OUTPUT_PORT.print("Failed to load json config: "); + DBG_OUTPUT_PORT.println(error.c_str()); + jsonBuffer.clear(); + } + } 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; + } + #endif + + bool writeStateFS(){ + updateFS = true; + //save the strip state to FS JSON + DBG_OUTPUT_PORT.print("Saving cfg: "); + //SPIFFS.remove("/stripstate.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; + settings_save_state.detach(); + updateState = false; + return false; + } + DBG_OUTPUT_PORT.println(listStatusJSON()); + configFile.print(listStatusJSON()); + configFile.close(); + updateFS = false; + settings_save_state.detach(); + updateState = false; + return true; + //end save } - } else { - DBG_OUTPUT_PORT.println("Couldn't find \"/stripstate.json\""); - } - //end read - updateFS = false; - return false; -} + + 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 buf(new char[size]); + configFile.readBytes(buf.get(), size); + const size_t bufferSize = JSON_OBJECT_SIZE(5) + JSON_ARRAY_SIZE(12) + 500; + DynamicJsonDocument jsonBuffer(bufferSize); + DeserializationError error = deserializeJson(jsonBuffer, buf.get()); + if (!error) { + JsonObject json = jsonBuffer.as(); + serializeJson(json, DBG_OUTPUT_PORT); + mode = static_cast((int) json["mode"]); + ws2812fx_mode = json["ws2812fx_mode"]; + ws2812fx_speed = json["speed"]; + brightness = json["brightness"]; + main_color.white = (uint8_t) json["color"][0]; + main_color.red = (uint8_t) json["color"][1]; + main_color.green = (uint8_t) json["color"][2]; + main_color.blue = (uint8_t) json["color"][3]; + back_color.white = (uint8_t) json["color"][4]; + back_color.red = (uint8_t) json["color"][5]; + back_color.green = (uint8_t) json["color"][6]; + back_color.blue = (uint8_t) json["color"][7]; + xtra_color.white = (uint8_t) json["color"][8]; + xtra_color.red = (uint8_t) json["color"][9]; + xtra_color.green = (uint8_t) json["color"][10]; + xtra_color.blue = (uint8_t) json["color"][11]; + convertColors(); + strip.setMode(ws2812fx_mode); + strip.setSpeed(convertSpeed(ws2812fx_speed)); + strip.setBrightness(brightness); + strip.setColors(0, hex_colors); + updateFS = false; + jsonBuffer.clear(); + return true; + } else { + DBG_OUTPUT_PORT.println("Failed to parse JSON!"); + jsonBuffer.clear(); + } + } else { + DBG_OUTPUT_PORT.println("Failed to open \"/stripstate.json\""); + } + } else { + DBG_OUTPUT_PORT.println("Couldn't find \"/stripstate.json\""); + } + //end read + updateFS = false; + return false; + } + #endif + + #if ENABLE_STATE_SAVE == 0 + // *************************************************************************** + // 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; + } + + 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, 0); + } + } + } + #endif +#endif + +#if defined(ENABLE_REMOTE) +// *************************************************************************** +// Request handler for IR remote support +// *************************************************************************** +void handleRemote() { + if (irrecv.decode(&results)) { + DBG_OUTPUT_PORT.print("IR Code: 0x"); + DBG_OUTPUT_PORT.print(uint64ToString(results.value, HEX)); + DBG_OUTPUT_PORT.println(""); + if (results.value == rmt_commands[REPEATCMD]) { //Repeat + results.value = last_remote_cmd; + chng = 5; + } else { + chng = 1; + } + if (results.value == rmt_commands[ON_OFF]) { // ON/OFF TOGGLE + last_remote_cmd = 0; + if (mode == OFF) { + mode = SET_ALL; + } else { + mode = OFF; + } + } + if ((mode != AUTO) && (mode != OFF)) { + if (results.value == rmt_commands[BRIGHTNESS_UP]) { //Brightness Up + last_remote_cmd = results.value; + if (brightness + chng <= 255) { + brightness = brightness + chng; + mode = SET_BRIGHTNESS; + } + } + if (results.value == rmt_commands[BRIGHTNESS_DOWN]) { //Brightness down + last_remote_cmd = results.value; + if (brightness - chng >= 0) { + brightness = brightness - chng; + mode = SET_BRIGHTNESS; + } + } + } + if ((mode !=AUTO) && (mode != E131) && (mode != OFF)) { + if (results.value == rmt_commands[SPEED_UP]) { //Speed Up + last_remote_cmd = results.value; + if (ws2812fx_speed + chng <= 255) { + ws2812fx_speed = ws2812fx_speed + chng; + mode = SET_SPEED; + } + } + if (results.value == rmt_commands[SPEED_DOWN]) { //Speed down + last_remote_cmd = results.value; + if (ws2812fx_speed - chng >= 0) { + ws2812fx_speed = ws2812fx_speed - chng; + mode = SET_SPEED; + } + } + } + if (mode == HOLD) { + if (results.value == rmt_commands[RED_UP]) { //Red Up + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.red + chng <= 255) { + main_color.red = main_color.red + chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.red + chng <= 255) { + back_color.red = back_color.red + chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.red + chng <= 255) { + xtra_color.red = xtra_color.red + chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[RED_DOWN]) { //Red down + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.red - chng >= 0) { + main_color.red = main_color.red - chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.red - chng >= 0) { + back_color.red = back_color.red - chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.red - chng >= 0) { + xtra_color.red = xtra_color.red - chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[GREEN_UP]) { //Green Up + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.green + chng <= 255) { + main_color.green = main_color.green + chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.green + chng <= 255) { + back_color.green = back_color.green + chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.green + chng <= 255) { + xtra_color.green = xtra_color.green + chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[GREEN_DOWN]) { //green down + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.green - chng >= 0) { + main_color.green = main_color.green - chng;; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.green - chng >= 0) { + back_color.green = back_color.green - chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.green - chng >= 0) { + xtra_color.green = xtra_color.green - chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[BLUE_UP]) { //Blue Up + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.blue + chng <= 255) { + main_color.blue = main_color.blue + chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.blue + chng <= 255) { + back_color.blue = back_color.blue + chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.blue + chng <= 255) { + xtra_color.blue = xtra_color.blue + chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[BLUE_DOWN]) { //BLUE down + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.blue - chng >= 0) { + main_color.blue = main_color.blue - chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.blue - chng >= 0) { + back_color.blue = back_color.blue - chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.blue - chng >= 0) { + xtra_color.blue = xtra_color.blue - chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[WHITE_UP]) { //White Up + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.white + chng <= 255) { + main_color.white = main_color.white + chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.white + chng <= 255) { + back_color.white = back_color.white + chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.white + chng <= 255) { + xtra_color.white = xtra_color.white + chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[WHITE_DOWN]) { //White down + last_remote_cmd = results.value; + if (selected_color == 1) { + if (main_color.white - chng >= 0) { + main_color.white = main_color.white - chng; + mode = SET_COLOR; + } + } + if (selected_color == 2) { + if (back_color.white - chng >= 0) { + back_color.white = back_color.white - chng; + mode = SET_COLOR; + } + } + if (selected_color == 3) { + if (xtra_color.white - chng >= 0) { + xtra_color.white = xtra_color.white - chng; + mode = SET_COLOR; + } + } + } + if (results.value == rmt_commands[COL_M]) { // Select Main Color + last_remote_cmd = 0; + selected_color = 1; + } + if (results.value == rmt_commands[COL_B]) { // Select Back Color + last_remote_cmd = 0; + selected_color = 2; + } + if (results.value == rmt_commands[COL_X]) { // Select Extra Color + last_remote_cmd = 0; + selected_color = 3; + } + } // end of if HOLD + if (results.value == rmt_commands[MODE_UP]) { //Mode Up + last_remote_cmd = results.value; + if ((ws2812fx_mode < strip.getModeCount()-1) && (mode == HOLD)) { + ws2812fx_mode = ws2812fx_mode + 1; + } + mode = SET_MODE; + } + if (results.value == rmt_commands[MODE_DOWN]) { //Mode down + last_remote_cmd = results.value; + if ((ws2812fx_mode > 0) && (mode == HOLD)) { + ws2812fx_mode = ws2812fx_mode - 1; + } + mode = SET_MODE; + } + if (results.value == rmt_commands[AUTOMODE]) { // Toggle Automode + last_remote_cmd = 0; + if (mode != AUTO) { + mode = AUTO; + } else { + mode = SET_ALL; + } + } + #if defined(ENABLE_TV) + if (results.value == rmt_commands[CUST_1]) { // Select TV Mode + last_remote_cmd = 0; + if (mode == TV) { + mode = SET_ALL; + } else { + mode = TV; + } + } + #endif + if (results.value == rmt_commands[CUST_2]) { // Select Custom Mode 2 + last_remote_cmd = 0; + ws2812fx_mode = 12; + mode = SET_MODE; + } + if (results.value == rmt_commands[CUST_3]) { // Select Custom Mode 3 + last_remote_cmd = 0; + ws2812fx_mode = 48; + mode = SET_MODE; + } + if (results.value == rmt_commands[CUST_4]) { // Select Custom Mode 4 + last_remote_cmd = 0; + ws2812fx_mode = 21; + mode = SET_MODE; + } + if (results.value == rmt_commands[CUST_5]) { // Select Custom Mode 5 + last_remote_cmd = 0; + ws2812fx_mode = 46; + mode = SET_MODE; + } + irrecv.resume(); // Receive the next value + } + } #endif diff --git a/Arduino/McLighting/version.h b/Arduino/McLighting/version.h index 510ef45..827798a 100644 --- a/Arduino/McLighting/version.h +++ b/Arduino/McLighting/version.h @@ -1 +1 @@ -#define SKETCH_VERSION "2.2.0" \ No newline at end of file +#define SKETCH_VERSION "2.2.0.rgbw.3c" diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino index 8364126..b642a81 100644 --- a/Arduino/McLighting/version_info.ino +++ b/Arduino/McLighting/version_info.ino @@ -59,4 +59,10 @@ * 6 Jan 2018 v 2.2.0 * - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet * - HA E1.31 mode added + * + * 15 Feb 2018 v 2.2.0 rgbw 3colors + * - Code cleanup + * - Implemented support for back- and xtra-color + * - Implemented IR remote control + * - Remove some string data types (to be continued) */