From e64b3991b8f9fcaa23652eb68202b85504f3bc9b Mon Sep 17 00:00:00 2001 From: Tobias Blum Date: Sun, 21 Jan 2018 00:10:20 +0100 Subject: [PATCH] Adapt pull request to McLighting --- Arduino/McLighting/McLighting.ino | 38 +-- Arduino/McLighting/definitions.h | 54 ++-- Arduino/McLighting/request_handlers.h | 427 +++++++++++++------------- 3 files changed, 257 insertions(+), 262 deletions(-) diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index 2912ec2..7c32587 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -60,16 +60,7 @@ WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800); // and minimize distance between Arduino and first pixel. Avoid connecting // on a live circuit...if you must, connect GND first. -/// Button //// -#ifdef ENABLE_BUTTON - unsigned long keyPrevMillis = 0; - const unsigned long keySampleIntervalMs = 25; - byte longKeyPressCountMax = 80; // 80 * 25 = 2000 ms - byte mediumKeyPressCountMin = 20; // 20 * 25 = 500 ms - byte KeyPressCount = 0; - byte prevKeyState = HIGH; // button is active low - boolean buttonState = false; -#endif + // *************************************************************************** // Load library "ticker" for blinking status led // *************************************************************************** @@ -584,32 +575,7 @@ void setup() { String chk = getValue(saved_state_string, '|', 0); if (chk == "STA") { DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str()); - String str_mode = getValue(saved_state_string, '|', 1); - mode = static_cast(str_mode.toInt()); - String str_ws2812fx_mode = getValue(saved_state_string, '|', 2); - ws2812fx_mode = str_ws2812fx_mode.toInt(); - String str_ws2812fx_speed = getValue(saved_state_string, '|', 3); - ws2812fx_speed = str_ws2812fx_speed.toInt(); - String str_brightness = getValue(saved_state_string, '|', 4); - brightness = str_brightness.toInt(); - String str_red = getValue(saved_state_string, '|', 5); - main_color.red = str_red.toInt(); - String str_green = getValue(saved_state_string, '|', 6); - main_color.green = str_green.toInt(); - String str_blue = getValue(saved_state_string, '|', 7); - main_color.blue = str_blue.toInt(); - - 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); - - strip.setMode(ws2812fx_mode); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - strip.setBrightness(brightness); - strip.setColor(main_color.red, main_color.green, main_color.blue); + setModeByStateString(saved_state_string); } sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d", mode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue); #endif diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index 5627523..ba06789 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -1,36 +1,33 @@ // Neopixel -#define PIN D2 // PIN where neopixel / WS2811 strip is attached -#define NUMLEDS 68 // 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 D1 // Input pin for switching the LED strip on / off +#define PIN D1 // PIN where neopixel / WS2811 strip is attached +#define NUMLEDS 7 // 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 D2 // Input pin for switching the LED strip on / off, connect this PIN to ground to trigger button. -const char HOSTNAME[] = "McLighting"; // Friedly hostname +const char HOSTNAME[] = "ESP8266_VORONOI"; // Friedly hostname #define ENABLE_OTA // If defined, enable Arduino OTA code. - #define ENABLE_MQTT // If defined, enable MQTT client code. - #define ENABLE_BUTTON // If defined, enable button handling code. // parameters for automatically cycling favorite patterns uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds) - {0xff0000, 200, 1, 5.0}, // blink red for 5 seconds - {0x00ff00, 200, 3, 10.0}, // wipe green for 10 seconds - {0x0000ff, 200, 11, 5.0}, // dual scan blue for 5 seconds - {0x0000ff, 200, 42, 15.0} // fireworks for 15 seconds + {0xff0000, 200, 1, 5.0}, // blink red for 5 seconds + {0x00ff00, 200, 3, 10.0}, // wipe green for 10 seconds + {0x0000ff, 200, 11, 5.0}, // dual scan blue for 5 seconds + {0x0000ff, 200, 42, 15.0} // fireworks for 15 seconds }; #ifdef ENABLE_MQTT #define MQTT_MAX_PACKET_SIZE 256 #define MQTT_MAX_RECONNECT_TRIES 4 - - int mqtt_reconnect_retries = 0; + int mqtt_reconnect_retries = 0; char mqtt_intopic[strlen(HOSTNAME) + 4]; // Topic in will be: /in char mqtt_outtopic[strlen(HOSTNAME) + 5]; // Topic out will be: /out - const char mqtt_clientid[] = "McLighting"; // MQTT ClientID - + const char mqtt_clientid[] = "McLighting"; // MQTT ClientID + char mqtt_host[64] = ""; char mqtt_port[6] = ""; char mqtt_user[32] = ""; @@ -49,24 +46,24 @@ enum MODE { SET_MODE, HOLD, OFF, ALL, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, MODE mode = RAINBOW; // Standard mode that is active when software starts int ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster -int brightness = 255; // Global variable for storing the brightness (255 == 100%) +int brightness = 196; // Global variable for storing the brightness (255 == 100%) int ws2812fx_mode = 0; // Helper variable to set WS2812FX modes bool exit_func = false; // Global helper variable to get out of the color modes when mode changes -bool shouldSaveConfig = true; // For WiFiManger custom config +bool shouldSaveConfig = false; // For WiFiManger custom config struct ledstate // Data structure to store a state of a single led { - uint8_t red; - uint8_t green; - uint8_t blue; + uint8_t red; + uint8_t green; + uint8_t blue; }; typedef struct ledstate LEDState; // Define the datatype LEDState LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip -LEDState main_color = { 255, 0, 0 }; // Store the "main color" of the strip used in single color modes +LEDState main_color = { 255, 0, 0 }; // Store the "main color" of the strip used in single color modes #define ENABLE_STATE_SAVE // If defined, save state on reboot #ifdef ENABLE_STATE_SAVE @@ -75,4 +72,19 @@ LEDState main_color = { 255, 0, 0 }; // Store the "main color" of the strip use 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 + +// Button handling +#ifdef ENABLE_BUTTON + #define BTN_MODE_SHORT "STA| 1| 0|245|196|255|255|255" // Static white + #define BTN_MODE_MEDIUM "STA| 1| 48|245|196|255|102| 0" // Fire flicker + #define BTN_MODE_LONG "STA| 1| 46|253|196|255|102| 0" // Fireworks random + + unsigned long keyPrevMillis = 0; + const unsigned long keySampleIntervalMs = 25; + byte longKeyPressCountMax = 80; // 80 * 25 = 2000 ms + byte mediumKeyPressCountMin = 20; // 20 * 25 = 500 ms + byte KeyPressCount = 0; + byte prevKeyState = HIGH; // button is active low + boolean buttonState = false; #endif diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h index d5826bc..28fe288 100644 --- a/Arduino/McLighting/request_handlers.h +++ b/Arduino/McLighting/request_handlers.h @@ -2,8 +2,6 @@ // Request handlers // *************************************************************************** - -//////////////////////////// void getArgs() { if (server.arg("rgb") != "") { uint32_t rgb = (uint32_t) strtol(server.arg("rgb").c_str(), NULL, 16); @@ -21,7 +19,7 @@ void getArgs() { } if (server.arg("m") != "") { - ws2812fx_mode = constrain(server.arg("m").toInt(), 0, strip.getModeCount()-1); + ws2812fx_mode = constrain(server.arg("m").toInt(), 0, strip.getModeCount() - 1); } main_color.red = constrain(main_color.red, 0, 255); @@ -92,13 +90,13 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { uint8_t led = atoi(templed); DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\n", led, strip.numPixels(), mypayload ); - if (led <= strip.numPixels()) { + if (led <= strip.numPixels()) { char redhex[3]; char greenhex[3]; char bluehex[3]; - strncpy (redhex, (const char *) &mypayload[2+firstChar], 2 ); - strncpy (greenhex, (const char *) &mypayload[4+firstChar], 2 ); - strncpy (bluehex, (const char *) &mypayload[6+firstChar], 2 ); + strncpy (redhex, (const char *) &mypayload[2 + firstChar], 2 ); + strncpy (greenhex, (const char *) &mypayload[4 + firstChar], 2 ); + strncpy (bluehex, (const char *) &mypayload[6 + firstChar], 2 ); ledstates[led].red = strtol(redhex, NULL, 16); ledstates[led].green = strtol(greenhex, NULL, 16); ledstates[led].blue = strtol(bluehex, NULL, 16); @@ -106,7 +104,7 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i]\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16)); DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] (%s)!\n", led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, mypayload); - + strip.setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue); strip.show(); } @@ -129,37 +127,66 @@ void handleRangeDifferentColors(uint8_t * mypayload) { //While there is a range to process R0110<00ff00> while (nextCommand) { - //Loop for each LED. - char startled[3] = { 0,0,0 }; - char endled[3] = { 0,0,0 }; - char colorval[7] = { 0,0,0,0,0,0,0 }; - strncpy ( startled, (const char *) &nextCommand[0], 2 ); - strncpy ( endled, (const char *) &nextCommand[2], 2 ); - strncpy ( colorval, (const char *) &nextCommand[4], 6 ); - int rangebegin = atoi(startled); - int rangeend = atoi(endled); - DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s] \n", rangebegin, rangeend, colorval); + //Loop for each LED. + char startled[3] = { 0, 0, 0 }; + char endled[3] = { 0, 0, 0 }; + char colorval[7] = { 0, 0, 0, 0, 0, 0, 0 }; + strncpy ( startled, (const char *) &nextCommand[0], 2 ); + strncpy ( endled, (const char *) &nextCommand[2], 2 ); + strncpy ( colorval, (const char *) &nextCommand[4], 6 ); + int rangebegin = atoi(startled); + int rangeend = atoi(endled); + DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s] \n", rangebegin, rangeend, colorval); - while ( rangebegin <= rangeend ) { - char rangeData[9] = { 0,0,0,0,0,0,0,0,0 }; - if ( rangebegin < 10 ) { - //Create the valid 'nextCommand' structure - sprintf(rangeData, "0%d%s", rangebegin, colorval); - } - if ( rangebegin >= 10 ) { - //Create the valid 'nextCommand' structure - sprintf(rangeData, "%d%s", rangebegin, colorval); - } - //Set one LED - handleSetSingleLED((uint8_t*) rangeData, 0); - rangebegin++; + while ( rangebegin <= rangeend ) { + char rangeData[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + if ( rangebegin < 10 ) { + //Create the valid 'nextCommand' structure + sprintf(rangeData, "0%d%s", rangebegin, colorval); } + if ( rangebegin >= 10 ) { + //Create the valid 'nextCommand' structure + sprintf(rangeData, "%d%s", rangebegin, colorval); + } + //Set one LED + handleSetSingleLED((uint8_t*) rangeData, 0); + rangebegin++; + } - //Next Range at R - nextCommand = (uint8_t*) strtok(NULL, "R"); + //Next Range at R + nextCommand = (uint8_t*) strtok(NULL, "R"); } } +void setModeByStateString(String saved_state_string) { + String str_mode = getValue(saved_state_string, '|', 1); + mode = static_cast(str_mode.toInt()); + String str_ws2812fx_mode = getValue(saved_state_string, '|', 2); + ws2812fx_mode = str_ws2812fx_mode.toInt(); + String str_ws2812fx_speed = getValue(saved_state_string, '|', 3); + ws2812fx_speed = str_ws2812fx_speed.toInt(); + String str_brightness = getValue(saved_state_string, '|', 4); + brightness = str_brightness.toInt(); + String str_red = getValue(saved_state_string, '|', 5); + main_color.red = str_red.toInt(); + String str_green = getValue(saved_state_string, '|', 6); + main_color.green = str_green.toInt(); + String str_blue = getValue(saved_state_string, '|', 7); + main_color.blue = str_blue.toInt(); + + 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); + + strip.setMode(ws2812fx_mode); + strip.setSpeed(convertSpeed(ws2812fx_speed)); + strip.setBrightness(brightness); + strip.setColor(main_color.red, main_color.green, main_color.blue); +} + void handleSetNamedMode(String str_mode) { exit_func = true; @@ -208,7 +235,7 @@ char* listStatusJSON() { strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), 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, strip.getMode(), modeName, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue); + mode, strip.getMode(), modeName, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue); return json; } @@ -218,7 +245,7 @@ void getStatusJSON() { String listModesJSON() { String modes = "["; - for(uint8_t i=0; i < strip.getModeCount(); i++) { + for (uint8_t i = 0; i < strip.getModeCount(); i++) { modes += "{\"mode\":"; modes += i; modes += ", \"name\":\""; @@ -241,7 +268,7 @@ void handleMinimalUpload() { char temp[1500]; snprintf ( temp, 1500, - "\ + "\ \ \ ESP8266 Upload\ @@ -257,7 +284,7 @@ void handleMinimalUpload() { \ \ " - ); + ); server.send ( 200, "text/html", temp ); } @@ -289,11 +316,11 @@ void autoTick() { DBG_OUTPUT_PORT.println(autoCount); autoCount++; - if(autoCount >= (sizeof(autoParams) / sizeof(autoParams[0]))) autoCount=0; + if (autoCount >= (sizeof(autoParams) / sizeof(autoParams[0]))) autoCount = 0; } void handleAutoStart() { - autoCount=0; + autoCount = 0; autoTick(); strip.start(); } @@ -433,143 +460,143 @@ void checkForRequests() { // MQTT callback / connection handler // *************************************************************************** #ifdef ENABLE_MQTT - void mqtt_callback(char* topic, byte* payload_in, unsigned int length) { - uint8_t * payload = (uint8_t *)malloc(length + 1); - memcpy(payload, payload_in, length); - payload[length] = NULL; - DBG_OUTPUT_PORT.printf("MQTT: Message arrived [%s]\n", payload); +void mqtt_callback(char* topic, byte* payload_in, unsigned int length) { + uint8_t * payload = (uint8_t *)malloc(length + 1); + memcpy(payload, payload_in, length); + payload[length] = NULL; + DBG_OUTPUT_PORT.printf("MQTT: Message arrived [%s]\n", payload); - // # ==> Set main color - if (payload[0] == '#') { - handleSetMainColor(payload); - DBG_OUTPUT_PORT.printf("MQTT: Set main color to [%u] [%u] [%u]\n", main_color.red, main_color.green, main_color.blue); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // ? ==> Set speed - if (payload[0] == '?') { - uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10); - ws2812fx_speed = constrain(d, 0, 255); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - DBG_OUTPUT_PORT.printf("MQTT: Set speed to [%u]\n", ws2812fx_speed); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // % ==> Set brightness - if (payload[0] == '%') { - uint8_t b = (uint8_t) strtol((const char *) &payload[1], NULL, 10); - brightness = constrain(b, 0, 255); - strip.setBrightness(brightness); - DBG_OUTPUT_PORT.printf("MQTT: Set brightness to [%u]\n", brightness); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // * ==> Set main color and light all LEDs (Shortcut) - if (payload[0] == '*') { - handleSetAllMode(payload); - DBG_OUTPUT_PORT.printf("MQTT: Set main color and light all LEDs [%s]\n", payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // ! ==> Set single LED in given color - if (payload[0] == '!') { - handleSetSingleLED(payload, 1); - DBG_OUTPUT_PORT.printf("MQTT: Set single LED in given color [%s]\n", payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // + ==> Set multiple LED in the given colors - if (payload[0] == '+') { - handleSetDifferentColors(payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // R ==> Set range of LEDs in the given colors - if (payload[0] == 'R') { - handleRangeDifferentColors(payload); - DBG_OUTPUT_PORT.printf("MQTT: Set range of LEDS to single color: [%s]\n", payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // = ==> Activate named mode - if (payload[0] == '=') { - String str_mode = String((char *) &payload[0]); - handleSetNamedMode(str_mode); - DBG_OUTPUT_PORT.printf("MQTT: Activate named mode [%s]\n", payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - // $ ==> Get status Info. - if (payload[0] == '$') { - DBG_OUTPUT_PORT.printf("MQTT: Get status info.\n"); - mqtt_client.publish(mqtt_outtopic, listStatusJSON()); - } - - // ~ ==> Get WS2812 modes. - // TODO: Fix this, doesn't return anything. Too long? - // Hint: https://github.com/knolleary/pubsubclient/issues/110 - if (payload[0] == '~') { - DBG_OUTPUT_PORT.printf("MQTT: Get WS2812 modes.\n"); - 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()); - } - - // / ==> Set WS2812 mode. - if (payload[0] == '/') { - handleSetWS2812FXMode(payload); - DBG_OUTPUT_PORT.printf("MQTT: Set WS2812 mode [%s]\n", payload); - mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); - } - - free(payload); + // # ==> Set main color + if (payload[0] == '#') { + handleSetMainColor(payload); + DBG_OUTPUT_PORT.printf("MQTT: Set main color to [%u] [%u] [%u]\n", main_color.red, main_color.green, main_color.blue); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); } - void mqtt_reconnect() { - // Loop until we're reconnected - while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { - mqtt_reconnect_retries++; - DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES); - // Attempt to connect - if (mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_pass)) { - DBG_OUTPUT_PORT.println("MQTT connected!"); - // Once connected, publish an announcement... - char * message = new char[18 + strlen(HOSTNAME) + 1]; - strcpy(message, "McLighting ready: "); - strcat(message, HOSTNAME); - mqtt_client.publish(mqtt_outtopic, message); - // ... and resubscribe - mqtt_client.subscribe(mqtt_intopic); + // ? ==> Set speed + if (payload[0] == '?') { + uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10); + ws2812fx_speed = constrain(d, 0, 255); + strip.setSpeed(convertSpeed(ws2812fx_speed)); + DBG_OUTPUT_PORT.printf("MQTT: Set speed to [%u]\n", ws2812fx_speed); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } - DBG_OUTPUT_PORT.printf("MQTT topic in: %s\n", mqtt_intopic); - DBG_OUTPUT_PORT.printf("MQTT topic out: %s\n", mqtt_outtopic); - } else { - DBG_OUTPUT_PORT.print("failed, rc="); - DBG_OUTPUT_PORT.print(mqtt_client.state()); - DBG_OUTPUT_PORT.println(" try again in 5 seconds"); - // Wait 5 seconds before retrying - delay(5000); - } - } - if (mqtt_reconnect_retries >= MQTT_MAX_RECONNECT_TRIES) { - DBG_OUTPUT_PORT.printf("MQTT connection failed, giving up after %d tries ...\n", mqtt_reconnect_retries); + // % ==> Set brightness + if (payload[0] == '%') { + uint8_t b = (uint8_t) strtol((const char *) &payload[1], NULL, 10); + brightness = constrain(b, 0, 255); + strip.setBrightness(brightness); + DBG_OUTPUT_PORT.printf("MQTT: Set brightness to [%u]\n", brightness); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // * ==> Set main color and light all LEDs (Shortcut) + if (payload[0] == '*') { + handleSetAllMode(payload); + DBG_OUTPUT_PORT.printf("MQTT: Set main color and light all LEDs [%s]\n", payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // ! ==> Set single LED in given color + if (payload[0] == '!') { + handleSetSingleLED(payload, 1); + DBG_OUTPUT_PORT.printf("MQTT: Set single LED in given color [%s]\n", payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // + ==> Set multiple LED in the given colors + if (payload[0] == '+') { + handleSetDifferentColors(payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // R ==> Set range of LEDs in the given colors + if (payload[0] == 'R') { + handleRangeDifferentColors(payload); + DBG_OUTPUT_PORT.printf("MQTT: Set range of LEDS to single color: [%s]\n", payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // = ==> Activate named mode + if (payload[0] == '=') { + String str_mode = String((char *) &payload[0]); + handleSetNamedMode(str_mode); + DBG_OUTPUT_PORT.printf("MQTT: Activate named mode [%s]\n", payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + // $ ==> Get status Info. + if (payload[0] == '$') { + DBG_OUTPUT_PORT.printf("MQTT: Get status info.\n"); + mqtt_client.publish(mqtt_outtopic, listStatusJSON()); + } + + // ~ ==> Get WS2812 modes. + // TODO: Fix this, doesn't return anything. Too long? + // Hint: https://github.com/knolleary/pubsubclient/issues/110 + if (payload[0] == '~') { + DBG_OUTPUT_PORT.printf("MQTT: Get WS2812 modes.\n"); + 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()); + } + + // / ==> Set WS2812 mode. + if (payload[0] == '/') { + handleSetWS2812FXMode(payload); + DBG_OUTPUT_PORT.printf("MQTT: Set WS2812 mode [%s]\n", payload); + mqtt_client.publish(mqtt_outtopic, String(String("OK ") + String((char *)payload)).c_str()); + } + + free(payload); +} + +void mqtt_reconnect() { + // Loop until we're reconnected + while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { + mqtt_reconnect_retries++; + DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES); + // Attempt to connect + if (mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_pass)) { + DBG_OUTPUT_PORT.println("MQTT connected!"); + // Once connected, publish an announcement... + char * message = new char[18 + strlen(HOSTNAME) + 1]; + strcpy(message, "McLighting ready: "); + strcat(message, HOSTNAME); + mqtt_client.publish(mqtt_outtopic, message); + // ... and resubscribe + mqtt_client.subscribe(mqtt_intopic); + + DBG_OUTPUT_PORT.printf("MQTT topic in: %s\n", mqtt_intopic); + DBG_OUTPUT_PORT.printf("MQTT topic out: %s\n", mqtt_outtopic); + } else { + DBG_OUTPUT_PORT.print("failed, rc="); + DBG_OUTPUT_PORT.print(mqtt_client.state()); + DBG_OUTPUT_PORT.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); } } + if (mqtt_reconnect_retries >= MQTT_MAX_RECONNECT_TRIES) { + DBG_OUTPUT_PORT.printf("MQTT connection failed, giving up after %d tries ...\n", mqtt_reconnect_retries); + } +} #endif -/// Button management ///// + +// *************************************************************************** +// Button management +// *************************************************************************** #ifdef ENABLE_BUTTON void shortKeyPress() { + DBG_OUTPUT_PORT.printf("Short button press\n"); if (buttonState == false) { - main_color.red = 255; - main_color.green = 255; - main_color.blue = 255; - strip.setColor(main_color.red, main_color.green, main_color.blue); - mode = HOLD; + setModeByStateString(BTN_MODE_SHORT); buttonState = true; } else { mode = OFF; @@ -577,55 +604,45 @@ void shortKeyPress() { } } - -// called when button is kept pressed for more than 2 seconds +// called when button is kept pressed for less than 2 seconds void mediumKeyPress() { - mode = TWINKLERANDOM; + DBG_OUTPUT_PORT.printf("Medium button press\n"); + setModeByStateString(BTN_MODE_MEDIUM); } // called when button is kept pressed for 2 seconds or more void longKeyPress() { - //Serial.println("hosszu lenyomas"); -} - -// called when key goes from not pressed to pressed -void keyPress() { - KeyPressCount = 0; -} - - -// called when key goes from pressed to not pressed -void keyRelease() { - - if (KeyPressCount < longKeyPressCountMax && KeyPressCount >= mediumKeyPressCountMin) { - mediumKeyPress(); - } - else { - if (KeyPressCount < mediumKeyPressCountMin) { - shortKeyPress(); - } - } + DBG_OUTPUT_PORT.printf("Long button press\n"); + setModeByStateString(BTN_MODE_LONG); } void button() { if (millis() - keyPrevMillis >= keySampleIntervalMs) { - keyPrevMillis = millis(); - - byte currKeyState = digitalRead(BUTTON); - - if ((prevKeyState == HIGH) && (currKeyState == LOW)) { - keyPress(); - } - else if ((prevKeyState == LOW) && (currKeyState == HIGH)) { - keyRelease(); - } - else if (currKeyState == LOW) { - KeyPressCount++; - if (KeyPressCount >= longKeyPressCountMax) { - longKeyPress(); - } - } - prevKeyState = currKeyState; + keyPrevMillis = millis(); + + byte currKeyState = digitalRead(BUTTON); + + if ((prevKeyState == HIGH) && (currKeyState == LOW)) { + // key goes from not pressed to pressed + KeyPressCount = 0; } + else if ((prevKeyState == LOW) && (currKeyState == HIGH)) { + if (KeyPressCount < longKeyPressCountMax && KeyPressCount >= mediumKeyPressCountMin) { + mediumKeyPress(); + } + else { + if (KeyPressCount < mediumKeyPressCountMin) { + shortKeyPress(); + } + } + } + else if (currKeyState == LOW) { + KeyPressCount++; + if (KeyPressCount >= longKeyPressCountMax) { + longKeyPress(); + } + } + prevKeyState = currKeyState; + } } #endif