Add Rule and Scripter xdrv sensor polling

This commit is contained in:
Theo Arends 2024-08-11 17:47:01 +02:00
parent d3f6d7d844
commit cc2ea328d5
10 changed files with 106 additions and 51 deletions

View File

@ -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<x>` to enabled/disable data validation/connection statistics (#21850)
- Analog GPIO ``ADC Input`` with ``AdcParam<x> 1,<start_range>,<end_range>,<margin>,1`` provide direct light control
- Analog GPIO ``ADC Voltage`` with ``AdcParam<x> 11,<start_range>,<end_range>,<lowest_voltage>,<highest_voltage>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Current`` with ``AdcParam<x> 12,<start_range>,<end_range>,<lowest_current>,<highest_current>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Input`` with ``AdcGpio<pin> <start_range>,<end_range>,<margin>,1`` provide direct light control
- Analog GPIO ``ADC Voltage`` with ``AdcGpio<pin> <start_range>,<end_range>,<lowest_voltage>,<highest_voltage>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Current`` with ``AdcGpio<pin> <start_range>,<end_range>,<lowest_current>,<highest_current>`` 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<gpio> <parameters>`` 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)

View File

@ -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<x> 1,<start_range>,<end_range>,<margin>,1`` provide direct light control
- Analog GPIO ``ADC Voltage`` with ``AdcParam<x> 11,<start_range>,<end_range>,<lowest_voltage>,<highest_voltage>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Current`` with ``AdcParam<x> 12,<start_range>,<end_range>,<lowest_current>,<highest_current>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Input`` with ``AdcGpio<pin> <start_range>,<end_range>,<margin>,1`` provide direct light control
- Analog GPIO ``ADC Voltage`` with ``AdcGpio<pin> <start_range>,<end_range>,<lowest_voltage>,<highest_voltage>`` provide energy monitoring with dc voltage
- Analog GPIO ``ADC Current`` with ``AdcGpio<pin> <start_range>,<end_range>,<lowest_current>,<highest_current>`` 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

View File

@ -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

View File

@ -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
\*********************************************************************************************/

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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());
}

View File

@ -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;

View File

@ -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;
bool XsnsNextCallJsonAppend(void) {
static int xsns_index = -1;
if (0 == xsns_present) { return false; }
xsns_index++;
if (xsns_index == xsns_present) {
xsns_index = -1;
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
while (!XsnsEnabled(0, 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);
}
xsns_func_ptr[xsns_index](FUNC_JSON_APPEND);
return true;
}
bool XsnsCall(uint32_t function) {