From 5c1f793887739ac1a73306d1f979022f4b1fbcc0 Mon Sep 17 00:00:00 2001 From: Caleb Mah Date: Thu, 16 Jul 2020 23:29:06 +0800 Subject: [PATCH 01/19] photoresister sensor usermod --- .../photoresistor_sensor_mqtt_v1/README.md | 11 +++ .../photoresistor_sensor_mqtt_v1/usermod.cpp | 70 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 usermods/photoresistor_sensor_mqtt_v1/README.md create mode 100644 usermods/photoresistor_sensor_mqtt_v1/usermod.cpp diff --git a/usermods/photoresistor_sensor_mqtt_v1/README.md b/usermods/photoresistor_sensor_mqtt_v1/README.md new file mode 100644 index 0000000000..33d96bc743 --- /dev/null +++ b/usermods/photoresistor_sensor_mqtt_v1/README.md @@ -0,0 +1,11 @@ +# Photoresister sensor with MQTT + +This simple usermod allows attaching a photoresistor sensor like the KY-018 and publish the readings in percentage over MQTT. The frequency of MQTT messages can be modified, and there is a threshold value that can be set so that significant changes in the readings can be published immediately instead of waiting for the next update. This was found to be a good compromise between spamming MQTT messages and delayed updates. + +I also found it useful to limit the frequency of analog pin reads because otherwise the board hangs. + +This usermod has only been tested with the KY-018 sensor though should work for any other analog pin sensor. Note that this does not control the LED strip directly, it only publishes MQTT readings for use with other integrations like Home Assistant. + +## Installation + +Copy and replace the file `usermod.cpp` in wled00 directory. diff --git a/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp b/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp new file mode 100644 index 0000000000..fff7118f3d --- /dev/null +++ b/usermods/photoresistor_sensor_mqtt_v1/usermod.cpp @@ -0,0 +1,70 @@ +#include "wled.h" +/* + * This v1 usermod file allows you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h) + * If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE) + * + * Consider the v2 usermod API if you need a more advanced feature set! + */ + +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + +const int LIGHT_PIN = A0; // define analog pin +const long UPDATE_MS = 30000; // Upper threshold between mqtt messages +const char MQTT_TOPIC[] = "/light"; // MQTT topic for sensor values +const int CHANGE_THRESHOLD = 5; // Change threshold in percentage to send before UPDATE_MS + +// variables +long lastTime = 0; +long timeDiff = 0; +long readTime = 0; +int lightValue = 0; +float lightPercentage = 0; +float lastPercentage = 0; + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() +{ + pinMode(LIGHT_PIN, INPUT); +} + +//gets called every time WiFi is (re-)connected. Initialize own network interfaces here +void userConnected() +{ + +} + +void publishMqtt(float state) +{ + //Check if MQTT Connected, otherwise it will crash the 8266 + if (mqtt != nullptr){ + char subuf[38]; + strcpy(subuf, mqttDeviceTopic); + strcat(subuf, MQTT_TOPIC); + mqtt->publish(subuf, 0, true, String(state).c_str()); + } +} + +//loop. You can use "if (WLED_CONNECTED)" to check for successful connection +void userLoop() +{ + // Read only every 500ms, otherwise it causes the board to hang + if (millis() - readTime > 500) + { + readTime = millis(); + timeDiff = millis() - lastTime; + + // Convert value to percentage + lightValue = analogRead(LIGHT_PIN); + lightPercentage = ((float)lightValue * -1 + 1024)/(float)1024 *100; + + // Send MQTT message on significant change or after UPDATE_MS + if (abs(lightPercentage - lastPercentage) > CHANGE_THRESHOLD || timeDiff > UPDATE_MS) + { + publishMqtt(lightPercentage); + lastTime = millis(); + lastPercentage = lightPercentage; + } + } +} From 51a7c2adc53cbb88022b974eebfa3e479c810bd1 Mon Sep 17 00:00:00 2001 From: Caleb Mah Date: Thu, 16 Jul 2020 23:32:23 +0800 Subject: [PATCH 02/19] PIR sensor usermod --- usermods/PIR_sensor_mqtt_v1/README.md | 9 +++++ usermods/PIR_sensor_mqtt_v1/usermod.cpp | 53 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 usermods/PIR_sensor_mqtt_v1/README.md create mode 100644 usermods/PIR_sensor_mqtt_v1/usermod.cpp diff --git a/usermods/PIR_sensor_mqtt_v1/README.md b/usermods/PIR_sensor_mqtt_v1/README.md new file mode 100644 index 0000000000..475c11b025 --- /dev/null +++ b/usermods/PIR_sensor_mqtt_v1/README.md @@ -0,0 +1,9 @@ +# PIR sensor with MQTT + +This simple usermod allows attaching a PIR sensor like the AM312 and publish the readings over MQTT. A message is sent when motion is detected as well as when motion has stopped. + +This usermod has only been tested with the AM312 sensor though should work for any other PIR sensor. Note that this does not control the LED strip directly, it only publishes MQTT readings for use with other integrations like Home Assistant. + +## Installation + +Copy and replace the file `usermod.cpp` in wled00 directory. diff --git a/usermods/PIR_sensor_mqtt_v1/usermod.cpp b/usermods/PIR_sensor_mqtt_v1/usermod.cpp new file mode 100644 index 0000000000..117b7c7142 --- /dev/null +++ b/usermods/PIR_sensor_mqtt_v1/usermod.cpp @@ -0,0 +1,53 @@ +#include "wled.h" +/* + * This v1 usermod file allows you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h) + * If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE) + * + * Consider the v2 usermod API if you need a more advanced feature set! + */ + +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + +// PIR sensor pin +const int MOTION_PIN = 16; + +int prevState = LOW; + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() +{ + pinMode(MOTION_PIN, INPUT); +} + +//gets called every time WiFi is (re-)connected. Initialize own network interfaces here +void userConnected() +{ + +} + +void publishMqtt(String state) +{ + //Check if MQTT Connected, otherwise it will crash the 8266 + if (mqtt != nullptr){ + char subuf[38]; + strcpy(subuf, mqttDeviceTopic); + strcat(subuf, "/kitchen_motion"); + mqtt->publish(subuf, 0, true, state.c_str()); + } +} + +//loop. You can use "if (WLED_CONNECTED)" to check for successful connection +void userLoop() +{ + if (digitalRead(MOTION_PIN) == HIGH && prevState == LOW) { // Motion detected + publishMqtt("ON"); + prevState = HIGH; + } + if (digitalRead(MOTION_PIN) == LOW && prevState == HIGH) { // Motion stopped + publishMqtt("OFF"); + prevState = LOW; + } +} + From 432755e05dad52d952c46afbae4fc2cba46372f5 Mon Sep 17 00:00:00 2001 From: Caleb Mah Date: Fri, 17 Jul 2020 00:54:52 +0800 Subject: [PATCH 03/19] Use MQTT_TOPIC --- usermods/PIR_sensor_mqtt_v1/usermod.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usermods/PIR_sensor_mqtt_v1/usermod.cpp b/usermods/PIR_sensor_mqtt_v1/usermod.cpp index 117b7c7142..426a80332b 100644 --- a/usermods/PIR_sensor_mqtt_v1/usermod.cpp +++ b/usermods/PIR_sensor_mqtt_v1/usermod.cpp @@ -12,6 +12,8 @@ // PIR sensor pin const int MOTION_PIN = 16; + // MQTT topic for sensor values +const char MQTT_TOPIC[] = "/motion"; int prevState = LOW; @@ -33,7 +35,7 @@ void publishMqtt(String state) if (mqtt != nullptr){ char subuf[38]; strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/kitchen_motion"); + strcat(subuf, MQTT_TOPIC); mqtt->publish(subuf, 0, true, state.c_str()); } } From ec6a243e3e8ec793c23f845559c41ba0378fb1c2 Mon Sep 17 00:00:00 2001 From: Aircoookie Date: Sun, 19 Jul 2020 16:24:26 +0200 Subject: [PATCH 04/19] Hostname alphanumeric (#1048) * Use string derived from serverDescription for wifi.hostname() The code was sending illegal hostname strings to WiFi.hostname() (which is then submitted to DHCP and often times to DNS.) A valid hostname contains only alphanumeric characters and hyphens (though it can't start with a hypen.) This change simply alters the value passed to wifi.hostname() by replacing all non alphanum chars with hyphens while ensuring the first char is never a hyphen. If the resulting hostname is empty, it uses the escapedMac value (which I'm assuming is initialized by the time this code executes.) This change would result issue #1033 * replace string with char array prefix wled improve documentation Co-authored-by: garyd9 Co-authored-by: Gary Dezern --- CHANGELOG.md | 4 +++- wled00/FX_fcn.cpp | 11 +++++++++++ wled00/wled.cpp | 30 ++++++++++++++++++++++++++++-- wled00/wled.h | 2 +- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63271ad2d8..b02aef1f05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ### Development versions after 0.10.0 release -#### Build 2007020 +#### Build 2007190 + +- Fixed hostname containing illegal characters (#1035) #### Build 2006251 diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 399df185b0..a1b4096cb1 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -801,6 +801,16 @@ void WS2812FX::handle_palette(void) } } + +/* + * Gets a single color from the currently selected palette. + * @param i Palette Index (if mapping is true, the full palette will be SEGLEN long, if false, 255). Will wrap around automatically. + * @param mapping if true, LED position in segment is considered for color + * @param wrap FastLED palettes will usally wrap back to the start smoothly. Set false to get a hard edge + * @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead + * @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling) + * @returns Single color from palette + */ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) { if (SEGMENT.palette == 0 && mcol < 3) return SEGCOLOR(mcol); //WS2812FX default @@ -812,6 +822,7 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8 return fastled_col.r*65536 + fastled_col.g*256 + fastled_col.b; } +//@returns `true` if color, mode, speed, intensity and palette match bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b) { //if (a->start != b->start) return false; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 594c92252a..5869865497 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -324,15 +324,41 @@ void WLED::initConnection() DEBUG_PRINT(clientSSID); DEBUG_PRINTLN("..."); + // convert the "serverDescription" into a valid DNS hostname (alphanumeric) + char hostname[25] = "wled-"; + const char *pC = serverDescription; + uint8_t pos = 5; + + while (*pC && pos < 24) { // while !null and not over length + if (isalnum(*pC)) { // if the current char is alpha-numeric append it to the hostname + hostname[pos] = *pC; + pos++; + } else if (*pC == ' ' || *pC == '_' || *pC == '-' || *pC == '+' || *pC == '!' || *pC == '?' || *pC == '*') { + hostname[pos] = '-'; + pos++; + } + // else do nothing - no leading hyphens and do not include hyphens for all other characters. + pC++; + } + // if the hostname is left blank, use the mac address/default mdns name + if (pos < 6) { + sprintf(hostname + 5, "%*s", 6, escapedMac.c_str() + 6); + } else { //last character must not be hyphen + while (pos > 0 && hostname[pos -1] == '-') { + hostname[pos -1] = 0; + pos--; + } + } + #ifdef ESP8266 - WiFi.hostname(serverDescription); + WiFi.hostname(hostname); #endif WiFi.begin(clientSSID, clientPass); #ifdef ARDUINO_ARCH_ESP32 WiFi.setSleep(!noWifiSleep); - WiFi.setHostname(serverDescription); + WiFi.setHostname(hostname); #else wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T); #endif diff --git a/wled00/wled.h b/wled00/wled.h index fda93b52fd..fbe6ab0161 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2007020 +#define VERSION 2007190 // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS). From 0ca6535345f458c31bc479d4e2cf84a09eb0aaaf Mon Sep 17 00:00:00 2001 From: garyd9 Date: Fri, 24 Jul 2020 23:33:50 -0400 Subject: [PATCH 05/19] Fix for power on (T=1) resetting brightness. In particular, if parsing T=1, and the brightness is already non-0, don't do anything. Resolves presets set from macros don't restore brightness #1063 --- wled00/set.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/set.cpp b/wled00/set.cpp index afc152ac50..66dbb753e2 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -637,8 +637,8 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) nightlightActive = false; //always disable nightlight when toggling switch (getNumVal(&req, pos)) { - case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off - case 1: bri = briLast; break; //on + case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off, only if it was previously on + case 1: if (bri == 0) bri = briLast; break; //on, only if it was previously off default: toggleOnOff(); //toggle } } From 35098c474cecaff316bccab7e6bf925a03ef8fbe Mon Sep 17 00:00:00 2001 From: juanesf Date: Mon, 27 Jul 2020 00:32:32 -0400 Subject: [PATCH 06/19] Update readme.md - add link to Hyperion.NG - add link to WLED App (Android & iOS) --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index fa1446b234..6063bc8b53 100644 --- a/readme.md +++ b/readme.md @@ -27,12 +27,12 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control - Configurable Auto Brightness limit for safer operation ## 💡 Supported light control interfaces -- WLED app for Android and iOS +- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033) - JSON and HTTP request APIs - MQTT - Blynk IoT - E1.31 -- Hyperion +- [Hyperion](https://github.com/hyperion-project/hyperion.ng) - UDP realtime - Alexa voice control (including dimming and color) - Sync to Philips hue lights From 3a4f4c8c3431062c09067aa9eafe67341c74ec50 Mon Sep 17 00:00:00 2001 From: Ted Schundler Date: Sun, 2 Aug 2020 17:48:47 -0700 Subject: [PATCH 07/19] Fix multi-universe ArtNet output The existing code was very buggy - a 512 channel ArtNet packet sent data to 171 LEDs, not 170. Also the second ArtNet universe was off-by-one. The math was very confusing with so many branches. The reduces the amount of code and amount of branching. Tested with Resolume + my own ArtNet software + 252 LEDs for ArtNet. Tested with LedFx for e1.31 --- wled00/data/settings_sync.htm | 6 +-- wled00/e131.cpp | 75 ++++++++++++----------------------- 2 files changed, 29 insertions(+), 52 deletions(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 42b493fae8..7c13650e93 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -2,7 +2,7 @@ Sync Settings +
@@ -48,9 +51,9 @@

Imma firin ma lazer (if it has DMX support)