diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d675bef..061aad82a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,16 @@ All notable changes to this project will be documented in this file. - Matter support for split lights (`SetOption68 1` and `SetOption37 128`) (#21834) - Berry `webserver_async` (#21836) - NeoPool command `NPSetOption` to enabled/disable data validation/connection statistics (#21850) -- Analog GPIO ``ADC Input`` with ``AdcParam 1,,,,1`` provide direct light control -- Analog GPIO ``ADC Voltage`` with ``AdcParam 11,,,,`` provide energy monitoring with dc voltage -- Analog GPIO ``ADC Current`` with ``AdcParam 12,,,,`` provide energy monitoring with dc voltage +- Analog GPIO ``ADC Input`` with ``AdcGpio ,,,1`` provide direct light control +- Analog GPIO ``ADC Voltage`` with ``AdcGpio ,,,`` provide energy monitoring with dc voltage +- Analog GPIO ``ADC Current`` with ``AdcGpio ,,,`` provide energy monitoring with dc voltage - Berry new type "addr" to ctypes mapping (#21883) - Berry `file.savecode()` (#21884) - Berry `solidify.nocompact()` and reduce size of Matter UI (#21885) - Berry `zigbee.find()` (#21889) - Berry `zigbee.started()` (#21895) - Command ``AdcGpio `` to better support ADC configuration +- Rule and Scripter xdrv sensor polling ### Breaking Changed - Berry `energy` module support for 8 phases and move to pseudo-arrays (#21887) @@ -31,6 +32,7 @@ All notable changes to this project will be documented in this file. - ESP32 Framework (Arduino Core) from v3.0.2 to v3.0.4 (#21893) - Refactored Analog driver to better support multiple channels - Zigbee loads device data early before MCU startup (#21917) +- Rule and Scripter sensor polling ### Fixed - Berry `light.get` for separate RGB/CT (#21818) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 00ef59a13..067827860 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -127,9 +127,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - Support for Sonoff iFan04-H using template [#16402](https://github.com/arendst/Tasmota/issues/16402) - Support for Sonoff POWCT Ring [#21131](https://github.com/arendst/Tasmota/issues/21131) - Support for Wooliis Hall Effect Coulometer or Battery capacity monitor [#21732](https://github.com/arendst/Tasmota/issues/21732) -- Analog GPIO ``ADC Input`` with ``AdcParam 1,,,,1`` provide direct light control -- Analog GPIO ``ADC Voltage`` with ``AdcParam 11,,,,`` provide energy monitoring with dc voltage -- Analog GPIO ``ADC Current`` with ``AdcParam 12,,,,`` provide energy monitoring with dc voltage +- Analog GPIO ``ADC Input`` with ``AdcGpio ,,,1`` provide direct light control +- Analog GPIO ``ADC Voltage`` with ``AdcGpio ,,,`` provide energy monitoring with dc voltage +- Analog GPIO ``ADC Current`` with ``AdcGpio ,,,`` provide energy monitoring with dc voltage +- Rule and Scripter xdrv sensor polling - Skip MQTT response if command is prefixed with underscore [#21740](https://github.com/arendst/Tasmota/issues/21740) - Skip MQTT response if commands are executed prefixed with ``Backlog2`` (no delay) or ``Backlog3`` [#21740](https://github.com/arendst/Tasmota/issues/21740) - Extend command ``SetOption147 1`` to disable publish of IRReceived MQTT messages [#21574](https://github.com/arendst/Tasmota/issues/21574) @@ -171,6 +172,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm - ESP8266 Framework (Arduino Core) from v2.7.6 to v2.7.7 [#21668](https://github.com/arendst/Tasmota/issues/21668) - ESP32 platform update from 2024.05.13 to 2024.08.10 [#21893](https://github.com/arendst/Tasmota/issues/21893) - ESP32 Framework (Arduino Core) from v3.0.0 to v3.0.4 [#21893](https://github.com/arendst/Tasmota/issues/21893) +- Rule and Scripter sensor polling - Refactored Analog driver to better support multiple channels - Optional MQTT_TELE_RETAIN to Energy Margins message replaced by ``SensorRetain`` - Display timing splash screen with display modes 1 to 5 diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index 06a2c9dd3..31f6ce7c8 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -80,7 +80,7 @@ const uint8_t MAX_DOMOTICZ_SNS_IDX = 12; // Max number of Domoticz sensors in const uint8_t MAX_KNX_GA = 10; // Max number of KNX Group Addresses to read that can be set const uint8_t MAX_KNX_CB = 10; // Max number of KNX Group Addresses to write that can be set const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy drivers -const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers +const uint8_t MAX_XDRV_DRIVERS = 128; // Max number of allowed driver drivers const uint8_t MAX_XSNS_DRIVERS = 128; // Max number of allowed sensor drivers const uint8_t MAX_I2C_DRIVERS = 96; // Max number of allowed i2c drivers const uint8_t MAX_SHUTTERS = 4; // Max number of shutters diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index d3908029a..0c533d52c 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -1416,6 +1416,44 @@ bool ResponseContains_P(const char* needle) { return (strstr_P(ResponseData(), needle) != nullptr); } +bool GetNextSensor(void) { + static uint32_t start_time = 0; + static uint8_t sensor_set = 0; + + ResponseClear(); + int tele_period_save = TasmotaGlobal.tele_period; + TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call + while (!ResponseLength()) { + if (0 == sensor_set) { + if (TimeReached(start_time)) { + SetNextTimeInterval(start_time, 1000); + sensor_set++; // Minimal loop time is 1 second + } + break; + } + else if (1 == sensor_set) { + if (!XsnsNextCallJsonAppend()) { // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + sensor_set++; // Looped + break; + } + } + else { + if (!XdrvNextCallJsonAppend()) { // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + sensor_set = 0; // Looped + break; + } + } + } +// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("DBG: GetNextSensor %d, %d"), sensor_set, ResponseLength()); + TasmotaGlobal.tele_period = tele_period_save; + if (ResponseLength()) { + ResponseJsonStart(); // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + ResponseJsonEnd(); + return true; + } + return false; +} + /*********************************************************************************************\ * GPIO Module and Template management \*********************************************************************************************/ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino index 392cbd690..38f063d72 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_rules.ino @@ -1093,16 +1093,8 @@ void RulesEvery50ms(void) } void RulesEvery100ms(void) { - static uint8_t xsns_index = 0; if ((Settings->rule_enabled || BERRY_RULES) && !Rules.busy && (TasmotaGlobal.uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) - ResponseClear(); - int tele_period_save = TasmotaGlobal.tele_period; - TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call - XsnsNextCall(FUNC_JSON_APPEND, xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - TasmotaGlobal.tele_period = tele_period_save; - if (ResponseLength()) { - ResponseJsonStart(); // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - ResponseJsonEnd(); + if (GetNextSensor()) { RulesProcessEvent(ResponseData()); } } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index eb8714737..ad5789b9d 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -8823,21 +8823,13 @@ bool Is_gpio_used(uint8_t gpiopin) { } void ScripterEvery100ms(void) { - static uint8_t xsns_index = 0; - if (bitRead(Settings->rule_enabled, 0) && (TasmotaGlobal.uptime > 4)) { - ResponseClear(); - uint16_t script_tele_period_save = TasmotaGlobal.tele_period; - TasmotaGlobal.tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, xsns_index); - TasmotaGlobal.tele_period = script_tele_period_save; - if (ResponseLength()) { - ResponseJsonStart(); - ResponseJsonEnd(); + if (GetNextSensor()) { //Run_Scripter(">T", 2, ResponseData()); if (glob_script_mem.teleperiod) Run_Scripter(glob_script_mem.teleperiod, 0, ResponseData()); } } + if (bitRead(Settings->rule_enabled, 0)) { if (glob_script_mem.fast_script) Run_Scripter1(glob_script_mem.fast_script, 0, 0); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino index 4e637adc4..d0a2adec7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_12_home_assistant.ino @@ -958,13 +958,13 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const void HAssAnnounceSensors(void) { - uint8_t hass_xsns_index = 0; + bool hass_xsns_index = true; do { ResponseClear(); int tele_period_save = TasmotaGlobal.tele_period; TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call - XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + hass_xsns_index = XsnsNextCallJsonAppend(); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} TasmotaGlobal.tele_period = tele_period_save; size_t sensordata_len = ResponseLength(); char sensordata[sensordata_len+2]; // dynamically adjust the size diff --git a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino index 8c0151232..545040ef9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino @@ -1443,17 +1443,7 @@ void DisplayDTVarsTeleperiod(void) { } void get_dt_mqtt(void) { - static uint8_t xsns_index = 0; - - ResponseClear(); - uint16_t script_tele_period_save = TasmotaGlobal.tele_period; - TasmotaGlobal.tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, xsns_index); - TasmotaGlobal.tele_period = script_tele_period_save; - if (ResponseLength()) { - ResponseJsonStart(); - ResponseJsonEnd(); - } + GetNextSensor(); get_dt_vars(ResponseData()); } diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index 464a345ae..3a4b47210 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1065,6 +1065,18 @@ const uint8_t kXdrvList[] = { uint32_t Xdrv_active[4] = { 0 }; +bool XdrvActive(uint32_t drv_index) { + if (drv_index < sizeof(kXdrvList)) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t index = pgm_read_byte(kXdrvList + drv_index); +#else + uint32_t index = kXdrvList[drv_index]; +#endif + return bitRead(Xdrv_active[index / 32], index % 32); + } + return true; +} + void XsnsDriverState(void) { ResponseAppend_P(PSTR(",\"Drivers\":\"")); // Use string for future enable/disable signal for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { @@ -1130,6 +1142,28 @@ bool XdrvCallDriver(uint32_t driver, uint32_t function) { * Function call to all xdrv \*********************************************************************************************/ +bool XdrvNextCallJsonAppend(void) { + static int xdrv_index = -1; + + if (0 == xdrv_present) { return false; } + + xdrv_index++; + if (xdrv_index == xdrv_present) { + xdrv_index = -1; + return false; + } + uint32_t max_disabled = xdrv_present; + while (!XdrvActive(xdrv_index) && max_disabled--) { // Perform at least one sensor + xdrv_index++; + if (xdrv_index == xdrv_present) { + xdrv_index = -1; + return false; + } + } + xdrv_func_ptr[xdrv_index](FUNC_JSON_APPEND); + return true; +} + bool XdrvCall(uint32_t function) { bool result = false; diff --git a/tasmota/tasmota_xx2c_global/xsns_interface.ino b/tasmota/tasmota_xx2c_global/xsns_interface.ino index 3c01b39c6..8799a9264 100644 --- a/tasmota/tasmota_xx2c_global/xsns_interface.ino +++ b/tasmota/tasmota_xx2c_global/xsns_interface.ino @@ -1094,21 +1094,26 @@ void XsnsSensorState(uint32_t sensor_list) { * Function call to all xsns \*********************************************************************************************/ -bool XsnsNextCall(uint32_t function, uint8_t &xsns_index) { - if (0 == xsns_present) { - xsns_index = 0; - return false; - } +bool XsnsNextCallJsonAppend(void) { + static int xsns_index = -1; + + if (0 == xsns_present) { return false; } xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - uint32_t max_disabled = xsns_present; - while ((!XsnsEnabled(0, xsns_index) || ((FUNC_WEB_SENSOR == function) && !XsnsEnabled(1, xsns_index))) && max_disabled--) { // Perform at least one sensor - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } + if (xsns_index == xsns_present) { + xsns_index = -1; + return false; } - - return xsns_func_ptr[xsns_index](function); + uint32_t max_disabled = xsns_present; + while (!XsnsEnabled(0, xsns_index) && max_disabled--) { // Perform at least one sensor + xsns_index++; + if (xsns_index == xsns_present) { + xsns_index = -1; + return false; + } + } + xsns_func_ptr[xsns_index](FUNC_JSON_APPEND); + return true; } bool XsnsCall(uint32_t function) {