+
Check out the WLED [Discourse forum](https://wled.discourse.group)!
diff --git a/tools/cdata.js b/tools/cdata.js
index 90619ba67..4b0d15d4f 100644
--- a/tools/cdata.js
+++ b/tools/cdata.js
@@ -16,12 +16,15 @@
*/
const fs = require("fs");
+const path = require('path');
const inliner = require("inliner");
const zlib = require("zlib");
const CleanCSS = require("clean-css");
const MinifyHTML = require("html-minifier-terser").minify;
const packageJson = require("../package.json");
+const output = ["wled00/html_ui.h", "wled00/html_pixart.h", "wled00/html_cpal.h", "wled00/html_pxmagic.h", "wled00/html_settings.h", "wled00/html_other.h"]
+
/**
*
*/
@@ -182,7 +185,7 @@ ${result}
const result = hexdump(buf);
const chunk = `
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
-const uint16_t ${s.name}_length = ${result.length};
+const uint16_t ${s.name}_length = ${buf.length};
const uint8_t ${s.name}[] PROGMEM = {
${result}
};
@@ -204,12 +207,13 @@ function writeChunks(srcDir, specs, resultFile) {
*/
`;
specs.forEach((s) => {
+ const file = srcDir + "/" + s.file;
try {
- console.info("Reading " + srcDir + "/" + s.file + " as " + s.name);
+ console.info("Reading " + file + " as " + s.name);
src += specToChunk(srcDir, s);
} catch (e) {
console.warn(
- "Failed " + s.name + " from " + srcDir + "/" + s.file,
+ "Failed " + s.name + " from " + file,
e.message.length > 60 ? e.message.substring(0, 60) : e.message
);
}
@@ -218,37 +222,57 @@ function writeChunks(srcDir, specs, resultFile) {
fs.writeFileSync(resultFile, src);
}
+// Check if a file is newer than a given time
+function isFileNewerThan(filePath, time) {
+ try {
+ const stats = fs.statSync(filePath);
+ return stats.mtimeMs > time;
+ } catch (e) {
+ console.error(`Failed to get stats for file ${filePath}:`, e);
+ return false;
+ }
+}
+
+// Check if any file in a folder (or its subfolders) is newer than a given time
+function isAnyFileInFolderNewerThan(folderPath, time) {
+ const files = fs.readdirSync(folderPath, { withFileTypes: true });
+ for (const file of files) {
+ const filePath = path.join(folderPath, file.name);
+ if (isFileNewerThan(filePath, time)) {
+ return true;
+ }
+ if (file.isDirectory() && isAnyFileInFolderNewerThan(filePath, time)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function isAlreadyBuilt(folderPath) {
+ let lastBuildTime = Infinity;
+
+ for (const file of output) {
+ try {
+ lastBuildTime = Math.min(lastBuildTime, fs.statSync(file).mtimeMs);
+ }
+ catch (e) {
+ return false;
+ }
+ }
+
+ return !isAnyFileInFolderNewerThan(folderPath, lastBuildTime);
+}
+
+if (isAlreadyBuilt("wled00/data") && process.argv[2] !== '--force' && process.argv[2] !== '-f') {
+ console.info("Web UI is already built");
+ return;
+}
+
writeHtmlGzipped("wled00/data/index.htm", "wled00/html_ui.h", 'index');
-writeHtmlGzipped("wled00/data/simple.htm", "wled00/html_simple.h", 'simple');
writeHtmlGzipped("wled00/data/pixart/pixart.htm", "wled00/html_pixart.h", 'pixart');
writeHtmlGzipped("wled00/data/cpal/cpal.htm", "wled00/html_cpal.h", 'cpal');
writeHtmlGzipped("wled00/data/pxmagic/pxmagic.htm", "wled00/html_pxmagic.h", 'pxmagic');
-/*
-writeChunks(
- "wled00/data",
- [
- {
- file: "simple.css",
- name: "PAGE_simpleCss",
- method: "gzip",
- filter: "css-minify",
- },
- {
- file: "simple.js",
- name: "PAGE_simpleJs",
- method: "gzip",
- filter: "js-minify",
- },
- {
- file: "simple.htm",
- name: "PAGE_simple",
- method: "gzip",
- filter: "html-minify-ui",
- }
- ],
- "wled00/html_simplex.h"
-);
-*/
+
writeChunks(
"wled00/data",
[
@@ -406,16 +430,6 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
file: "favicon.ico",
name: "favicon",
method: "binary",
- },
- {
- file: "iro.js",
- name: "iroJs",
- method: "gzip"
- },
- {
- file: "rangetouch.js",
- name: "rangetouchJs",
- method: "gzip"
}
],
"wled00/html_other.h"
diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h
index 151cf1d4a..147497211 100644
--- a/usermods/Animated_Staircase/Animated_Staircase.h
+++ b/usermods/Animated_Staircase/Animated_Staircase.h
@@ -25,6 +25,7 @@ class Animated_Staircase : public Usermod {
bool useUSSensorBottom = false; // using PIR or UltraSound sensor?
unsigned int topMaxDist = 50; // default maximum measured distance in cm, top
unsigned int bottomMaxDist = 50; // default maximum measured distance in cm, bottom
+ bool togglePower = false; // toggle power on/off with staircase on/off
/* runtime variables */
bool initDone = false;
@@ -90,7 +91,8 @@ class Animated_Staircase : public Usermod {
static const char _bottomEcho_pin[];
static const char _topEchoCm[];
static const char _bottomEchoCm[];
-
+ static const char _togglePower[];
+
void publishMqtt(bool bottom, const char* state) {
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
@@ -196,6 +198,7 @@ class Animated_Staircase : public Usermod {
if (on) {
lastSensor = topSensorRead;
} else {
+ if (togglePower && onIndex == offIndex && offMode) toggleOnOff(); // toggle power on if off
// If the bottom sensor triggered, we need to swipe up, ON
swipe = bottomSensorRead;
@@ -249,7 +252,10 @@ class Animated_Staircase : public Usermod {
offIndex = MAX(onIndex, offIndex - 1);
}
}
- if (oldOn != onIndex || oldOff != offIndex) updateSegments(); // reduce the number of updates to necessary ones
+ if (oldOn != onIndex || oldOff != offIndex) {
+ updateSegments(); // reduce the number of updates to necessary ones
+ if (togglePower && onIndex == offIndex && !offMode && !on) toggleOnOff(); // toggle power off for all segments off
+ }
}
}
@@ -291,10 +297,11 @@ class Animated_Staircase : public Usermod {
offIndex = maxSegmentId = strip.getLastActiveSegmentId() + 1;
// shorten the strip transition time to be equal or shorter than segment delay
- transitionDelayTemp = transitionDelay = segment_delay_ms;
- strip.setTransition(segment_delay_ms/100);
+ transitionDelay = segment_delay_ms;
+ strip.setTransition(segment_delay_ms);
strip.trigger();
} else {
+ if (togglePower && !on && offMode) toggleOnOff(); // toggle power on if off
// Restore segment options
for (int i = 0; i <= strip.getLastActiveSegmentId(); i++) {
Segment &seg = strip.getSegment(i);
@@ -444,6 +451,7 @@ class Animated_Staircase : public Usermod {
staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1;
staircase[FPSTR(_topEchoCm)] = topMaxDist;
staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist;
+ staircase[FPSTR(_togglePower)] = togglePower;
DEBUG_PRINTLN(F("Staircase config saved."));
}
@@ -488,6 +496,8 @@ class Animated_Staircase : public Usermod {
bottomMaxDist = top[FPSTR(_bottomEchoCm)] | bottomMaxDist;
bottomMaxDist = min(150,max(30,(int)bottomMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected)
+ togglePower = top[FPSTR(_togglePower)] | togglePower; // staircase toggles power on/off
+
DEBUG_PRINT(FPSTR(_name));
if (!initDone) {
// first run: reading from cfg.json
@@ -511,7 +521,7 @@ class Animated_Staircase : public Usermod {
if (changed) setup();
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
- return true;
+ return !top[FPSTR(_togglePower)].isNull();
}
/*
@@ -551,3 +561,4 @@ const char Animated_Staircase::_bottomPIRorTrigger_pin[] PROGMEM = "bottomPIR
const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin";
const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm";
const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm";
+const char Animated_Staircase::_togglePower[] PROGMEM = "toggle-on-off";
diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h
index 43648b588..910e0cae2 100644
--- a/usermods/EXAMPLE_v2/usermod_v2_example.h
+++ b/usermods/EXAMPLE_v2/usermod_v2_example.h
@@ -87,7 +87,7 @@ class MyExampleUsermod : public Usermod {
* readFromConfig() is called prior to setup()
* You can use it to initialize variables, sensors or similar.
*/
- void setup() {
+ void setup() override {
// do your set-up here
//Serial.println("Hello from my usermod!");
initDone = true;
@@ -98,7 +98,7 @@ class MyExampleUsermod : public Usermod {
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
- void connected() {
+ void connected() override {
//Serial.println("Connected to WiFi!");
}
@@ -113,7 +113,7 @@ class MyExampleUsermod : public Usermod {
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
- void loop() {
+ void loop() override {
// if usermod is disabled or called during strip updating just exit
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
if (!enabled || strip.isUpdating()) return;
@@ -131,7 +131,7 @@ class MyExampleUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
- void addToJsonInfo(JsonObject& root)
+ void addToJsonInfo(JsonObject& root) override
{
// if "u" object does not exist yet wee need to create it
JsonObject user = root["u"];
@@ -156,7 +156,7 @@ class MyExampleUsermod : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void addToJsonState(JsonObject& root)
+ void addToJsonState(JsonObject& root) override
{
if (!initDone || !enabled) return; // prevent crash on boot applyPreset()
@@ -171,7 +171,7 @@ class MyExampleUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void readFromJsonState(JsonObject& root)
+ void readFromJsonState(JsonObject& root) override
{
if (!initDone) return; // prevent crash on boot applyPreset()
@@ -220,7 +220,7 @@ class MyExampleUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
- void addToConfig(JsonObject& root)
+ void addToConfig(JsonObject& root) override
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
@@ -253,7 +253,7 @@ class MyExampleUsermod : public Usermod {
*
* This function is guaranteed to be called on boot, but could also be called every time settings are updated
*/
- bool readFromConfig(JsonObject& root)
+ bool readFromConfig(JsonObject& root) override
{
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
@@ -285,7 +285,7 @@ class MyExampleUsermod : public Usermod {
* it may add additional metadata for certain entry fields (adding drop down is possible)
* be careful not to add too much as oappend() buffer is limited to 3k
*/
- void appendConfigData()
+ void appendConfigData() override
{
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'(this is a great config value)');"));
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
@@ -300,7 +300,7 @@ class MyExampleUsermod : public Usermod {
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
* Commonly used for custom clocks (Cronixie, 7 segment)
*/
- void handleOverlayDraw()
+ void handleOverlayDraw() override
{
//strip.setPixelColor(0, RGBW32(0,0,0,0)) // set the first pixel to black
}
@@ -311,7 +311,7 @@ class MyExampleUsermod : public Usermod {
* will prevent button working in a default way.
* Replicating button.cpp
*/
- bool handleButton(uint8_t b) {
+ bool handleButton(uint8_t b) override {
yield();
// ignore certain button types as they may have other consequences
if (!enabled
@@ -334,7 +334,7 @@ class MyExampleUsermod : public Usermod {
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
*/
- bool onMqttMessage(char* topic, char* payload) {
+ bool onMqttMessage(char* topic, char* payload) override {
// check if we received a command
//if (strlen(topic) == 8 && strncmp_P(topic, PSTR("/command"), 8) == 0) {
// String action = payload;
@@ -355,7 +355,7 @@ class MyExampleUsermod : public Usermod {
/**
* onMqttConnect() is called when MQTT connection is established
*/
- void onMqttConnect(bool sessionPresent) {
+ void onMqttConnect(bool sessionPresent) override {
// do any MQTT related initialisation here
//publishMqtt("I am alive!");
}
@@ -366,7 +366,7 @@ class MyExampleUsermod : public Usermod {
* onStateChanged() is used to detect WLED state change
* @mode parameter is CALL_MODE_... parameter used for notifications
*/
- void onStateChange(uint8_t mode) {
+ void onStateChange(uint8_t mode) override {
// do something if WLED state changed (color, brightness, effect, preset, etc)
}
@@ -375,7 +375,7 @@ class MyExampleUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
- uint16_t getId()
+ uint16_t getId() override
{
return USERMOD_ID_EXAMPLE;
}
diff --git a/usermods/Internal_Temperature_v2/readme.md b/usermods/Internal_Temperature_v2/readme.md
new file mode 100644
index 000000000..58a9e1939
--- /dev/null
+++ b/usermods/Internal_Temperature_v2/readme.md
@@ -0,0 +1,17 @@
+# Internal Temperature Usermod
+This usermod adds the temperature readout to the Info tab and also publishes that over the topic `mcutemp` topic.
+
+## Important
+A shown temp of 53,33°C might indicate that the internal temp is not supported.
+
+ESP8266 does not have a internal temp sensor
+
+ESP32S2 seems to crash on reading the sensor -> disabled
+
+## Installation
+Add a build flag `-D USERMOD_INTERNAL_TEMPERATURE` to your `platformio.ini` (or `platformio_override.ini`).
+
+## Authors
+Soeren Willrodt [@lost-hope](https://github.com/lost-hope)
+
+Dimitry Zhemkov [@dima-zhemkov](https://github.com/dima-zhemkov)
\ No newline at end of file
diff --git a/usermods/Internal_Temperature_v2/usermod_internal_temperature.h b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
new file mode 100644
index 000000000..180176a2f
--- /dev/null
+++ b/usermods/Internal_Temperature_v2/usermod_internal_temperature.h
@@ -0,0 +1,117 @@
+#pragma once
+
+#include "wled.h"
+
+class InternalTemperatureUsermod : public Usermod
+{
+
+private:
+ unsigned long loopInterval = 10000;
+ unsigned long lastTime = 0;
+ bool isEnabled = false;
+ float temperature = 0;
+
+ static const char _name[];
+ static const char _enabled[];
+ static const char _loopInterval[];
+
+ // any private methods should go here (non-inline methosd should be defined out of class)
+ void publishMqtt(const char *state, bool retain = false); // example for publishing MQTT message
+
+public:
+ void setup()
+ {
+ }
+
+ void loop()
+ {
+ // if usermod is disabled or called during strip updating just exit
+ // NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
+ if (!isEnabled || strip.isUpdating() || millis() - lastTime <= loopInterval)
+ return;
+
+ lastTime = millis();
+
+#ifdef ESP8266 // ESP8266
+ // does not seem possible
+ temperature = -1;
+#elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32S2
+ temperature = -1;
+#else // ESP32 ESP32S3 and ESP32C3
+ temperature = roundf(temperatureRead() * 10) / 10;
+#endif
+
+#ifndef WLED_DISABLE_MQTT
+ if (WLED_MQTT_CONNECTED)
+ {
+ char array[10];
+ snprintf(array, sizeof(array), "%f", temperature);
+ publishMqtt(array);
+ }
+#endif
+ }
+
+ void addToJsonInfo(JsonObject &root)
+ {
+ if (!isEnabled)
+ return;
+
+ // if "u" object does not exist yet wee need to create it
+ JsonObject user = root["u"];
+ if (user.isNull())
+ user = root.createNestedObject("u");
+
+ JsonArray userTempArr = user.createNestedArray(FPSTR(_name));
+ userTempArr.add(temperature);
+ userTempArr.add(F(" °C"));
+
+ // if "sensor" object does not exist yet wee need to create it
+ JsonObject sensor = root[F("sensor")];
+ if (sensor.isNull())
+ sensor = root.createNestedObject(F("sensor"));
+
+ JsonArray sensorTempArr = sensor.createNestedArray(FPSTR(_name));
+ sensorTempArr.add(temperature);
+ sensorTempArr.add(F("°C"));
+ }
+
+ void addToConfig(JsonObject &root)
+ {
+ JsonObject top = root.createNestedObject(FPSTR(_name));
+ top[FPSTR(_enabled)] = isEnabled;
+ top[FPSTR(_loopInterval)] = loopInterval;
+ }
+
+ bool readFromConfig(JsonObject &root)
+ {
+ JsonObject top = root[FPSTR(_name)];
+ bool configComplete = !top.isNull();
+ configComplete &= getJsonValue(top[FPSTR(_enabled)], isEnabled);
+ configComplete &= getJsonValue(top[FPSTR(_loopInterval)], loopInterval);
+
+ return configComplete;
+ }
+
+ uint16_t getId()
+ {
+ return USERMOD_ID_INTERNAL_TEMPERATURE;
+ }
+};
+
+const char InternalTemperatureUsermod::_name[] PROGMEM = "Internal Temperature";
+const char InternalTemperatureUsermod::_enabled[] PROGMEM = "Enabled";
+const char InternalTemperatureUsermod::_loopInterval[] PROGMEM = "Loop Interval";
+
+void InternalTemperatureUsermod::publishMqtt(const char *state, bool retain)
+{
+#ifndef WLED_DISABLE_MQTT
+ // Check if MQTT Connected, otherwise it will crash the 8266
+ if (WLED_MQTT_CONNECTED)
+ {
+ char subuf[64];
+ strcpy(subuf, mqttDeviceTopic);
+ strcat_P(subuf, PSTR("/mcutemp"));
+ mqtt->publish(subuf, 0, retain, state);
+ }
+#endif
+}
\ No newline at end of file
diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
index 8a4b9a608..2e909ae0e 100644
--- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
+++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
@@ -50,8 +50,7 @@ private:
volatile unsigned long offTimerStart = 0; // off timer start time
volatile bool PIRtriggered = false; // did PIR trigger?
- byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // notification mode for stateUpdated(): CALL_MODE_NO_NOTIFY or CALL_MODE_DIRECT_CHANGE
- byte sensorPinState = LOW; // current PIR sensor pin state
+ bool sensorPinState = LOW; // current PIR sensor pin state
bool initDone = false; // status of initialization
unsigned long lastLoop = 0;
@@ -70,6 +69,7 @@ private:
// Home Assistant
bool HomeAssistantDiscovery = false; // is HA discovery turned on
+ int16_t idx = -1; // Domoticz virtual switch idx
// strings to reduce flash memory usage (used more than twice)
static const char _name[];
@@ -81,8 +81,8 @@ private:
static const char _mqttOnly[];
static const char _offOnly[];
static const char _haDiscovery[];
- static const char _notify[];
static const char _override[];
+ static const char _domoticzIDX[];
/**
* check if it is daytime
@@ -94,7 +94,7 @@ private:
* switch strip on/off
*/
void switchStrip(bool switchOn);
- void publishMqtt(const char* state);
+ void publishMqtt(bool switchOn);
// Create an MQTT Binary Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
void publishHomeAssistantAutodiscovery();
@@ -117,7 +117,7 @@ public:
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
- void setup();
+ void setup() override;
/**
* connected() is called every time the WiFi is (re)connected
@@ -128,24 +128,24 @@ public:
/**
* onMqttConnect() is called when MQTT connection is established
*/
- void onMqttConnect(bool sessionPresent);
+ void onMqttConnect(bool sessionPresent) override;
/**
* loop() is called continuously. Here you can check for events, read sensors, etc.
*/
- void loop();
+ void loop() override;
/**
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
*
* Add PIR sensor state and switch off timer duration to jsoninfo
*/
- void addToJsonInfo(JsonObject &root);
+ void addToJsonInfo(JsonObject &root) override;
/**
* onStateChanged() is used to detect WLED state change
*/
- void onStateChange(uint8_t mode);
+ void onStateChange(uint8_t mode) override;
/**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
@@ -157,17 +157,17 @@ public:
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void readFromJsonState(JsonObject &root);
+ void readFromJsonState(JsonObject &root) override;
/**
* provide the changeable values
*/
- void addToConfig(JsonObject &root);
+ void addToConfig(JsonObject &root) override;
/**
* provide UI information and allow extending UI options
*/
- void appendConfigData();
+ void appendConfigData() override;
/**
* restore the changeable values
@@ -175,13 +175,13 @@ public:
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
- bool readFromConfig(JsonObject &root);
+ bool readFromConfig(JsonObject &root) override;
/**
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
- uint16_t getId() { return USERMOD_ID_PIRSWITCH; }
+ uint16_t getId() override { return USERMOD_ID_PIRSWITCH; }
};
// strings to reduce flash memory usage (used more than twice)
@@ -194,8 +194,8 @@ const char PIRsensorSwitch::_nightTime[] PROGMEM = "nighttime-only";
const char PIRsensorSwitch::_mqttOnly[] PROGMEM = "mqtt-only";
const char PIRsensorSwitch::_offOnly[] PROGMEM = "off-only";
const char PIRsensorSwitch::_haDiscovery[] PROGMEM = "HA-discovery";
-const char PIRsensorSwitch::_notify[] PROGMEM = "notifications";
const char PIRsensorSwitch::_override[] PROGMEM = "override";
+const char PIRsensorSwitch::_domoticzIDX[] PROGMEM = "domoticz-idx";
bool PIRsensorSwitch::isDayTime() {
updateLocalTime();
@@ -235,24 +235,24 @@ void PIRsensorSwitch::switchStrip(bool switchOn)
prevPlaylist = 0;
prevPreset = 255;
}
- applyPreset(m_onPreset, NotifyUpdateMode);
+ applyPreset(m_onPreset, CALL_MODE_BUTTON_PRESET);
return;
}
// preset not assigned
if (bri == 0) {
bri = briLast;
- stateUpdated(NotifyUpdateMode);
+ stateUpdated(CALL_MODE_BUTTON);
}
} else {
if (m_offPreset) {
- applyPreset(m_offPreset, NotifyUpdateMode);
+ applyPreset(m_offPreset, CALL_MODE_BUTTON_PRESET);
return;
} else if (prevPlaylist) {
- if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPlaylist, NotifyUpdateMode);
+ if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPlaylist, CALL_MODE_BUTTON_PRESET);
prevPlaylist = 0;
return;
} else if (prevPreset) {
- if (prevPreset<255) { if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPreset, NotifyUpdateMode); }
+ if (prevPreset<255) { if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyPreset(prevPreset, CALL_MODE_BUTTON_PRESET); }
else { if (currentPreset==m_onPreset || currentPlaylist==m_onPreset) applyTemporaryPreset(); }
prevPreset = 0;
return;
@@ -261,19 +261,29 @@ void PIRsensorSwitch::switchStrip(bool switchOn)
if (bri != 0) {
briLast = bri;
bri = 0;
- stateUpdated(NotifyUpdateMode);
+ stateUpdated(CALL_MODE_BUTTON);
}
}
}
-void PIRsensorSwitch::publishMqtt(const char* state)
+void PIRsensorSwitch::publishMqtt(bool switchOn)
{
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED) {
- char buf[64];
+ char buf[128];
sprintf_P(buf, PSTR("%s/motion"), mqttDeviceTopic); //max length: 33 + 7 = 40
- mqtt->publish(buf, 0, false, state);
+ mqtt->publish(buf, 0, false, switchOn?"on":"off");
+ // Domoticz formatted message
+ if (idx > 0) {
+ StaticJsonDocument <128> msg;
+ msg[F("idx")] = idx;
+ msg[F("RSSI")] = WiFi.RSSI();
+ msg[F("command")] = F("switchlight");
+ msg[F("switchcmd")] = switchOn ? F("On") : F("Off");
+ serializeJson(msg, buf, 128);
+ mqtt->publish("domoticz/in", 0, false, buf);
+ }
}
#endif
}
@@ -322,13 +332,11 @@ bool PIRsensorSwitch::updatePIRsensorState()
if (sensorPinState == HIGH) {
offTimerStart = 0;
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true);
- else if (NotifyUpdateMode != CALL_MODE_NO_NOTIFY) updateInterfaces(CALL_MODE_WS_SEND);
- publishMqtt("on");
} else {
// start switch off timer
offTimerStart = millis();
- if (NotifyUpdateMode != CALL_MODE_NO_NOTIFY) updateInterfaces(CALL_MODE_WS_SEND);
}
+ publishMqtt(sensorPinState == HIGH);
return true;
}
return false;
@@ -338,11 +346,7 @@ bool PIRsensorSwitch::handleOffTimer()
{
if (offTimerStart > 0 && millis() - offTimerStart > m_switchOffDelay) {
offTimerStart = 0;
- if (enabled == true) {
- if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()) || PIRtriggered)) switchStrip(false);
- else if (NotifyUpdateMode != CALL_MODE_NO_NOTIFY) updateInterfaces(CALL_MODE_WS_SEND);
- publishMqtt("off");
- }
+ if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()) || PIRtriggered)) switchStrip(false);
return true;
}
return false;
@@ -482,14 +486,13 @@ void PIRsensorSwitch::addToConfig(JsonObject &root)
top[FPSTR(_offOnly)] = m_offOnly;
top[FPSTR(_override)] = m_override;
top[FPSTR(_haDiscovery)] = HomeAssistantDiscovery;
- top[FPSTR(_notify)] = (NotifyUpdateMode != CALL_MODE_NO_NOTIFY);
+ top[FPSTR(_domoticzIDX)] = idx;
DEBUG_PRINTLN(F("PIR config saved."));
}
void PIRsensorSwitch::appendConfigData()
{
oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('PIRsensorSwitch:notifications',1,'Periodic WS updates');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
}
@@ -521,8 +524,7 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root)
m_offOnly = top[FPSTR(_offOnly)] | m_offOnly;
m_override = top[FPSTR(_override)] | m_override;
HomeAssistantDiscovery = top[FPSTR(_haDiscovery)] | HomeAssistantDiscovery;
-
- NotifyUpdateMode = top[FPSTR(_notify)] ? CALL_MODE_DIRECT_CHANGE : CALL_MODE_NO_NOTIFY;
+ idx = top[FPSTR(_domoticzIDX)] | idx;
if (!initDone) {
// reading config prior to setup()
@@ -549,5 +551,5 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root)
DEBUG_PRINTLN(F(" config (re)loaded."));
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
- return !top[FPSTR(_override)].isNull();
+ return !top[FPSTR(_domoticzIDX)].isNull();
}
diff --git a/usermods/PWM_fan/usermod_PWM_fan.h b/usermods/PWM_fan/usermod_PWM_fan.h
index f7fe0e10f..1b78cfd4c 100644
--- a/usermods/PWM_fan/usermod_PWM_fan.h
+++ b/usermods/PWM_fan/usermod_PWM_fan.h
@@ -52,9 +52,15 @@ class PWMFanUsermod : public Usermod {
uint8_t tachoUpdateSec = 30;
float targetTemperature = 35.0;
uint8_t minPWMValuePct = 0;
+ uint8_t maxPWMValuePct = 100;
uint8_t numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
uint8_t pwmValuePct = 0;
+ // constant values
+ static const uint8_t _pwmMaxValue = 255;
+ static const uint8_t _pwmMaxStepCount = 7;
+ float _pwmTempStepSize = 0.5f;
+
// strings to reduce flash memory usage (used more than twice)
static const char _name[];
static const char _enabled[];
@@ -63,6 +69,7 @@ class PWMFanUsermod : public Usermod {
static const char _temperature[];
static const char _tachoUpdateSec[];
static const char _minPWMValuePct[];
+ static const char _maxPWMValuePct[];
static const char _IRQperRotation[];
static const char _speed[];
static const char _lock[];
@@ -156,38 +163,32 @@ class PWMFanUsermod : public Usermod {
void setFanPWMbasedOnTemperature(void) {
float temp = getActualTemperature();
- float difftemp = temp - targetTemperature;
- // Default to run fan at full speed.
- int newPWMvalue = 255;
- int pwmStep = ((100 - minPWMValuePct) * newPWMvalue) / (7*100);
- int pwmMinimumValue = (minPWMValuePct * newPWMvalue) / 100;
+ // dividing minPercent and maxPercent into equal pwmvalue sizes
+ int pwmStepSize = ((maxPWMValuePct - minPWMValuePct) * _pwmMaxValue) / (_pwmMaxStepCount*100);
+ int pwmStep = calculatePwmStep(temp - targetTemperature);
+ // minimum based on full speed - not entered MaxPercent
+ int pwmMinimumValue = (minPWMValuePct * _pwmMaxValue) / 100;
+ updateFanSpeed(pwmMinimumValue + pwmStep*pwmStepSize);
+ }
- if ((temp == NAN) || (temp <= -100.0)) {
+ uint8_t calculatePwmStep(float diffTemp){
+ if ((diffTemp == NAN) || (diffTemp <= -100.0)) {
DEBUG_PRINTLN(F("WARNING: no temperature value available. Cannot do temperature control. Will set PWM fan to 255."));
- } else if (difftemp <= 0.0) {
- // Temperature is below target temperature. Run fan at minimum speed.
- newPWMvalue = pwmMinimumValue;
- } else if (difftemp <= 0.5) {
- newPWMvalue = pwmMinimumValue + pwmStep;
- } else if (difftemp <= 1.0) {
- newPWMvalue = pwmMinimumValue + 2*pwmStep;
- } else if (difftemp <= 1.5) {
- newPWMvalue = pwmMinimumValue + 3*pwmStep;
- } else if (difftemp <= 2.0) {
- newPWMvalue = pwmMinimumValue + 4*pwmStep;
- } else if (difftemp <= 2.5) {
- newPWMvalue = pwmMinimumValue + 5*pwmStep;
- } else if (difftemp <= 3.0) {
- newPWMvalue = pwmMinimumValue + 6*pwmStep;
+ return _pwmMaxStepCount;
}
- updateFanSpeed(newPWMvalue);
+ if(diffTemp <=0){
+ return 0;
+ }
+ int calculatedStep = (diffTemp / _pwmTempStepSize)+1;
+ // anything greater than max stepcount gets max
+ return (uint8_t)min((int)_pwmMaxStepCount,calculatedStep);
}
public:
// gets called once at boot. Do all initialization that doesn't depend on
// network here
- void setup() {
+ void setup() override {
#ifdef USERMOD_DALLASTEMPERATURE
// This Usermod requires Temperature usermod
tempUM = (UsermodTemperature*) usermods.lookup(USERMOD_ID_TEMPERATURE);
@@ -202,12 +203,12 @@ class PWMFanUsermod : public Usermod {
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
- void connected() {}
+ void connected() override {}
/*
* Da loop.
*/
- void loop() {
+ void loop() override {
if (!enabled || strip.isUpdating()) return;
unsigned long now = millis();
@@ -222,7 +223,7 @@ class PWMFanUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
- void addToJsonInfo(JsonObject& root) {
+ void addToJsonInfo(JsonObject& root) override {
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
@@ -271,7 +272,7 @@ class PWMFanUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void readFromJsonState(JsonObject& root) {
+ void readFromJsonState(JsonObject& root) override {
if (!initDone) return; // prevent crash on boot applyPreset()
JsonObject usermod = root[FPSTR(_name)];
if (!usermod.isNull()) {
@@ -304,7 +305,7 @@ class PWMFanUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
- void addToConfig(JsonObject& root) {
+ void addToConfig(JsonObject& root) override {
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
top[FPSTR(_enabled)] = enabled;
top[FPSTR(_pwmPin)] = pwmPin;
@@ -312,6 +313,7 @@ class PWMFanUsermod : public Usermod {
top[FPSTR(_tachoUpdateSec)] = tachoUpdateSec;
top[FPSTR(_temperature)] = targetTemperature;
top[FPSTR(_minPWMValuePct)] = minPWMValuePct;
+ top[FPSTR(_maxPWMValuePct)] = maxPWMValuePct;
top[FPSTR(_IRQperRotation)] = numberOfInterrupsInOneSingleRotation;
DEBUG_PRINTLN(F("Autosave config saved."));
}
@@ -326,7 +328,7 @@ class PWMFanUsermod : public Usermod {
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
- bool readFromConfig(JsonObject& root) {
+ bool readFromConfig(JsonObject& root) override {
int8_t newTachoPin = tachoPin;
int8_t newPwmPin = pwmPin;
@@ -345,6 +347,8 @@ class PWMFanUsermod : public Usermod {
targetTemperature = top[FPSTR(_temperature)] | targetTemperature;
minPWMValuePct = top[FPSTR(_minPWMValuePct)] | minPWMValuePct;
minPWMValuePct = (uint8_t) min(100,max(0,(int)minPWMValuePct)); // bounds checking
+ maxPWMValuePct = top[FPSTR(_maxPWMValuePct)] | maxPWMValuePct;
+ maxPWMValuePct = (uint8_t) min(100,max((int)minPWMValuePct,(int)maxPWMValuePct)); // bounds checking
numberOfInterrupsInOneSingleRotation = top[FPSTR(_IRQperRotation)] | numberOfInterrupsInOneSingleRotation;
numberOfInterrupsInOneSingleRotation = (uint8_t) max(1,(int)numberOfInterrupsInOneSingleRotation); // bounds checking
@@ -376,7 +380,7 @@ class PWMFanUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
- uint16_t getId() {
+ uint16_t getId() override {
return USERMOD_ID_PWM_FAN;
}
};
@@ -389,6 +393,7 @@ const char PWMFanUsermod::_pwmPin[] PROGMEM = "PWM-pin";
const char PWMFanUsermod::_temperature[] PROGMEM = "target-temp-C";
const char PWMFanUsermod::_tachoUpdateSec[] PROGMEM = "tacho-update-s";
const char PWMFanUsermod::_minPWMValuePct[] PROGMEM = "min-PWM-percent";
+const char PWMFanUsermod::_maxPWMValuePct[] PROGMEM = "max-PWM-percent";
const char PWMFanUsermod::_IRQperRotation[] PROGMEM = "IRQs-per-rotation";
const char PWMFanUsermod::_speed[] PROGMEM = "speed";
const char PWMFanUsermod::_lock[] PROGMEM = "lock";
diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.h
index 144cccbfa..281fba25d 100644
--- a/usermods/ST7789_display/ST7789_display.h
+++ b/usermods/ST7789_display/ST7789_display.h
@@ -132,7 +132,7 @@ class St7789DisplayUsermod : public Usermod {
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
- void setup()
+ void setup() override
{
PinManagerPinType spiPins[] = { { spi_mosi, true }, { spi_miso, false}, { spi_sclk, true } };
if (!pinManager.allocateMultiplePins(spiPins, 3, PinOwner::HW_SPI)) { enabled = false; return; }
@@ -162,7 +162,7 @@ class St7789DisplayUsermod : public Usermod {
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
- void connected() {
+ void connected() override {
//Serial.println("Connected to WiFi!");
}
@@ -176,7 +176,7 @@ class St7789DisplayUsermod : public Usermod {
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
- void loop() {
+ void loop() override {
char buff[LINE_BUFFER_SIZE];
// Check if we time interval for redrawing passes.
@@ -307,7 +307,7 @@ class St7789DisplayUsermod : public Usermod {
// Print estimated milliamp usage (must specify the LED type in LED prefs for this to be a reasonable estimate).
tft.print("Current: ");
tft.setTextColor(TFT_ORANGE);
- tft.print(strip.currentMilliamps);
+ tft.print(BusManager::currentMilliamps());
tft.print("mA");
}
@@ -316,7 +316,7 @@ class St7789DisplayUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
- void addToJsonInfo(JsonObject& root)
+ void addToJsonInfo(JsonObject& root) override
{
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
@@ -330,7 +330,7 @@ class St7789DisplayUsermod : public Usermod {
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void addToJsonState(JsonObject& root)
+ void addToJsonState(JsonObject& root) override
{
//root["user0"] = userVar0;
}
@@ -340,7 +340,7 @@ class St7789DisplayUsermod : public Usermod {
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
- void readFromJsonState(JsonObject& root)
+ void readFromJsonState(JsonObject& root) override
{
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
@@ -361,7 +361,7 @@ class St7789DisplayUsermod : public Usermod {
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
- void addToConfig(JsonObject& root)
+ void addToConfig(JsonObject& root) override
{
JsonObject top = root.createNestedObject("ST7789");
JsonArray pins = top.createNestedArray("pin");
@@ -373,7 +373,7 @@ class St7789DisplayUsermod : public Usermod {
}
- void appendConfigData() {
+ void appendConfigData() override {
oappend(SET_F("addInfo('ST7789:pin[]',0,'','SPI CS');"));
oappend(SET_F("addInfo('ST7789:pin[]',1,'','SPI DC');"));
oappend(SET_F("addInfo('ST7789:pin[]',2,'','SPI RST');"));
@@ -388,7 +388,7 @@ class St7789DisplayUsermod : public Usermod {
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/
- bool readFromConfig(JsonObject& root)
+ bool readFromConfig(JsonObject& root) override
{
//JsonObject top = root["top"];
//userVar0 = top["great"] | 42; //The value right of the pipe "|" is the default value in case your setting was not present in cfg.json (e.g. first boot)
@@ -400,7 +400,7 @@ class St7789DisplayUsermod : public Usermod {
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
- uint16_t getId()
+ uint16_t getId() override
{
return USERMOD_ID_ST7789_DISPLAY;
}
diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h
index a15baf878..4d4f04368 100644
--- a/usermods/Temperature/usermod_temperature.h
+++ b/usermods/Temperature/usermod_temperature.h
@@ -48,6 +48,7 @@ class UsermodTemperature : public Usermod {
bool enabled = true;
bool HApublished = false;
+ int16_t idx = -1; // Domoticz virtual sensor idx
// strings to reduce flash memory usage (used more than twice)
static const char _name[];
@@ -55,6 +56,7 @@ class UsermodTemperature : public Usermod {
static const char _readInterval[];
static const char _parasite[];
static const char _parasitePin[];
+ static const char _domoticzIDX[];
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013
float readDallas();
@@ -74,26 +76,26 @@ class UsermodTemperature : public Usermod {
inline float getTemperatureF() { return temperature * 1.8f + 32.0f; }
float getTemperature();
const char *getTemperatureUnit();
- uint16_t getId() { return USERMOD_ID_TEMPERATURE; }
+ uint16_t getId() override { return USERMOD_ID_TEMPERATURE; }
- void setup();
- void loop();
- //void connected();
+ void setup() override;
+ void loop() override;
+ //void connected() override;
#ifndef WLED_DISABLE_MQTT
- void onMqttConnect(bool sessionPresent);
+ void onMqttConnect(bool sessionPresent) override;
#endif
- //void onUpdateBegin(bool init);
+ //void onUpdateBegin(bool init) override;
- //bool handleButton(uint8_t b);
- //void handleOverlayDraw();
+ //bool handleButton(uint8_t b) override;
+ //void handleOverlayDraw() override;
- void addToJsonInfo(JsonObject& root);
- //void addToJsonState(JsonObject &root);
- //void readFromJsonState(JsonObject &root);
- void addToConfig(JsonObject &root);
- bool readFromConfig(JsonObject &root);
+ void addToJsonInfo(JsonObject& root) override;
+ //void addToJsonState(JsonObject &root) override;
+ //void readFromJsonState(JsonObject &root) override;
+ void addToConfig(JsonObject &root) override;
+ bool readFromConfig(JsonObject &root) override;
- void appendConfigData();
+ void appendConfigData() override;
};
//Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013
@@ -264,7 +266,7 @@ void UsermodTemperature::loop() {
#ifndef WLED_DISABLE_MQTT
if (WLED_MQTT_CONNECTED) {
- char subuf[64];
+ char subuf[128];
strcpy(subuf, mqttDeviceTopic);
if (temperature > -100.0f) {
// dont publish super low temperature as the graph will get messed up
@@ -274,6 +276,15 @@ void UsermodTemperature::loop() {
mqtt->publish(subuf, 0, false, String(getTemperatureC()).c_str());
strcat_P(subuf, PSTR("_f"));
mqtt->publish(subuf, 0, false, String(getTemperatureF()).c_str());
+ if (idx > 0) {
+ StaticJsonDocument <128> msg;
+ msg[F("idx")] = idx;
+ msg[F("RSSI")] = WiFi.RSSI();
+ msg[F("nvalue")] = 0;
+ msg[F("svalue")] = String(getTemperatureC());
+ serializeJson(msg, subuf, 127);
+ mqtt->publish("domoticz/in", 0, false, subuf);
+ }
} else {
// publish something else to indicate status?
}
@@ -360,6 +371,7 @@ void UsermodTemperature::addToConfig(JsonObject &root) {
top[FPSTR(_readInterval)] = readingInterval / 1000;
top[FPSTR(_parasite)] = parasite;
top[FPSTR(_parasitePin)] = parasitePin;
+ top[FPSTR(_domoticzIDX)] = idx;
DEBUG_PRINTLN(F("Temperature config saved."));
}
@@ -386,6 +398,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
readingInterval = min(120,max(10,(int)readingInterval)) * 1000; // convert to ms
parasite = top[FPSTR(_parasite)] | parasite;
parasitePin = top[FPSTR(_parasitePin)] | parasitePin;
+ idx = top[FPSTR(_domoticzIDX)] | idx;
if (!initDone) {
// first run: reading from cfg.json
@@ -406,7 +419,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
}
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
- return !top[FPSTR(_parasitePin)].isNull();
+ return !top[FPSTR(_domoticzIDX)].isNull();
}
void UsermodTemperature::appendConfigData() {
@@ -430,3 +443,4 @@ const char UsermodTemperature::_enabled[] PROGMEM = "enabled";
const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr";
const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin";
+const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx";
diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h
index 357e612c3..50555ca54 100644
--- a/usermods/audioreactive/audio_reactive.h
+++ b/usermods/audioreactive/audio_reactive.h
@@ -20,6 +20,12 @@
* ....
*/
+#if !defined(FFTTASK_PRIORITY)
+#define FFTTASK_PRIORITY 1 // standard: looptask prio
+//#define FFTTASK_PRIORITY 2 // above looptask, below asyc_tcp
+//#define FFTTASK_PRIORITY 4 // above asyc_tcp
+#endif
+
// Comment/Uncomment to toggle usb serial debugging
// #define MIC_LOGGER // MIC sampling & sound input debugging (serial plotter)
// #define FFT_SAMPLING_LOG // FFT result debugging
@@ -45,6 +51,8 @@
#define PLOT_PRINTF(x...)
#endif
+#define MAX_PALETTES 3
+
// use audio source class (ESP32 specific)
#include "audio_source.h"
constexpr i2s_port_t I2S_PORT = I2S_NUM_0; // I2S port to use (do not change !)
@@ -104,7 +112,7 @@ static float sampleAgc = 0.0f; // Smoothed AGC sample
// peak detection
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
-static uint8_t maxVol = 10; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
+static uint8_t maxVol = 31; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated)
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
@@ -173,13 +181,18 @@ static float windowWeighingFactors[samplesFFT] = {0.0f};
// Create FFT object
#ifdef UM_AUDIOREACTIVE_USE_NEW_FFT
-// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
-#define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc), and an a few other speedups
-#define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt
-#define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 50% on ESP32 (as alternative to FFT_SQRT_APPROXIMATION)
+ // lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
+ // these options actually cause slow-downs on all esp32 processors, don't use them.
+ // #define FFT_SPEED_OVER_PRECISION // enables use of reciprocals (1/x etc) - not faster on ESP32
+ // #define FFT_SQRT_APPROXIMATION // enables "quake3" style inverse sqrt - slower on ESP32
+ // Below options are forcing ArduinoFFT to use sqrtf() instead of sqrt()
+ #define sqrt(x) sqrtf(x) // little hack that reduces FFT time by 10-50% on ESP32
+ #define sqrt_internal sqrtf // see https://github.com/kosme/arduinoFFT/pull/83
#else
-// lib_deps += https://github.com/blazoncek/arduinoFFT.git
+ // around 40% slower on -S2
+ // lib_deps += https://github.com/blazoncek/arduinoFFT.git
#endif
+
#include Brightness
-