From 341c469b49f7856c3567d4c9576c9e48ab7bd4aa Mon Sep 17 00:00:00 2001 From: bpohvoodoo Date: Sun, 29 Sep 2019 13:27:37 +0200 Subject: [PATCH] V3.0.0.BETA1 * Version Bump to 3.0.0.BETA1 * further code changes * bugfixes --- .gitmodules | 6 - Arduino/McLighting/McLighting.ino | 82 +-- Arduino/McLighting/definitions.h | 15 +- .../mode_custom_ws2812fx_animations.h | 1 - Arduino/McLighting/request_handlers.h | 432 ++++++++------- Arduino/McLighting/version_info.ino | 5 +- clients/HomeAssistant/light.yaml | 7 +- clients/homebridge/config.json | 4 +- clients/newWebClient/favicon.ico | Bin 1150 -> 0 bytes clients/newWebClient/index.htm.gz | Bin 19973 -> 0 bytes clients/web(RGBW)/README.md | 4 - clients/web(RGBW)/build/index.htm | 491 ------------------ clients/web(RGBW)/gulpfile.js | 55 -- clients/web(RGBW)/package.json | 18 - clients/web(RGBW)/src/index.htm | 159 ------ clients/web(RGBW)/src/js/script.js | 331 ------------ clients/web/README.md | 4 - clients/web/apple-touch-icon.png | Bin 0 -> 4500 bytes clients/web/build/index.htm | 466 ----------------- clients/{newWebClient => web}/edit.htm | 0 clients/{newWebClient => web}/edit.htm.gz | Bin clients/web/favicon.ico | Bin 0 -> 34494 bytes clients/web/graphs.js.gz | Bin 0 -> 1971 bytes clients/web/gulpfile.js | 55 -- clients/{newWebClient => web}/index.htm | 187 +++---- clients/web/index.htm.gz | Bin 0 -> 19755 bytes clients/web/package.json | 18 - clients/web/src/index.htm | 162 ------ clients/web/src/js/script.js | 305 ----------- 29 files changed, 339 insertions(+), 2468 deletions(-) delete mode 100644 .gitmodules delete mode 100644 clients/newWebClient/favicon.ico delete mode 100644 clients/newWebClient/index.htm.gz delete mode 100644 clients/web(RGBW)/README.md delete mode 100644 clients/web(RGBW)/build/index.htm delete mode 100644 clients/web(RGBW)/gulpfile.js delete mode 100644 clients/web(RGBW)/package.json delete mode 100644 clients/web(RGBW)/src/index.htm delete mode 100644 clients/web(RGBW)/src/js/script.js delete mode 100644 clients/web/README.md create mode 100644 clients/web/apple-touch-icon.png delete mode 100644 clients/web/build/index.htm rename clients/{newWebClient => web}/edit.htm (100%) rename clients/{newWebClient => web}/edit.htm.gz (100%) create mode 100644 clients/web/favicon.ico create mode 100644 clients/web/graphs.js.gz delete mode 100644 clients/web/gulpfile.js rename clients/{newWebClient => web}/index.htm (93%) create mode 100644 clients/web/index.htm.gz delete mode 100644 clients/web/package.json delete mode 100644 clients/web/src/index.htm delete mode 100644 clients/web/src/js/script.js diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e764857..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "Arduino/McLighting/data/McLightingUI"] - path = Arduino/McLighting/data/McLightingUI - url = https://github.com/toblum/McLightingUI -[submodule "clients/web/McLightingUI"] - path = clients/web/McLightingUI - url = https://github.com/toblum/McLightingUI diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index 8a962cb..13e245e 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -671,8 +671,6 @@ void setup() { #if defined(ENABLE_REMOTE) irrecv.enableIRIn(); // Start the receiver #endif - snprintf(last_state, sizeof(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); - last_state[sizeof(last_state)]= 0x00; ws2812fx_speed_actual = ws2812fx_speed; brightness_trans = brightness; memcpy(hex_colors, hex_colors_trans, sizeof(hex_colors_trans)); @@ -777,48 +775,43 @@ void loop() { if (mode == SET) { mode = HOLD; + // Mode if (ws2812fx_mode != strip->getMode(selected_segment)) { // SET_MODE - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", ws2812fx_mode); - #endif + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", ws2812fx_mode); + #endif strip->strip_off(); autoCount = 0; autoDelay = 0; strip->setMode(selected_segment, ws2812fx_mode); } + //Color + /*if (memcmp(hex_colors_trans, strip->getColors(selected_segment), sizeof(hex_colors_trans)) != 0) { + + }*/ + // Brightness if (strip->getBrightness() != brightness) { #if defined(ENABLE_MQTT) snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %%%i", brightness); #endif brightness_trans = brightness; } + // Speed + if (ws2812fx_speed_actual != ws2812fx_speed) { + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", ws2812fx_speed); + #endif + } prevmode = SET; strip->trigger(); } - - /*if (mode == SET) { - mode = HOLD; - if (trans_cnt==0) { trans_cnt=1; } - if (!transEffect) { trans_cnt=255; } - convertColorsFade(); - prevmode = SET; - }*/ - - if (mode == SET_SPEED) { - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", ws2812fx_speed); - #endif - mode = prevmode; - prevmode = SET_SPEED; - } if (prevmode != mode) { convertColors(); if (memcmp(hex_colors_trans, strip->getColors(selected_segment), sizeof(hex_colors_trans)) != 0) { DBG_OUTPUT_PORT.println("Colors not equal!"); - if (trans_cnt==0) { trans_cnt=1; } - if (!transEffect) { trans_cnt=255; } convertColorsFade(); + trans_cnt = 1; } strip->setSpeed(selected_segment, convertSpeed(ws2812fx_speed_actual)); //strip->setBrightness(brightness_actual); @@ -873,7 +866,7 @@ void loop() { } #endif - if ((mode == HOLD) || ((mode == OFF) && ((strip->getBrightness() == 0) || !transEffect))) { + if ((mode == HOLD) || ((mode == OFF) && (strip->getBrightness() > 0) && transEffect)) { if (ws2812fx_mode == FX_MODE_CUSTOM_0) { handleAutoPlay(); } @@ -882,26 +875,33 @@ void loop() { } // Async color transition - if ((trans_cnt > 0) && (trans_cnt < 255)) { - uint32_t hex_colors_actual[3] = {}; - if ((transEffect) && (colorFadeDelay <= millis())) { - hex_colors_actual[0] = trans(hex_colors_trans[0], hex_colors[0], trans_cnt); - hex_colors_actual[1] = trans(hex_colors_trans[1], hex_colors[1], trans_cnt); - hex_colors_actual[2] = trans(hex_colors_trans[2], hex_colors[2], trans_cnt); - strip->setColors(selected_segment, hex_colors_actual); - trans_cnt++; - colorFadeDelay = millis() + TRANS_COLOR_DELAY; + if (memcmp(hex_colors_trans, strip->getColors(selected_segment), sizeof(hex_colors_trans)) != 0) { + if (transEffect) { + if ((trans_cnt > 0) && (trans_cnt < trans_cnt_max)) { + if (colorFadeDelay <= millis()) { + uint32_t hex_colors_actual[3] = {}; + hex_colors_actual[0] = trans(hex_colors_trans[0], hex_colors[0], trans_cnt); + hex_colors_actual[1] = trans(hex_colors_trans[1], hex_colors[1], trans_cnt); + hex_colors_actual[2] = trans(hex_colors_trans[2], hex_colors[2], trans_cnt); + strip->setColors(selected_segment, hex_colors_actual); + trans_cnt++; + colorFadeDelay = millis() + TRANS_COLOR_DELAY; + if (mode == HOLD) strip->trigger(); + } + } else if (trans_cnt >= trans_cnt_max) { + memcpy(hex_colors, hex_colors_trans, sizeof(hex_colors_trans)); + strip->setColors(selected_segment, hex_colors); + if (mode == HOLD) strip->trigger(); + trans_cnt = 0; + DBG_OUTPUT_PORT.println("Color transition finished!"); + } + } else { + memcpy(hex_colors, hex_colors_trans, sizeof(hex_colors_trans)); + strip->setColors(selected_segment, hex_colors); if (mode == HOLD) strip->trigger(); + trans_cnt = 0; } } - if (trans_cnt > 254) { - memcpy(hex_colors, hex_colors_trans, sizeof(hex_colors_trans)); - strip->setColors(selected_segment, hex_colors); - if (mode == HOLD) strip->trigger(); - trans_cnt = 0; - DBG_OUTPUT_PORT.println("Color transition finished!"); - } - // Async speed transition if (ws2812fx_speed_actual != ws2812fx_speed) { if (transEffect) { diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index 6ef1856..9ad718a 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -21,11 +21,11 @@ char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just #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_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. #if defined(ENABLE_BUTTON_GY33) #define GAMMA 2.5 // Gamma correction for GY-33 sensor #endif -//#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out +#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out #define ENABLE_STATE_SAVE 1 // If defined, load saved state on reboot and save state. If set to 0 from EEPROM, if set to 1 from SPIFFS @@ -35,12 +35,13 @@ char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just #define TRANS_COLOR_DELAY 5 // Delay for color transition #define TRANS_DELAY 10 // Delay for brightness and speed transition -bool transEffect = false; // Experimental: Enable transitions of color, brightness and speed. It does not work properly for all effects. +bool transEffect = false; // Experimental: Enable transitions of color, brightness and speed. It does not work properly for all effects. bool transEffectOverride = false; -uint8_t trans_cnt = 0; -unsigned long colorFadeDelay = 0; +uint8_t trans_cnt = 0; +int trans_cnt_max = 0; +unsigned long colorFadeDelay = 0; unsigned long brightnessFadeDelay = 0; -unsigned long speedFadeDelay = 0; +unsigned long speedFadeDelay = 0; #if defined(CUSTOM_WS2812FX_ANIMATIONS) #define MULTICAST false @@ -140,7 +141,7 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod #define DBG_OUTPUT_PORT Serial // Set debug output port // List of all color modes -enum MODE {OFF, HOLD, SET, SET_SPEED, INIT_STRIP}; +enum MODE {OFF, HOLD, SET, INIT_STRIP}; MODE mode = SET; // Standard mode that is active when software starts MODE prevmode = HOLD; // Do not change diff --git a/Arduino/McLighting/mode_custom_ws2812fx_animations.h b/Arduino/McLighting/mode_custom_ws2812fx_animations.h index 8b345aa..a851d82 100644 --- a/Arduino/McLighting/mode_custom_ws2812fx_animations.h +++ b/Arduino/McLighting/mode_custom_ws2812fx_animations.h @@ -150,7 +150,6 @@ void handleE131(){ } } - #include //https://github.com/FastLED/FastLED /* * paste in the Fire2012 code with a small edit at the end which uses the diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h index 95bcc98..9e73264 100644 --- a/Arduino/McLighting/request_handlers.h +++ b/Arduino/McLighting/request_handlers.h @@ -17,38 +17,33 @@ void convertColors() { hex_colors_trans[2] = (uint32_t)(xtra_color.white << 24) | (xtra_color.red << 16) | (xtra_color.green << 8) | xtra_color.blue; } -void convertColorsFade() { - if ((transEffect) && (trans_cnt > 1) && (trans_cnt < 254)) { - memcpy(hex_colors, strip->getColors(selected_segment), sizeof(strip->getColors(selected_segment))); - DBG_OUTPUT_PORT.println("Color transistion aborted. Restarting...!"); - trans_cnt = 1; - } else { - //memcpy(hex_colors, hex_colors_trans, sizeof(hex_colors_trans)); - } -} - -uint8_t calculateColorTransitionSteps () { +void calculateColorTransitionSteps() { //compare all colors and calculate steps - int trans_cnt_max = 0; + trans_cnt_max = 0; int calculate_max[4] = {}; for (uint8_t i=0; i<3; i++){ - DBG_OUTPUT_PORT.printf("i: %i\r\n", i); for (uint8_t j=0; j<4; j++) { - DBG_OUTPUT_PORT.printf("j: %i\r\n", j); calculate_max[j] = ((hex_colors[i] >> ((3-j)*8)) & 0xFF) - ((hex_colors_trans[i] >> ((3-j)*8)) & 0xFF); calculate_max[j] = abs(calculate_max[j]); trans_cnt_max = max(trans_cnt_max, calculate_max[j]); - DBG_OUTPUT_PORT.printf("calcmax: %i %i\r\n", j, calculate_max[j]); } } - DBG_OUTPUT_PORT.printf("max: %i\r\n", trans_cnt_max); - return trans_cnt_max; } - +void convertColorsFade() { + if (transEffect) { + if (trans_cnt > 1) { + memcpy(hex_colors, strip->getColors(selected_segment), sizeof(hex_colors)); + DBG_OUTPUT_PORT.println("Color transistion aborted. Restarting...!"); + trans_cnt = 1; + } + calculateColorTransitionSteps(); + } +} void getArgs() { if (mode == SET) { + //color wrgb if (server.arg("rgb") != "") { uint32_t rgb = (uint32_t) strtoul(server.arg("rgb").c_str(), NULL, 16); main_color.white = ((rgb >> 24) & 0xFF); @@ -121,17 +116,16 @@ void getArgs() { 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); - } - if (mode == SET || mode == SET_SPEED) { + // Speed if ((server.arg("s") != "") && (server.arg("s").toInt() >= 0) && (server.arg("s").toInt() <= 255)) { - ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255); + ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255); } - } - if (mode == SET) { + //Mode if ((server.arg("m") != "") && (server.arg("m").toInt() >= 0) && (server.arg("m").toInt() <= strip->getModeCount())) { ws2812fx_mode = constrain(server.arg("m").toInt(), 0, strip->getModeCount() - 1); } - if ((server.arg("c") != "") && (server.arg("c").toInt() >= 0) && (server.arg("c").toInt() <= 100)) { + // Brightness + if ((server.arg("c") != "") && (server.arg("c").toInt() >= 0) && (server.arg("c").toInt() <= 100)) { brightness = constrain((int) server.arg("c").toInt() * 2.55, 0, 255); } else if ((server.arg("p") != "") && (server.arg("p").toInt() >= 0) && (server.arg("p").toInt() <= 255)) { brightness = constrain(server.arg("p").toInt(), 0, 255); @@ -204,9 +198,9 @@ void handleSetAllMode(uint8_t * mypayload) { void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { // decode led index - char templed[3]; - strncpy (templed, (const char *) &mypayload[firstChar], 2 ); - templed[2] = 0x00; + char templed[5]; + strncpy (templed, (const char *) &mypayload[firstChar], 4 ); + templed[4] = 0x00; uint8_t led = atoi(templed); DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\r\n", led, WS2812FXStripSettings.stripSize, mypayload ); @@ -215,10 +209,10 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { char greenhex[3]; char bluehex[3]; char whitehex[3]; - strncpy (whitehex, (const char *) &mypayload[2 + firstChar], 2 ); - strncpy (redhex, (const char *) &mypayload[4 + firstChar], 2 ); - strncpy (greenhex, (const char *) &mypayload[6 + firstChar], 2 ); - strncpy (bluehex, (const char *) &mypayload[8 + firstChar], 2 ); + strncpy (whitehex, (const char *) &mypayload[4 + firstChar], 2 ); + strncpy (redhex, (const char *) &mypayload[6 + firstChar], 2 ); + strncpy (greenhex, (const char *) &mypayload[8 + firstChar], 2 ); + strncpy (bluehex, (const char *) &mypayload[10 + firstChar], 2 ); whitehex[2] = 0x00; redhex[2] = 0x00; greenhex[2] = 0x00; @@ -260,26 +254,26 @@ void handleSetDifferentColors(uint8_t * mypayload) { void handleRangeDifferentColors(uint8_t * mypayload) { uint8_t* nextCommand = 0; nextCommand = (uint8_t*) strtok((char*) mypayload, "R"); - // While there is a range to process R0110<00ff00> + // While there is a range to process R00010010<0000ff00> while (nextCommand) { // Loop for each LED. - char startled[4]; - char endled[4]; + char startled[5]; + char endled[5]; char colorval[9]; - strncpy ( startled, (const char *) &nextCommand[0], 2 ); - startled[3] = 0x00; - strncpy ( endled, (const char *) &nextCommand[2], 2 ); - endled[3] = 0x00; - strncpy ( colorval, (const char *) &nextCommand[4], 8 ); + strncpy ( startled, (const char *) &nextCommand[0], 4 ); + startled[4] = 0x00; + strncpy ( endled, (const char *) &nextCommand[4], 4 ); + endled[4] = 0x00; + strncpy ( colorval, (const char *) &nextCommand[8], 8 ); colorval[8] = 0x00; uint8_t rangebegin = atoi(startled); uint8_t rangeend = atoi(endled); DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s]\r\n", rangebegin, rangeend, colorval); while ( rangebegin <= rangeend ) { - char rangeData[11]; - snprintf(rangeData, sizeof(rangeData), "%02d%s", rangebegin, colorval); + char rangeData[18]; + snprintf(rangeData, sizeof(rangeData), "%04d%s", rangebegin, colorval); rangeData[sizeof(rangeData) - 1] = 0x00; // Set one LED handleSetSingleLED((uint8_t*) rangeData, 0); @@ -472,6 +466,9 @@ void handleSetWS2812FXMode(uint8_t * mypayload) { if (strcmp((char *) &mypayload[1], "off") == 0) { mode = OFF; } + if (strcmp((char *) &mypayload[1], "on") == 0) { + mode = HOLD; + } } } @@ -646,7 +643,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { if (payload[0] == '?') { uint8_t d = (uint8_t) strtol((const char *) &payload[1], NULL, 10); ws2812fx_speed = constrain(d, 0, 255); - mode = SET_SPEED; + mode = SET; Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set speed to: [%u]\r\n", ws2812fx_speed); } @@ -1059,7 +1056,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght uint8_t json_speed = constrain((uint8_t) root["speed"], 0, 255); if (json_speed != ws2812fx_speed) { ws2812fx_speed = json_speed; - mode = SET_SPEED; + mode = SET; } } @@ -1663,7 +1660,7 @@ void handleRemote() { mode = OFF; } } - if ((mode != AUTO) && (mode != OFF)) { + if (mode == HOLD) { if (results.value == rmt_commands[BRIGHTNESS_UP]) { //Brightness Up last_remote_cmd = results.value; if (brightness + chng <= 255) { @@ -1678,204 +1675,204 @@ void handleRemote() { mode = SET; } } - } - if ((mode !=AUTO) && (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; + if ((ws2812fx_mode < 56) || (ws2812fx_mode > 57)) { + 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; } } - if (selected_color == 2) { - if (back_color.red + chng <= 255) { - back_color.red = back_color.red + chng; - mode = SET; - } - } - if (selected_color == 3) { - if (xtra_color.red + chng <= 255) { - xtra_color.red = xtra_color.red + chng; + 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; } } } - 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; + if ((ws2812fx_mode < 56) || (ws2812fx_mode > 60)) { + 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; + } + } + if (selected_color == 2) { + if (back_color.red + chng <= 255) { + back_color.red = back_color.red + chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.red + chng <= 255) { + xtra_color.red = xtra_color.red + chng; + mode = SET; + } } } - if (selected_color == 2) { - if (back_color.red - chng >= 0) { - back_color.red = back_color.red - chng; - mode = SET; + 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; + } + } + if (selected_color == 2) { + if (back_color.red - chng >= 0) { + back_color.red = back_color.red - chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.red - chng >= 0) { + xtra_color.red = xtra_color.red - chng; + mode = SET; + } } } - if (selected_color == 3) { - if (xtra_color.red - chng >= 0) { - xtra_color.red = xtra_color.red - chng; - mode = SET; + 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; + } + } + if (selected_color == 2) { + if (back_color.green + chng <= 255) { + back_color.green = back_color.green + chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.green + chng <= 255) { + xtra_color.green = xtra_color.green + chng; + mode = SET; + } } } - } - 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; + 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; + } + } + if (selected_color == 2) { + if (back_color.green - chng >= 0) { + back_color.green = back_color.green - chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.green - chng >= 0) { + xtra_color.green = xtra_color.green - chng; + mode = SET; + } } } - if (selected_color == 2) { - if (back_color.green + chng <= 255) { - back_color.green = back_color.green + chng; - mode = SET; + 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; + } + } + if (selected_color == 2) { + if (back_color.blue + chng <= 255) { + back_color.blue = back_color.blue + chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.blue + chng <= 255) { + xtra_color.blue = xtra_color.blue + chng; + mode = SET; + } } } - if (selected_color == 3) { - if (xtra_color.green + chng <= 255) { - xtra_color.green = xtra_color.green + chng; - mode = SET; + 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; + } + } + if (selected_color == 2) { + if (back_color.blue - chng >= 0) { + back_color.blue = back_color.blue - chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.blue - chng >= 0) { + xtra_color.blue = xtra_color.blue - chng; + mode = SET; + } } } - } - 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; + 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; + } + } + if (selected_color == 2) { + if (back_color.white + chng <= 255) { + back_color.white = back_color.white + chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.white + chng <= 255) { + xtra_color.white = xtra_color.white + chng; + mode = SET; + } } } - if (selected_color == 2) { - if (back_color.green - chng >= 0) { - back_color.green = back_color.green - chng; - mode = SET; + 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; + } + } + if (selected_color == 2) { + if (back_color.white - chng >= 0) { + back_color.white = back_color.white - chng; + mode = SET; + } + } + if (selected_color == 3) { + if (xtra_color.white - chng >= 0) { + xtra_color.white = xtra_color.white - chng; + mode = SET; + } } } - if (selected_color == 3) { - if (xtra_color.green - chng >= 0) { - xtra_color.green = xtra_color.green - chng; - mode = SET; - } + 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; } } - 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; - } - } - if (selected_color == 2) { - if (back_color.blue + chng <= 255) { - back_color.blue = back_color.blue + chng; - mode = SET; - } - } - if (selected_color == 3) { - if (xtra_color.blue + chng <= 255) { - xtra_color.blue = xtra_color.blue + chng; - mode = SET; - } - } - } - 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; - } - } - if (selected_color == 2) { - if (back_color.blue - chng >= 0) { - back_color.blue = back_color.blue - chng; - mode = SET; - } - } - if (selected_color == 3) { - if (xtra_color.blue - chng >= 0) { - xtra_color.blue = xtra_color.blue - chng; - mode = SET; - } - } - } - 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; - } - } - if (selected_color == 2) { - if (back_color.white + chng <= 255) { - back_color.white = back_color.white + chng; - mode = SET; - } - } - if (selected_color == 3) { - if (xtra_color.white + chng <= 255) { - xtra_color.white = xtra_color.white + chng; - mode = SET; - } - } - } - 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; - } - } - if (selected_color == 2) { - if (back_color.white - chng >= 0) { - back_color.white = back_color.white - chng; - mode = SET; - } - } - if (selected_color == 3) { - if (xtra_color.white - chng >= 0) { - xtra_color.white = xtra_color.white - chng; - mode = SET; - } - } - } - 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; @@ -1937,6 +1934,7 @@ uint32_t scale_wrgb(uint32_t wrgb, uint8_t level) { } uint32_t trans(uint32_t newcolor, uint32_t oldcolor, uint8_t level) { + level = (level * (255/trans_cnt_max)); newcolor = scale_wrgb(newcolor, level); oldcolor = scale_wrgb(oldcolor, 255-level); return newcolor + oldcolor; diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino index 1bee4b4..cd572df 100644 --- a/Arduino/McLighting/version_info.ino +++ b/Arduino/McLighting/version_info.ino @@ -172,7 +172,7 @@ * adressed issue: https://github.com/toblum/McLighting/issues/403 (Experimental Support of transitions: set transEffect = true in definitions.h) * corrected use of DMA for Neopixelbus by Makuna (Tests for other strips than SK6812 GRBW were not made) * - * 27 September 2019 + * 27 September 2019 * Version Bump to 3.0.0.ALPHA1 * removed LEGACY_ANIMATIONS * removed old Custom Animations from beginning of list. @@ -184,4 +184,7 @@ * moved Custom Animation 'Gradients' to number 61 * REST-API changes (will be documented soon) * + * 29 September 2019 + * Version Bump to 3.0.0.BETA1 + * further code changes */ diff --git a/clients/HomeAssistant/light.yaml b/clients/HomeAssistant/light.yaml index 72543f1..061f4a7 100644 --- a/clients/HomeAssistant/light.yaml +++ b/clients/HomeAssistant/light.yaml @@ -64,7 +64,12 @@ light: - "Bicolor Chase" - "Tricolor Chase" - "ICU" - - "E131" + - "AutoPlay" + - "Custom WS" + - "TV" + - "E1.31" + - "Fire(2012)" + - "Gradient" brightness: true color_temp: true rgb: true diff --git a/clients/homebridge/config.json b/clients/homebridge/config.json index 239959b..7adf230 100644 --- a/clients/homebridge/config.json +++ b/clients/homebridge/config.json @@ -22,12 +22,12 @@ "brightness": { "status": "http:///get_brightness", - "url": "http:///set_brightness?c=%s" + "url": "http:///set?c=%s" }, "color": { "status": "http:///get_color", - "url": "http:///all?rgb=%s", + "url": "http:///set?m=0?rgb=%s", "brightness": true } } diff --git a/clients/newWebClient/favicon.ico b/clients/newWebClient/favicon.ico deleted file mode 100644 index 12e9deac79f3905e145ebb882854ba06f85357d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmah|ZAep57=Cu|w(I6tx>><$HVY}7N?+ur&KZ{|tthOBW%OYzg$hZ?=ts?xK9&?2 z&Y+Bj)sL>!k3Jxx59j^_5w#x~^mU^|s2QY!LV0~VcS|zu<6NF|InQ~Y_q^wQ-vema zmzD-LJ5ZwqrU978z$nHfdG-U?o;5Xz#CqbS*Q<;Pxj7uxH5q0d17LZ zPuNUUs%s7BoaxdY+Ae7yUF*}lf2%<5Cp=_0)uUiTqz~B*5`;XLYCF+^uE17dY}+gw zKV2m~y&&!z(|sHyJYZ-ZA#5YUq5;B`4jJ%PjOh&}7U;54-04kAWb3QlWd7Vt!jlU_ zTuU&D+WHWD469nBD2xrk&in}9iRU|Ho_D&n+BK>hQ^wXb$#E~AW;`t;^TpM@yqM=_ zeEQfKEZTIWF86EncX|aup^S_HvRDpFs@9kZaqdYWo`2s;v)b&#DTNkQJL!HZ$MfZW zyFE5sR7B+QMB-MfQ?xBbprjp2>1_?o-o;0mnS~Q3%Q?=dhGX%1TceGQqZADGC>~E` zz_}jbO*cWlTcDhc2&qQ@8dX*Gp;&B?y1VDC=2YWoAP>e*A4A>>0&G>E-J zckzU}xPCe&Nb+p0)9uwK`X_POk_D(ZR}DF`8+30i=yERTv>6oCq)`hBsU3UhD%$8E z&d3YK_3yY$X|kunwS7LMqYKe@ItxmZ33NhZqDJH>`ylqMgD5%R_~ZLg{b-YIW3n3{ zx>6BXszbOGy6|F{12&ivxzd6gcO>w23ed>|4NR*-9egJsy#F04r;af@RikQu0B{>1 A)c^nh diff --git a/clients/newWebClient/index.htm.gz b/clients/newWebClient/index.htm.gz deleted file mode 100644 index 951285306aff190abefe75b74be775b34cbc417c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19973 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 - - - - - - - - - - - - - McLighting (RGBW) v2 - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Error on websocket connect.
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
pick a color
-
-
-
-
-
Auto:
- -
-
-
-
-
- -
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-

-
-
- -
-
-
-

-
-
- -
-
-
-

-
-
- -
-
-
-

-
-
-
-
- -
-
-
- Loading animations... -
-
-
-
-
- - - - - - - - - - - \ No newline at end of file diff --git a/clients/web(RGBW)/gulpfile.js b/clients/web(RGBW)/gulpfile.js deleted file mode 100644 index cb2773a..0000000 --- a/clients/web(RGBW)/gulpfile.js +++ /dev/null @@ -1,55 +0,0 @@ -var gulp = require('gulp'), - request = require('request'), - fs = require('fs'), - connect = require('gulp-connect'), - fileinclude = require('gulp-file-include'); - -var src_dir = "src/"; -var build_dir = "build/"; - - -gulp.task('html', function() { - gulp.src(src_dir + '*.htm') - .pipe(fileinclude({ - prefix: '@@', - basepath: '@file' - })) - .pipe(gulp.dest('build')) - .pipe(connect.reload()); -}); - - -gulp.task('connect', function() { - connect.server({ - root: 'build', - livereload: true - }); -}); - -gulp.task('watch', function() { - gulp.watch(src_dir + '*.htm', ['html']); - gulp.watch(src_dir + 'js/*.js', ['html']); -}); - - -gulp.task('upload', ['html'], function() { - var url = 'http://192.168.0.49/edit'; - var options = { - url: url, - headers: { - 'Content-Type': 'multipart/form-data' - } - }; - - var r = request.post(options, function optionalCallback(err, httpResponse, body) { - if (err) { - return console.error('upload failed:', err); - } - console.log('Upload successful! Server responded with:', body); - }); - var form = r.form(); - form.append('data', fs.createReadStream(__dirname + "/" + build_dir + '/index.htm'), {filename: '/index.htm', contentType: "application/octet-stream"}); -}); - -gulp.task('default', ['html']); -gulp.task('serve', ['watch', 'connect']); \ No newline at end of file diff --git a/clients/web(RGBW)/package.json b/clients/web(RGBW)/package.json deleted file mode 100644 index 98632aa..0000000 --- a/clients/web(RGBW)/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "mc_lighting", - "version": "2.0.0", - "description": "Web client for Mc Lighting", - "main": "index.html", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Tobias Blum", - "license": "MIT", - "dependencies": { - "fs": "0.0.2", - "gulp": "^3.9.1", - "gulp-connect": "^5.0.0", - "gulp-file-include": "^1.0.0", - "request": "^2.72.0" - } -} diff --git a/clients/web(RGBW)/src/index.htm b/clients/web(RGBW)/src/index.htm deleted file mode 100644 index b5e1645..0000000 --- a/clients/web(RGBW)/src/index.htm +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - McLighting (RGBW) v2 - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Error on websocket connect.
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
pick a color
-
-
-
-
-
Auto:
- -
-
-
-
-
- -
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-

-
-
- -
-
-
-

-
-
- -
-
-
-

-
-
- -
-
-
-

-
-
-
-
- -
-
-
- Loading animations... -
-
-
-
-
- - - - - - - - - - - \ No newline at end of file - \ No newline at end of file diff --git a/clients/web(RGBW)/src/js/script.js b/clients/web(RGBW)/src/js/script.js deleted file mode 100644 index 4f62d27..0000000 --- a/clients/web(RGBW)/src/js/script.js +++ /dev/null @@ -1,331 +0,0 @@ -(function($){ -$(function(){ - - // Settings - var host = window.location.hostname; - //host = "esp8266_02.local"; - - var ws_url = 'ws://' + host + ':81'; - var connection; - var ws_waiting = 0; - - // ****************************************************************** - // Side navigation - // ****************************************************************** - $('.button-collapse').sideNav(); - - // Navlinks - $('#mc-nav').on('click', '.mc-navlink', function(){ - console.log("Navigate to pane: ", $(this).data("pane")); - showPane($(this).data("pane")); - }); - - function showPane(pane) { - $('.mc_pane').addClass('hide'); - $('#' + pane).removeClass('hide'); - $('.button-collapse').sideNav('hide'); - - //if (pane == "pane2") { - // setMainColor(); - //} - } - - - // ****************************************************************** - // init() - // ****************************************************************** - function init() { - console.log("Connection websockets to:", ws_url); - connection = new WebSocket(ws_url, ['arduino']); - var mode = 0; - var ws2812fx_mode = 0; - $.getJSON("http://" + host + "/status", function(data) { - console.log("status", data); - mode = data.mode; - ws2812fx_mode = data.ws2812fx_mode; - $("#rng_delay").val(data.speed); - $("#rng_brightness").val(data.brightness); - $("#rng_white").val(data.color[0]); - $("#rng_red").val(data.color[1]); - $("#rng_green").val(data.color[2]); - $("#rng_blue").val(data.color[3]); - var statusColor = "#" + componentToHex(data.color[1]) + componentToHex(data.color[2]) + componentToHex(data.color[3]); - $('#status').css("backgroundColor", statusColor); - $('#status_color').text(statusColor + "- R=" + data.color[1] + ", G=" + data.color[2] + ", B=" + data.color[3]); - }); - - // Load modes async - // List of all color modes - // enum MODE {OFF, AUTO, TV, E131, SET_MODE, HOLD, CUSTOM, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW}; - $.getJSON("http://" + host + "/get_modes", function(data) { - console.log("modes", data); - var modes_html = ""; - data.forEach(function(current_mode){ - if (current_mode.mode !== undefined) { - modes_html += '
'; - if ((mode == "5" && current_mode.mode == ws2812fx_mode) || (mode == "0" && current_mode.mode == "off") || (mode == "2" && current_mode.mode == "tv") || (mode == "3" && current_mode.mode == "e131")){ - modes_html += '(' + current_mode.mode +') '+ current_mode.name; - } else { - modes_html += '(' + current_mode.mode +') '+ current_mode.name; - } - modes_html += 'send'; - modes_html += ''; - modes_html += '
'; - } - }); - - $('#modes').html(modes_html); - }); - // When the connection is open, send some data to the server - connection.onopen = function () { - //connection.send('Ping'); // Send the message 'Ping' to the server - console.log('WebSocket Open'); - showPane('pane1'); - }; - - // Log errors - connection.onerror = function (error) { - console.log('WebSocket Error ' + error); - $('#mc-wsloader').addClass('hide'); - $('#mc-wserror').removeClass('hide'); - }; - - // Log messages from the server - connection.onmessage = function (e) { - console.log('WebSocket from server: ' + e.data); - ws_waiting = 0; - }; - } - - - // ****************************************************************** - // Modes - // ****************************************************************** - $("#pane2").on("click", ".btn_mode", function() { - var mode = $(this).attr("data-mode"); - last_mode = mode; - var btn = $(this); - setMode(mode, function() { - $(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue"); - btn.removeClass("blue").addClass("red"); - }); - }); - - $("#pane2").on("click", ".btn_mode_static", function() { - var mode = $(this).attr("data-mode"); - var btn = $(this); - - wsSendCommand("=" + mode); - $(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue"); - btn.removeClass("blue").addClass("red"); - }); - - $("#pane2").on("change", ".update_colors", setMainColor); - - $("#pane2").on("change", ".update_delay", function() { - var delay = $("#rng_delay").val(); - - wsSendCommand("?" + delay); - }); - - $("#pane2").on("change", ".update_brightness", function() { - var brightness = $("#rng_brightness").val(); - - wsSendCommand("%" + brightness); - }); - - $("#autoSwitch").on("change", function () { - if ($(this).prop('checked')) { - wsSendCommand("start"); - } else { - wsSendCommand("stop"); - } - }); - - function setMode(mode, finish_funtion) { - console.log("Mode: ", mode); - - wsSendCommand("/" + mode); - finish_funtion(); - } - - function setMainColor() { - var white = $("#rng_white").val(); - var red = $("#rng_red").val(); - var green = $("#rng_green").val(); - var blue = $("#rng_blue").val(); - - var hexColor = componentToHex(white) + componentToHex(red) + componentToHex(green) + componentToHex(blue); - var statusColor = "#" + componentToHex(red) + componentToHex(green) + componentToHex(blue); - wsSetMainColor(hexColor); - $('#status').css("backgroundColor", statusColor); - $('#status_color').text(statusColor + "- R=" + red + ", G=" + green + ", B=" + blue); - } - - - // ****************************************************************** - // WebSocket commands - // ****************************************************************** - function wsSendCommand(cmd) { - console.log("Send WebSocket command:", cmd); - if (ws_waiting == 0) { - connection.send(cmd); - ws_waiting++; - } else { - console.log("++++++++ WS call waiting, skip") - } - } - - - function wsSetAll(hexColor) { - console.log("wsSetAll() Set all colors to:", hexColor); - wsSendCommand("*" + hexColor); - } - - function wsSetMainColor(hexColor) { - console.log("wsSetMainColor() Set main colors to:", hexColor); - wsSendCommand("#" + hexColor); - } - - - - // ****************************************************************** - // Colorwheel - // ****************************************************************** - // this is supposed to work on mobiles (touch) as well as on a desktop (click) - // since we couldn't find a decent one .. this try of writing one by myself - // + google. swiping would be really nice - I will possibly implement it with - // jquery later - or never. - - var canvas = document.getElementById("myCanvas"); - // FIX: Cancel touch end event and handle click via touchstart - // canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false); - canvas.addEventListener("touchmove", doTouch, false); - canvas.addEventListener("click", doClick, false); - //canvas.addEventListener("mousemove", doClick, false); - - - var context = canvas.getContext('2d'); - var centerX = canvas.width / 2; - var centerY = canvas.height / 2; - var innerRadius = canvas.width / 4.5; - var outerRadius = (canvas.width - 10) / 2 - - //outer border - context.beginPath(); - //outer circle - context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false); - //draw the outer border: (gets drawn around the circle!) - context.lineWidth = 4; - context.strokeStyle = '#000000'; - context.stroke(); - context.closePath(); - - //fill with beautiful colors - //taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5 - for(var angle=0; angle<=360; angle+=1) { - var startAngle = (angle-2)*Math.PI/180; - var endAngle = angle * Math.PI/180; - context.beginPath(); - context.moveTo(centerX, centerY); - context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false); - context.closePath(); - context.fillStyle = 'hsl('+angle+', 100%, 50%)'; - context.fill(); - context.closePath(); - } - - //inner border - context.beginPath(); - //context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise); - context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false); - //fill the center - var my_gradient=context.createLinearGradient(0,0,170,0); - my_gradient.addColorStop(0,"black"); - my_gradient.addColorStop(1,"white"); - - context.fillStyle = my_gradient; - context.fillStyle = "white"; - context.fill(); - - //draw the inner line - context.lineWidth = 2; - context.strokeStyle = '#000000'; - context.stroke(); - context.closePath(); - - //get Mouse x/y canvas position - function getMousePos(canvas, evt) { - var rect = canvas.getBoundingClientRect(); - return { - x: evt.clientX - rect.left, - y: evt.clientY - rect.top - }; - } - - //comp to Hex - function componentToHex(c) { - //var hex = c.toString(16); - //return hex.length == 1 ? "0" + hex : hex; - return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase(); - } - - //rgb/rgba to Hex - function rgbToHex(rgb) { - return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); - } - - //display the touch/click position and color info - function updateStatus(pos, color) { - //var hexColor = rgbToHex(color); - //wsSetAll(hexColor); - var hexColor = componentToHex(color[0]) + componentToHex(color[1]) + componentToHex(color[2]); - wsSetMainColor(hexColor); - hexColor = "#" + hexColor; - - $('#status').css("backgroundColor", hexColor); - $('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]); - $('#status_pos').text("x: " + pos.x + " - y: " + pos.y); - - $("#rng_white").val(0); - $("#rng_red").val(color[0]); - $("#rng_green").val(color[1]); - $("#rng_blue").val(color[2]); - } - - //handle the touch event - function doTouch(event) { - //to not also fire on click - event.preventDefault(); - var el = event.target; - - //touch position - var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft), - y: Math.round(event.targetTouches[0].pageY - el.offsetTop)}; - //color - var color = context.getImageData(pos.x, pos.y, 1, 1).data; - - updateStatus(pos, color); - } - - function doClick(event) { - //click position - var pos = getMousePos(canvas, event); - //color - var color = context.getImageData(pos.x, pos.y, 1, 1).data; - - //console.log("click", pos.x, pos.y, color); - updateStatus(pos, color); - - //now do sth with the color rgbToHex(color); - //don't do stuff when #000000 (outside circle and lines - } - - - // ****************************************************************** - // main - // ****************************************************************** - init(); - -}); // end of document ready -})(jQuery); // end of jQuery name space \ No newline at end of file diff --git a/clients/web/README.md b/clients/web/README.md deleted file mode 100644 index b7e7616..0000000 --- a/clients/web/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Retired, use: -McLightingHTML from https://github.com/FabLab-Luenen/McLightingHTML - -or set #define USE_HTML_MIN_GZ in definitions.h to use the integrated! diff --git a/clients/web/apple-touch-icon.png b/clients/web/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c00fb89de57046547094f4785167e3409afdc8ac GIT binary patch literal 4500 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 m_iVO+_x78a5@6?Iw*L#`C2;+Lpe=y_0000 - - - - - - - - - - - - McLighting v2 - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Error on websocket connect.
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
pick a color
-
-
-
-
-
Auto:
- -
-
-
-
-
- -
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-

-
-
- -
-
-
-

-
-
- -
-
-
-

-
-
-
-
- -
- - - - -
-
- Loading animations... -
-
-
-
-
- - - - - - - - - - - \ No newline at end of file diff --git a/clients/newWebClient/edit.htm b/clients/web/edit.htm similarity index 100% rename from clients/newWebClient/edit.htm rename to clients/web/edit.htm diff --git a/clients/newWebClient/edit.htm.gz b/clients/web/edit.htm.gz similarity index 100% rename from clients/newWebClient/edit.htm.gz rename to clients/web/edit.htm.gz diff --git a/clients/web/favicon.ico b/clients/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1c55beaf3d048b31b786937190d4bdc8a40610ea GIT binary patch literal 34494 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 literal 0 HcmV?d00001 diff --git a/clients/web/graphs.js.gz b/clients/web/graphs.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..72435445a7ef86e00fe6c66b3b71c47fdbd53a93 GIT binary patch literal 1971 zcmV;k2Tb@MiwFo@s$5k717~t!aAw-*8%!ep`yEM!aI@XpTRzN;M>CH`Bk93rb1y+*nfgVXr6{*O z+qWk+vpIfdbmRB&GiOD~!8-BI8jWLya*xm0`?Ns*u7@$U5b~-2FAtyY?VsHiJWiul z$g}Ci$m17Tz>sgbNBG!p6`3AIdmW5d-8e)$jYf;JJn?*ncK^L=>v4>q7o#|V#AXxo zd(ilSPVW5&A*9`%(ECk!Y+arKfe)*P?pEpRp~jzoF096?>r=Aoz97T=5)|h&-xQIu zg>l28ew8E08a6CBp`}c_5jC)_GP?DY`3f}-jd!TP&)0@aTI6>ySBJ(C^6Vjg_FCi? z4W)y8K|{N+7xu_b?5Q2tp*_aW9rTMaq?DSsrVu+rd~J}hE1ki{8Q_4DpSuf+7N=y0 z&lbmI*d0+cIw7C&8TouX>b8vuC7%rP5n-@XYJN3AXB2Qkjq~PBh|f&&!8{IOB&X(2 zH9yyb7aQ|uSdryo%OvNrl!(4VCh<(%jlKg>o+p(VLEZu+SU49}D`X?;9hV2J6#b@5xoQzr_H2o5@^1L}hMUELzT^@ZjjKOo0;;PSc-R=y16 zZ?GMY#vgK8*szEP4+cZTEn{%f2k_E z27Gde+C~f)Fg^jqZfsd{i2;6w@jVpRk!@);Z(!Q^0V_`j7DaAW9TdZ@cIt4a4szZaa^^aU29qDr;ABm46G?-=na2}Ferp=!isDL5 zZsRR-8*h`__!TcbYL6zj@e8?){|UK0{(#)d@5!y&&_(q^Zq+tjEH`wq+|b2RliLz5 zFqaQCU2wY8dG2R6eWA(3ua&TB6J>0#%pV>3Z zdyofc0!I`ut`SP$kiJ3WHi#-0<433_` z)YOv0bAAFn?dFnNRNv(ebZf$J9m~5X4;HB}|KgQLUj9wtTU0ot`o1rAx!kOPE}Fw8 zS~Q^pvJt_F1Mf4=n%)ASw`5Ik|GTcX!Dzk1YQ^WUvs*ob65M#*8Pl}n#sj~2z;Kp3 z#wt>!wBemdQe1%Fa@<6G*Tw3BO6(?)=)j$C-mo1S$t$oENe=yhLb-k<8_;yI4OzB} zRnJ39Vd(ZadQJ$E_Fo6+T+OyM?w0=_W4@|s1;9o}-pE(zujhQpQ&}rb!wtIwq}*=X z4FSKo$AySPF)Nk{6YIBX;rZfke?Eikq=c+ENp6^52>r$^5|&2ANW^K%_#LYXv7c8e z=vGa#hyxfcmO0B{UVkpiG+<$zvOo;WqJY`6)K6l6B8Kp~K2ezpCd|@8%tl_2EiSSo zFA^|v1uq>WUSe{a+%Cnisy&!<^nU5?i#QLL2@C+6O z9mvZ6hkhC(4R=nr5iF#GH6&3&)`F6DcbF}Sh6I^7IhzV|9hOnAbbP~0)_aTc?G-T zUOp0`CmZu63}>tmJ`@(Gu)SWMGnfEAsi4IU)bR<5*jr~_#!;-Z^EjQ<&VItC4B8MT z8B`^L%rDim_gH$+=1MruU~n)H8CPxfm(bCv7eR<84hDk()HUc0oPGxaFZ!1Rx^{U0 z&VK*U?e~RBheyXbhhXsb4|_d`A?>3*L0l+t&uz4z32}iM0zT**`+0@&e*in8G#?BP F000|7$0Ps% literal 0 HcmV?d00001 diff --git a/clients/web/gulpfile.js b/clients/web/gulpfile.js deleted file mode 100644 index cb2773a..0000000 --- a/clients/web/gulpfile.js +++ /dev/null @@ -1,55 +0,0 @@ -var gulp = require('gulp'), - request = require('request'), - fs = require('fs'), - connect = require('gulp-connect'), - fileinclude = require('gulp-file-include'); - -var src_dir = "src/"; -var build_dir = "build/"; - - -gulp.task('html', function() { - gulp.src(src_dir + '*.htm') - .pipe(fileinclude({ - prefix: '@@', - basepath: '@file' - })) - .pipe(gulp.dest('build')) - .pipe(connect.reload()); -}); - - -gulp.task('connect', function() { - connect.server({ - root: 'build', - livereload: true - }); -}); - -gulp.task('watch', function() { - gulp.watch(src_dir + '*.htm', ['html']); - gulp.watch(src_dir + 'js/*.js', ['html']); -}); - - -gulp.task('upload', ['html'], function() { - var url = 'http://192.168.0.49/edit'; - var options = { - url: url, - headers: { - 'Content-Type': 'multipart/form-data' - } - }; - - var r = request.post(options, function optionalCallback(err, httpResponse, body) { - if (err) { - return console.error('upload failed:', err); - } - console.log('Upload successful! Server responded with:', body); - }); - var form = r.form(); - form.append('data', fs.createReadStream(__dirname + "/" + build_dir + '/index.htm'), {filename: '/index.htm', contentType: "application/octet-stream"}); -}); - -gulp.task('default', ['html']); -gulp.task('serve', ['watch', 'connect']); \ No newline at end of file diff --git a/clients/newWebClient/index.htm b/clients/web/index.htm similarity index 93% rename from clients/newWebClient/index.htm rename to clients/web/index.htm index 7d8a7bf..647bb87 100644 --- a/clients/newWebClient/index.htm +++ b/clients/web/index.htm @@ -5,8 +5,8 @@ - - + + - - - - - - - diff --git a/clients/web/src/js/script.js b/clients/web/src/js/script.js deleted file mode 100644 index 60ef6d8..0000000 --- a/clients/web/src/js/script.js +++ /dev/null @@ -1,305 +0,0 @@ -(function($){ -$(function(){ - - // Settings - var host = window.location.hostname; - //host = "esp8266_02.local"; - - var ws_url = 'ws://' + host + ':81'; - var connection; - var ws_waiting = 0; - - // ****************************************************************** - // Side navigation - // ****************************************************************** - $('.button-collapse').sideNav(); - - // Navlinks - $('#mc-nav').on('click', '.mc-navlink', function(){ - console.log("Navigate to pane: ", $(this).data("pane")); - showPane($(this).data("pane")); - }); - - function showPane(pane) { - $('.mc_pane').addClass('hide'); - $('#' + pane).removeClass('hide'); - $('.button-collapse').sideNav('hide'); - - if (pane == "pane2") { - setMainColor(); - } - } - - - // ****************************************************************** - // init() - // ****************************************************************** - function init() { - console.log("Connection websockets to:", ws_url); - connection = new WebSocket(ws_url, ['arduino']); - - // Load modes async - $.getJSON("http://" + host + "/get_modes", function(data) { - //console.log("modes", data); - - var modes_html = ""; - data.forEach(function(current_mode){ - if (current_mode.mode !== undefined) { - modes_html += ''; - } - }); - - $('#modes').html(modes_html); - }); - - // When the connection is open, send some data to the server - connection.onopen = function () { - //connection.send('Ping'); // Send the message 'Ping' to the server - console.log('WebSocket Open'); - showPane('pane1'); - }; - - // Log errors - connection.onerror = function (error) { - console.log('WebSocket Error ' + error); - $('#mc-wsloader').addClass('hide'); - $('#mc-wserror').removeClass('hide'); - }; - - // Log messages from the server - connection.onmessage = function (e) { - console.log('WebSocket from server: ' + e.data); - ws_waiting = 0; - }; - } - - - // ****************************************************************** - // Modes - // ****************************************************************** - $("#pane2").on("click", ".btn_mode", function() { - var mode = $(this).attr("data-mode"); - last_mode = mode; - var btn = $(this); - setMode(mode, function() { - $(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue"); - btn.removeClass("blue").addClass("red"); - }); - }); - - $("#pane2").on("click", ".btn_mode_static", function() { - var mode = $(this).attr("data-mode"); - var btn = $(this); - - wsSendCommand("=" + mode); - $(".btn_mode, .btn_mode_static").removeClass("red").addClass("blue"); - btn.removeClass("blue").addClass("red"); - }); - - $("#pane2").on("change", ".update_colors", setMainColor); - - $("#pane2").on("change", ".update_delay", function() { - var delay = $("#rng_delay").val(); - - wsSendCommand("?" + delay); - }); - - $("#pane2").on("change", ".update_brightness", function() { - var brightness = $("#rng_brightness").val(); - - wsSendCommand("%" + brightness); - }); - - $("#autoSwitch").on("change", function () { - if ($(this).prop('checked')) { - wsSendCommand("start"); - } else { - wsSendCommand("stop"); - } - }); - - function setMode(mode, finish_funtion) { - console.log("Mode: ", mode); - - wsSendCommand("/" + mode); - finish_funtion(); - } - - function setMainColor() { - var red = $("#rng_red").val(); - var green = $("#rng_green").val(); - var blue = $("#rng_blue").val(); - - var mainColorHex = componentToHex(red) + componentToHex(green) + componentToHex(blue); - wsSetMainColor(mainColorHex); - } - - - // ****************************************************************** - // WebSocket commands - // ****************************************************************** - function wsSendCommand(cmd) { - console.log("Send WebSocket command:", cmd); - if (ws_waiting == 0) { - connection.send(cmd); - ws_waiting++; - } else { - console.log("++++++++ WS call waiting, skip") - } - } - - - function wsSetAll(hexColor) { - console.log("wsSetAll() Set all colors to:", hexColor); - wsSendCommand("*" + hexColor); - } - - function wsSetMainColor(hexColor) { - console.log("wsSetMainColor() Set main colors to:", hexColor); - wsSendCommand("#" + hexColor); - } - - - - // ****************************************************************** - // Colorwheel - // ****************************************************************** - // this is supposed to work on mobiles (touch) as well as on a desktop (click) - // since we couldn't find a decent one .. this try of writing one by myself - // + google. swiping would be really nice - I will possibly implement it with - // jquery later - or never. - - var canvas = document.getElementById("myCanvas"); - // FIX: Cancel touch end event and handle click via touchstart - // canvas.addEventListener("touchend", function(e) { e.preventDefault(); }, false); - canvas.addEventListener("touchmove", doTouch, false); - canvas.addEventListener("click", doClick, false); - //canvas.addEventListener("mousemove", doClick, false); - - - var context = canvas.getContext('2d'); - var centerX = canvas.width / 2; - var centerY = canvas.height / 2; - var innerRadius = canvas.width / 4.5; - var outerRadius = (canvas.width - 10) / 2 - - //outer border - context.beginPath(); - //outer circle - context.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI, false); - //draw the outer border: (gets drawn around the circle!) - context.lineWidth = 4; - context.strokeStyle = '#000000'; - context.stroke(); - context.closePath(); - - //fill with beautiful colors - //taken from here: http://stackoverflow.com/questions/18265804/building-a-color-wheel-in-html5 - for(var angle=0; angle<=360; angle+=1) { - var startAngle = (angle-2)*Math.PI/180; - var endAngle = angle * Math.PI/180; - context.beginPath(); - context.moveTo(centerX, centerY); - context.arc(centerX, centerY, outerRadius, startAngle, endAngle, false); - context.closePath(); - context.fillStyle = 'hsl('+angle+', 100%, 50%)'; - context.fill(); - context.closePath(); - } - - //inner border - context.beginPath(); - //context.arc(centerX, centerY, radius, startAngle, endAngle, counterClockwise); - context.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, false); - //fill the center - var my_gradient=context.createLinearGradient(0,0,170,0); - my_gradient.addColorStop(0,"black"); - my_gradient.addColorStop(1,"white"); - - context.fillStyle = my_gradient; - context.fillStyle = "white"; - context.fill(); - - //draw the inner line - context.lineWidth = 2; - context.strokeStyle = '#000000'; - context.stroke(); - context.closePath(); - - //get Mouse x/y canvas position - function getMousePos(canvas, evt) { - var rect = canvas.getBoundingClientRect(); - return { - x: evt.clientX - rect.left, - y: evt.clientY - rect.top - }; - } - - //comp to Hex - function componentToHex(c) { - //var hex = c.toString(16); - //return hex.length == 1 ? "0" + hex : hex; - return ("0"+(Number(c).toString(16))).slice(-2).toUpperCase(); - } - - //rgb/rgba to Hex - function rgbToHex(rgb) { - return componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); - } - - //display the touch/click position and color info - function updateStatus(pos, color) { - var hexColor = rgbToHex(color); - wsSetAll(hexColor); - - hexColor = "#" + hexColor; - - $('#status').css("backgroundColor", hexColor); - $('#status_color').text(hexColor + " - R=" + color[0] + ", G=" + color[1] + ", B=" + color[2]); - $('#status_pos').text("x: " + pos.x + " - y: " + pos.y); - - $("#rng_red").val(color[0]); - $("#rng_green").val(color[1]); - $("#rng_blue").val(color[2]); - } - - //handle the touch event - function doTouch(event) { - //to not also fire on click - event.preventDefault(); - var el = event.target; - - //touch position - var pos = {x: Math.round(event.targetTouches[0].pageX - el.offsetLeft), - y: Math.round(event.targetTouches[0].pageY - el.offsetTop)}; - //color - var color = context.getImageData(pos.x, pos.y, 1, 1).data; - - updateStatus(pos, color); - } - - function doClick(event) { - //click position - var pos = getMousePos(canvas, event); - //color - var color = context.getImageData(pos.x, pos.y, 1, 1).data; - - //console.log("click", pos.x, pos.y, color); - updateStatus(pos, color); - - //now do sth with the color rgbToHex(color); - //don't do stuff when #000000 (outside circle and lines - } - - - // ****************************************************************** - // main - // ****************************************************************** - init(); - -}); // end of document ready -})(jQuery); // end of jQuery name space \ No newline at end of file