diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index 0070eb5..1aa2223 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -1,5 +1,6 @@ #include "definitions.h" +#include "version.h" // *************************************************************************** // Load libraries for: WebServer / WiFiManager / WebSockets // *************************************************************************** @@ -510,17 +511,53 @@ DBG_OUTPUT_PORT.println("Starting...."); //first callback is called after the request has ended with all parsed arguments //second callback handles file uploads at that location server.on("/edit", HTTP_POST, []() { + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", ""); }, handleFileUpload); //get heap status, analog input value and all GPIO statuses in one json call server.on("/esp_status", HTTP_GET, []() { - String json = "{"; - json += "\"heap\":" + String(ESP.getFreeHeap()); - // json += ", \"analog\":" + String(analogRead(A0)); - // json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); - json += "}"; - server.send(200, "text/json", json); - json = String(); + //String json = "{"; + //json += "\"heap\":" + String(ESP.getFreeHeap()); + //// json += ", \"analog\":" + String(analogRead(A0)); + //// json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); + //json += "}"; + + DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(9)); + JsonObject& json = jsonBuffer.createObject(); + + json["HOSTNAME"] = HOSTNAME; + json["version"] = SKETCH_VERSION; + json["heap"] = ESP.getFreeHeap(); + #ifndef USE_NEOANIMATIONFX + json["animation_lib"] = "WS2812FX"; + json["pin"] = PIN; + #else + json["animation_lib"] = "NeoAnimationFX"; + json["pin"] = "Ignored, check NEOMETHOD"; + #endif + json["number_leds"] = NUMLEDS; + #ifdef ENABLE_BUTTON + json["button_mode"] = "ON"; + #else + json["button_mode"] = "OFF"; + #endif + #ifdef ENABLE_AMQTT + json["mqtt"] = "ON"; + #else + json["mqtt"] = "OFF"; + #endif + #ifdef ENABLE_HOMEASSISTANT + json["home_assistant"] = "ON"; + #else + json["home_assistant"] = "OFF"; + #endif + //char buffer[json.measureLength() + 1]; + //json.printTo(buffer, sizeof(buffer)); + String json_str; + json.printTo(json_str); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "application/json", json_str); + //json_str = String(); }); @@ -535,12 +572,14 @@ DBG_OUTPUT_PORT.println("Starting...."); server.on("/restart", []() { DBG_OUTPUT_PORT.printf("/restart\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "restarting..." ); ESP.restart(); }); server.on("/reset_wlan", []() { DBG_OUTPUT_PORT.printf("/reset_wlan\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "Resetting WLAN and restarting..." ); WiFiManager wifiManager; wifiManager.resetSettings(); @@ -549,6 +588,7 @@ DBG_OUTPUT_PORT.println("Starting...."); server.on("/start_config_ap", []() { DBG_OUTPUT_PORT.printf("/start_config_ap\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "Starting config AP ..." ); WiFiManager wifiManager; wifiManager.startConfigPortal(HOSTNAME); @@ -586,6 +626,7 @@ DBG_OUTPUT_PORT.println("Starting...."); server.on("/get_brightness", []() { String str_brightness = String((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); @@ -612,12 +653,14 @@ DBG_OUTPUT_PORT.println("Starting...."); server.on("/get_speed", []() { String str_speed = String(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); }); 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"); }); @@ -625,6 +668,7 @@ DBG_OUTPUT_PORT.println("Starting...."); server.on("/get_color", []() { char rgbcolor[9]; snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue); + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", rgbcolor ); DBG_OUTPUT_PORT.print("/get_color: "); DBG_OUTPUT_PORT.println(rgbcolor); @@ -655,6 +699,27 @@ DBG_OUTPUT_PORT.println("Starting...."); #endif }); + server.on("/auto", []() { + #ifdef ENABLE_LEGACY_ANIMATIONS + exit_func = true; + #endif + mode = OFF; + //getArgs(); + 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 + #ifdef ENABLE_STATE_SAVE_SPIFFS + if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState); + #endif + }); + server.on("/all", []() { #ifdef ENABLE_LEGACY_ANIMATIONS exit_func = true; @@ -918,6 +983,7 @@ void loop() { if (mode == SET_MODE) { DBG_OUTPUT_PORT.printf("SET_MODE: %d %d\n", ws2812fx_mode, mode); strip.setMode(ws2812fx_mode); + strip.trigger(); prevmode = SET_MODE; mode = SETCOLOR; } @@ -927,40 +993,52 @@ void loop() { } if (mode == SETCOLOR) { strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); + strip.trigger(); mode = (prevmode == SET_MODE) ? SETSPEED : HOLD; } if (mode == SETSPEED) { strip.setSpeed(convertSpeed(ws2812fx_speed)); + strip.trigger(); mode = (prevmode == SET_MODE) ? BRIGHTNESS : HOLD; } if (mode == BRIGHTNESS) { strip.setBrightness(brightness); - if (prevmode == SET_MODE) prevmode == HOLD; + strip.trigger(); + if (prevmode == SET_MODE) prevmode = HOLD; mode = HOLD; } #ifdef ENABLE_LEGACY_ANIMATIONS if (mode == WIPE) { + strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setMode(FX_MODE_COLOR_WIPE); + strip.trigger(); mode = HOLD; } if (mode == RAINBOW) { strip.setMode(FX_MODE_RAINBOW); + strip.trigger(); mode = HOLD; } if (mode == RAINBOWCYCLE) { strip.setMode(FX_MODE_RAINBOW_CYCLE); + strip.trigger(); mode = HOLD; } if (mode == THEATERCHASE) { + strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setMode(FX_MODE_THEATER_CHASE); + strip.trigger(); mode = HOLD; } if (mode == TWINKLERANDOM) { + strip.setColor(main_color.white, main_color.red, main_color.green, main_color.blue); strip.setMode(FX_MODE_TWINKLE_RANDOM); + strip.trigger(); mode = HOLD; } if (mode == THEATERCHASERAINBOW) { strip.setMode(FX_MODE_THEATER_CHASE_RAINBOW); + strip.trigger(); mode = HOLD; } #endif @@ -1007,7 +1085,7 @@ void loop() { 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 32 bytes) + writeEEPROM(256, 36, last_state); // 256 --> last_state (reserved 36 bytes) EEPROM.commit(); } #endif diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index d223c9d..bb87d28 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -17,7 +17,7 @@ const char HOSTNAME[] = "McLightingRGBW01"; // Friedly hostname //#define ENABLE_MQTT // If defined, enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API //#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active #define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control -//#define ENABLE_BUTTON_GY33 // If defined, enable button handling code for GY-33 color sensor to scan color +#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 #define ENABLE_STATE_SAVE_SPIFFS // If defined, saves state on SPIFFS @@ -37,6 +37,9 @@ const char HOSTNAME[] = "McLightingRGBW01"; // Friedly hostname #if ( (defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT)) and (defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_AMQTT)) ) #error "To use HA, you have to either enable PubCubClient or AsyncMQTT" #endif +#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) diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h index 7591f69..76c8bcf 100644 --- a/Arduino/McLighting/request_handlers.h +++ b/Arduino/McLighting/request_handlers.h @@ -231,6 +231,12 @@ void setModeByStateString(String saved_state_string) { stateOn = false; #endif } + if (str_mode.startsWith("=auto")) { + mode = AUTO; + #ifdef ENABLE_HOMEASSISTANT + stateOn = true; + #endif + } if (str_mode.startsWith("=all")) { ws2812fx_mode = FX_MODE_STATIC; mode = SET_MODE; @@ -289,35 +295,73 @@ void handleSetWS2812FXMode(uint8_t * mypayload) { ws2812fx_mode = constrain(ws2812fx_mode_tmp, 0, strip.getModeCount() - 1); } -char* listStatusJSON() { - char json[255]; - char modeName[30]; +String listStatusJSON(void) { + //char json[255]; + //char modeName[30]; uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode(); - strncpy_P(modeName, (PGM_P)strip.getModeName(tmp_mode), sizeof(modeName)); // copy from progmem - snprintf(json, sizeof(json), "{\"mode\":%d, \"ws2812fx_mode\":%d, \"ws2812fx_mode_name\":\"%s\", \"speed\":%d, \"brightness\":%d, \"color\":[%d, %d, %d, %d]}", - mode, tmp_mode, modeName, ws2812fx_speed, brightness, main_color.white, main_color.red, main_color.green, main_color.blue); + //strncpy_P(modeName, (PGM_P)strip.getModeName(tmp_mode), sizeof(modeName)); // copy from progmem + + //snprintf(json, sizeof(json), "{\"mode\":%d, \"ws2812fx_mode\":%d, \"ws2812fx_mode_name\":\"%s\", \"speed\":%d, \"brightness\":%d, \"color\":[%d, %d, %d]}", + // mode, tmp_mode, modeName, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue); + + const size_t bufferSize = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(6); + DynamicJsonBuffer jsonBuffer(bufferSize); + JsonObject& root = jsonBuffer.createObject(); + root["mode"] = (uint8_t) 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"); + color.add(main_color.white); + color.add(main_color.red); + color.add(main_color.green); + color.add(main_color.blue); + +// char* json = (char*) malloc(root.measureLength() + 1); +// root.printTo(json, sizeof(json)); + + String json; + root.printTo(json); + return json; } void getStatusJSON() { + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send ( 200, "application/json", listStatusJSON() ); } -String listModesJSON() { - String modes = "["; +String listModesJSON(void) { +// String modes = "["; +// for (uint8_t i = 0; i < strip.getModeCount(); i++) { +// modes += "{\"mode\":"; +// modes += i; +// modes += ", \"name\":\""; +// modes += strip.getModeName(i); +// modes += "\"},"; +// } +// modes += "{}]"; +// return modes; + + const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2); + DynamicJsonBuffer jsonBuffer(bufferSize); + JsonArray& json = jsonBuffer.createArray(); for (uint8_t i = 0; i < strip.getModeCount(); i++) { - modes += "{\"mode\":"; - modes += i; - modes += ", \"name\":\""; - modes += strip.getModeName(i); - modes += "\"},"; + JsonObject& object = json.createNestedObject(); + object["mode"] = i; + object["name"] = strip.getModeName(i); } - modes += "{}]"; - return modes; + JsonObject& object = json.createNestedObject(); + + String json_str; + json.printTo(json_str); + return json_str; } void getModesJSON() { + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send ( 200, "application/json", listModesJSON() ); } @@ -344,7 +388,8 @@ void handleMinimalUpload() { \ \ " - ); + ); + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send ( 200, "text/html", temp ); } @@ -445,7 +490,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { brightness = constrain(b, 0, 255); strip.setBrightness(brightness); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("WS: Set brightness to: [%u]\n", brightness); + 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 diff --git a/Arduino/McLighting/spiffs_webserver.h b/Arduino/McLighting/spiffs_webserver.h index a02fc6a..0c9c5c7 100644 --- a/Arduino/McLighting/spiffs_webserver.h +++ b/Arduino/McLighting/spiffs_webserver.h @@ -69,6 +69,7 @@ bool handleFileRead(String path) { if (SPIFFS.exists(pathWithGz)) path += ".gz"; File file = SPIFFS.open(path, "r"); + server.sendHeader("Access-Control-Allow-Origin", "*"); size_t sent = server.streamFile(file, contentType); file.close(); return true; @@ -153,5 +154,6 @@ void handleFileList() { } output += "]"; + server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/json", output); } diff --git a/Arduino/McLighting/version.h b/Arduino/McLighting/version.h new file mode 100644 index 0000000..db35e16 --- /dev/null +++ b/Arduino/McLighting/version.h @@ -0,0 +1 @@ +#define SKETCH_VERSION "2.1.1" diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino new file mode 100644 index 0000000..f381e99 --- /dev/null +++ b/Arduino/McLighting/version_info.ino @@ -0,0 +1,9 @@ +/* + * 07 May 2018 v 2.1.0 + * - Start of versioning v2.1, added version support + * - '/esp_status' returns lot more info + * + * 11 May 2018 v 2.1.1 + * - Use ArduinoJSON to send JSON replies + * - Add strip.trigger() + */