From be895fdcc0efce9c7ea0983872ffab6c02a3f8ca Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 24 May 2018 11:24:03 +0200 Subject: [PATCH 1/5] Move GetUsedInModule to support.ino Move GetUsedInModule to support.ino (#2810) --- sonoff/support.ino | 90 ++++++++++++++++++++++++++++++++++++++++++++ sonoff/webserver.ino | 90 -------------------------------------------- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 720649c9f..b5ec74df9 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -482,6 +482,96 @@ int GetStateNumber(char *state_text) return state_number; } +boolean GetUsedInModule(byte val, uint8_t *arr) +{ + int offset = 0; + + if (!val) { return false; } // None +#ifndef USE_I2C + if (GPIO_I2C_SCL == val) { return true; } + if (GPIO_I2C_SDA == val) { return true; } +#endif +#ifndef USE_SR04 + if (GPIO_SR04_TRIG == val) { return true; } + if (GPIO_SR04_ECHO == val) { return true; } +#endif +#ifndef USE_WS2812 + if (GPIO_WS2812 == val) { return true; } +#endif +#ifndef USE_IR_REMOTE + if (GPIO_IRSEND == val) { return true; } +#ifndef USE_IR_RECEIVE + if (GPIO_IRRECV == val) { return true; } +#endif +#endif +#ifndef USE_MHZ19 + if (GPIO_MHZ_TXD == val) { return true; } + if (GPIO_MHZ_RXD == val) { return true; } +#endif +#ifndef USE_PZEM004T + if (GPIO_PZEM_TX == val) { return true; } + if (GPIO_PZEM_RX == val) { return true; } +#endif +#ifndef USE_SENSEAIR + if (GPIO_SAIR_TX == val) { return true; } + if (GPIO_SAIR_RX == val) { return true; } +#endif +#ifndef USE_SPI + if (GPIO_SPI_CS == val) { return true; } + if (GPIO_SPI_DC == val) { return true; } +#endif +#ifndef USE_DISPLAY + if (GPIO_BACKLIGHT == val) { return true; } +#endif +#ifndef USE_PMS5003 + if (GPIO_PMS5003 == val) { return true; } +#endif +#ifndef USE_NOVA_SDS + if (GPIO_SDS0X1 == val) { return true; } +#endif +#ifndef USE_SERIAL_BRIDGE + if (GPIO_SBR_TX == val) { return true; } + if (GPIO_SBR_RX == val) { return true; } +#endif +#ifndef USE_SR04 + if (GPIO_SR04_TRIG == val) { return true; } + if (GPIO_SR04_ECHO == val) { return true; } +#endif +#ifndef USE_SDM120 + if (GPIO_SDM120_TX == val) { return true; } + if (GPIO_SDM120_RX == val) { return true; } +#endif +#ifndef USE_SDM630 + if (GPIO_SDM630_TX == val) { return true; } + if (GPIO_SDM630_RX == val) { return true; } +#endif + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { + offset = (GPIO_REL1_INV - GPIO_REL1); + } + if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { + offset = -(GPIO_REL1_INV - GPIO_REL1); + } + + if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { + offset = (GPIO_LED1_INV - GPIO_LED1); + } + if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { + offset = -(GPIO_LED1_INV - GPIO_LED1); + } + + if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { + offset = (GPIO_PWM1_INV - GPIO_PWM1); + } + if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { + offset = -(GPIO_PWM1_INV - GPIO_PWM1); + } + for (byte i = 0; i < MAX_GPIO_PIN; i++) { + if (arr[i] == val) { return true; } + if (arr[i] == val + offset) { return true; } + } + return false; +} + void SetSerialBaudrate(int baudrate) { Settings.baudrate = baudrate / 1200; diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 0cb4cce27..b46c5354b 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -639,96 +639,6 @@ void HandleConfiguration() ShowPage(page); } -boolean GetUsedInModule(byte val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { return false; } // None -#ifndef USE_I2C - if (GPIO_I2C_SCL == val) { return true; } - if (GPIO_I2C_SDA == val) { return true; } -#endif -#ifndef USE_SR04 - if (GPIO_SR04_TRIG == val) { return true; } - if (GPIO_SR04_ECHO == val) { return true; } -#endif -#ifndef USE_WS2812 - if (GPIO_WS2812 == val) { return true; } -#endif -#ifndef USE_IR_REMOTE - if (GPIO_IRSEND == val) { return true; } -#ifndef USE_IR_RECEIVE - if (GPIO_IRRECV == val) { return true; } -#endif -#endif -#ifndef USE_MHZ19 - if (GPIO_MHZ_TXD == val) { return true; } - if (GPIO_MHZ_RXD == val) { return true; } -#endif -#ifndef USE_PZEM004T - if (GPIO_PZEM_TX == val) { return true; } - if (GPIO_PZEM_RX == val) { return true; } -#endif -#ifndef USE_SENSEAIR - if (GPIO_SAIR_TX == val) { return true; } - if (GPIO_SAIR_RX == val) { return true; } -#endif -#ifndef USE_SPI - if (GPIO_SPI_CS == val) { return true; } - if (GPIO_SPI_DC == val) { return true; } -#endif -#ifndef USE_DISPLAY - if (GPIO_BACKLIGHT == val) { return true; } -#endif -#ifndef USE_PMS5003 - if (GPIO_PMS5003 == val) { return true; } -#endif -#ifndef USE_NOVA_SDS - if (GPIO_SDS0X1 == val) { return true; } -#endif -#ifndef USE_SERIAL_BRIDGE - if (GPIO_SBR_TX == val) { return true; } - if (GPIO_SBR_RX == val) { return true; } -#endif -#ifndef USE_SR04 - if (GPIO_SR04_TRIG == val) { return true; } - if (GPIO_SR04_ECHO == val) { return true; } -#endif -#ifndef USE_SDM120 - if (GPIO_SDM120_TX == val) { return true; } - if (GPIO_SDM120_RX == val) { return true; } -#endif -#ifndef USE_SDM630 - if (GPIO_SDM630_TX == val) { return true; } - if (GPIO_SDM630_RX == val) { return true; } -#endif - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - void HandleModuleConfiguration() { if (HttpUser()) { return; } From ca08b77aad59c12066e180c77a9c53363b2d0a8c Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 24 May 2018 14:25:52 +0200 Subject: [PATCH 2/5] Add two more rule sets 5.14.0b * Increase rule storage space to 3 rule sets of 512 characters using commands rule1, rule2 and rule3 --- README.md | 4 +- platformio.ini | 5 +-- sonoff/_releasenotes.ino | 7 +++- sonoff/settings.h | 15 +++---- sonoff/settings.ino | 29 ++++++++++++- sonoff/sonoff.h | 3 +- sonoff/sonoff.ino | 2 +- sonoff/webserver.ino | 53 +++++++++++------------ sonoff/xdrv_10_rules.ino | 91 ++++++++++++++++++++++------------------ 9 files changed, 126 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 3eca78b2b..606577d21 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! ### Development [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) -Current version is **5.14.0a** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.14.0b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### Quick install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. @@ -22,7 +22,7 @@ Download one of the released binaries from https://github.com/arendst/Sonoff-Tas If you want to compile Sonoff-Tasmota yourself keep in mind the following: - Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information. -- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite). +- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite). - To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config.override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file. ### Version Information diff --git a/platformio.ini b/platformio.ini index 90b89cb9c..bc5dfca12 100644 --- a/platformio.ini +++ b/platformio.ini @@ -57,9 +57,6 @@ build_flags = -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; -DUSE_CONFIG_OVERRIDE -; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes -extra_scripts = pio/strip-floats.py - ; *** Serial Monitor options monitor_speed = 115200 @@ -68,6 +65,8 @@ monitor_speed = 115200 upload_speed = 512000 upload_resetmethod = nodemcu upload_port = COM5 +; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes +extra_scripts = pio/strip-floats.py ; *** Upload file to OTA server using SCP ;upload_port = user@host:/path diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 0ad53c457..e89fc9140 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,7 @@ -/* 5.14.0a +/* 5.14.0b + * Increase rule storage space to 3 rule sets of 512 characters using commands rule1, rule2 and rule3 + * + * 5.14.0a * Add feature information to Status 4 * Add tools folder with python script decode-status.py for decoding some status fields like SetOption and Features * Add Eastron SDM630 energy meter by Gennaro Tortone (#2735) @@ -7,7 +10,7 @@ * Add python script fw-server.py in tools folder to create a simple OTA server by Gennaro Tortone (#2759) * Add rules %mem1% to %mem5% variable names storing data in flash (#2780) * Add rules test on %varx% or %memx% (#2780) - * Add optional token %id% substituting the unique MAC address for topic names by Michael Graf (#2794) + * Add optional token %id% substituting the unique MAC address to fulltopic by Michael Graf (#2794) * Fix display selection of un-available GPIO options in Module Configuration webpage (#2718) * Fix timer re-trigger within one minute after restart (#2744) * Fix IRSend not accepting data value of 0 by David Conran (#2751) diff --git a/sonoff/settings.h b/sonoff/settings.h index ccb9509d2..0c4a8617c 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -48,8 +48,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i) uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f) - uint32_t rules_enabled : 1; // bit 23 (v5.12.0j) - uint32_t rules_once : 1; // bit 24 (v5.12.0k) + uint32_t rules_enabled : 1; // bit 23 (v5.12.0j) - free since v5.14.0b + uint32_t rules_once : 1; // bit 24 (v5.12.0k) - free since v5.14.0b uint32_t knx_enabled : 1; // bit 25 (v5.12.0l) KNX uint32_t device_index_enable : 1; // bit 26 (v5.13.1a) uint32_t knx_enable_enhancement : 1; // bit 27 (v5.14.0a) KNX @@ -232,9 +232,8 @@ struct SYSCFG { uint8_t light_color[5]; // 498 uint8_t light_correction; // 49D uint8_t light_dimmer; // 49E - - byte free_49F[2]; // 49F - + uint8_t rule_enabled; // 49F + uint8_t rule_once; // 4A0 uint8_t light_fade; // 4A1 uint8_t light_speed; // 4A2 uint8_t light_scheme; // 4A3 @@ -274,9 +273,11 @@ struct SYSCFG { byte free_6f6[216]; // 6F6 char mems[RULES_MAX_MEMS][10]; // 7CE - char rules[MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m + // 800 Full - no more free locations - // A00 - FFF free locations + char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b + + // E00 - FFF free locations } Settings; struct RTCMEM { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 2d3f3c3d8..ac71c9cac 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -143,6 +143,7 @@ extern "C" uint32_t _SPIFFS_end; uint32_t settings_hash = 0; uint32_t settings_location = SETTINGS_LOCATION; +uint8_t *settings_buffer = NULL; /********************************************************************************************/ /* @@ -167,6 +168,24 @@ void SetFlashModeDout() delete[] _buffer; } +void SettingsBufferFree() +{ + if (settings_buffer != NULL) { + free(settings_buffer); + settings_buffer = NULL; + } +} + +bool SettingsBufferAlloc() +{ + SettingsBufferFree(); + if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); // Not enough (memory) space + return false; + } + return true; +} + uint32_t GetSettingsHash() { uint32_t hash = 0; @@ -870,7 +889,8 @@ void SettingsDelta() Settings.longitude = (int)((double)LONGITUDE * 1000000); } if (Settings.version < 0x050C000B) { - memset(&Settings.rules, 0x00, sizeof(Settings.rules)); +// memset(&Settings.rules, 0x00, sizeof(Settings.rules)); + Settings.rules[0][0] = '\0'; } if (Settings.version < 0x050C000D) { memmove(Settings.rules, Settings.rules -256, sizeof(Settings.rules)); // move rules up by 256 bytes @@ -887,6 +907,13 @@ void SettingsDelta() if (Settings.version < 0x050D0103) { SettingsDefaultSet_5_13_1c(); } + if (Settings.version < 0x050E0002) { + for (byte i = 1; i < MAX_RULE_SETS -1; i++) { + Settings.rules[i][0] = '\0'; + } + Settings.rule_enabled = Settings.flag.rules_enabled; + Settings.rule_once = Settings.flag.rules_once; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 369fb10cb..35a50952f 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -51,6 +51,7 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set #define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set #define RULES_MAX_MEMS 5 // Max number of saved vars +#define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters #define MAX_RULE_SIZE 512 // Max number of characters in rules #define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] @@ -88,7 +89,7 @@ typedef unsigned long power_t; // Power (Relay) type #define SERIALLOG_TIMER 600 // Seconds to disable SerialLog #define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware -#define INPUT_BUFFER_SIZE 512 // Max number of characters in (serial and http) command buffer +#define INPUT_BUFFER_SIZE 520 // Max number of characters in (serial and http) command buffer #define CMDSZ 24 // Max number of characters in command #define TOPSZ 100 // Max number of characters in topic string #define LOGSZ 512 // Max number of characters in log diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e88c03e7e..ad159489b 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x050E0001 // 5.14.0a +#define VERSION 0x050E0002 // 5.14.0b // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index b46c5354b..e1656ec31 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -328,7 +328,6 @@ uint8_t upload_progress_dot_count; uint8_t config_block_count = 0; uint8_t config_xor_on = 0; uint8_t config_xor_on_set = CONFIG_FILE_XOR; -uint8_t *settings_new = NULL; // Helper function to avoid code duplication (saves 4k Flash) static void WebGetArg(const char* arg, char* out, size_t max) @@ -915,25 +914,36 @@ void HandleBackupConfiguration() if (HttpUser()) { return; } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION)); - uint8_t buffer[sizeof(Settings)]; + if (!SettingsBufferAlloc()) { return; } WiFiClient myClient = WebServer->client(); - WebServer->setContentLength(sizeof(buffer)); + WebServer->setContentLength(sizeof(Settings)); char attachment[100]; char friendlyname[sizeof(Settings.friendlyname[0])]; snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, Settings.friendlyname[0]), my_version); WebServer->sendHeader(F("Content-Disposition"), attachment); + WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), ""); - memcpy(buffer, &Settings, sizeof(buffer)); - buffer[0] = CONFIG_FILE_SIGN; - buffer[1] = (!config_xor_on_set) ? 0 : 1; - if (buffer[1]) { - for (uint16_t i = 2; i < sizeof(buffer); i++) { - buffer[i] ^= (config_xor_on_set +i); + memcpy(settings_buffer, &Settings, sizeof(Settings)); + settings_buffer[0] = CONFIG_FILE_SIGN; + settings_buffer[1] = (!config_xor_on_set) ? 0 : 1; + if (settings_buffer[1]) { + for (uint16_t i = 2; i < sizeof(Settings); i++) { + settings_buffer[i] ^= (config_xor_on_set +i); } } - myClient.write((const char*)buffer, sizeof(buffer)); + +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + size_t written = myClient.write((const char*)settings_buffer, sizeof(Settings)); + if (written < sizeof(Settings)) { // https://github.com/esp8266/Arduino/issues/3218 + myClient.write((const char*)settings_buffer +written, sizeof(Settings) -written); + } +#else + myClient.write((const char*)settings_buffer, sizeof(Settings)); +#endif + + SettingsBufferFree(); } void HandleSaveSettings() @@ -1186,14 +1196,6 @@ void HandleUpgradeFirmwareStart() ExecuteCommand(svalue); } -void SettingsNewFree() -{ - if (settings_new != NULL) { - free(settings_new); - settings_new = NULL; - } -} - void HandleUploadDone() { if (HttpUser()) { return; } @@ -1233,7 +1235,7 @@ void HandleUploadDone() page += FPSTR(HTTP_MSG_RSTRT); restart_flag = 2; } - SettingsNewFree(); + SettingsBufferFree(); page += F("
"); page += FPSTR(HTTP_BTN_MAIN); ShowPage(page); @@ -1262,8 +1264,7 @@ void HandleUploadLoop() snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str()); AddLog(LOG_LEVEL_INFO); if (upload_file_type) { - SettingsNewFree(); - if (!(settings_new = (uint8_t *)malloc(sizeof(Settings)))) { + if (!SettingsBufferAlloc()) { upload_error = 2; return; } @@ -1311,7 +1312,7 @@ void HandleUploadLoop() upload_error = 9; return; } - memcpy(settings_new + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); + memcpy(settings_buffer + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize); config_block_count++; } } else { // firmware @@ -1332,13 +1333,13 @@ void HandleUploadLoop() if (upload_file_type) { if (config_xor_on) { for (uint16_t i = 2; i < sizeof(Settings); i++) { - settings_new[i] ^= (config_xor_on_set +i); + settings_buffer[i] ^= (config_xor_on_set +i); } } SettingsDefaultSet2(); - memcpy((char*)&Settings +16, settings_new +16, sizeof(Settings) -16); - memcpy((char*)&Settings +8, settings_new +8, 4); // Restore version and auto upgrade - SettingsNewFree(); + memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16); + memcpy((char*)&Settings +8, settings_buffer +8, 4); // Restore version and auto upgrade + SettingsBufferFree(); } else { if (!Update.end(true)) { // true to set the size to the current progress if (_serialoutput) { Update.printError(Serial); } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 714924af1..678f95705 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -80,14 +80,16 @@ enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM ; +char rules[MAX_RULE_SIZE]; + String rules_event_value; unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 }; uint8_t rules_quota = 0; long rules_new_power = -1; long rules_old_power = -1; -uint32_t rules_triggers = 0; -uint8_t rules_trigger_count = 0; +uint32_t rules_triggers[MAX_RULE_SETS] = { 0 }; +uint8_t rules_trigger_count[MAX_RULE_SETS] = { 0 }; uint8_t rules_teleperiod = 0; char vars[RULES_MAX_VARS][10] = { 0 }; @@ -141,7 +143,7 @@ bool TimeReached(unsigned long timer) /*******************************************************************************************/ -bool RulesRuleMatch(String &event, String &rule) +bool RulesRuleMatch(byte rule_set, String &event, String &rule) { // event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} // event = {"System":{"Boot":1}} @@ -218,7 +220,7 @@ bool RulesRuleMatch(String &event, String &rule) const char* str_value = root[rule_task][rule_name]; //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), -// rule_task.c_str(), rule_name.c_str(), tmp_value, rules_trigger_count, bitRead(rules_triggers, rules_trigger_count), event.c_str(), (str_value) ? str_value : "none"); +// rule_task.c_str(), rule_name.c_str(), tmp_value, rules_trigger_count[rule_set], bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); //AddLog(LOG_LEVEL_DEBUG); if (!root[rule_task][rule_name].success()) { return false; } @@ -247,13 +249,13 @@ bool RulesRuleMatch(String &event, String &rule) if (Settings.flag.rules_once) { if (match) { // Only allow match state changes - if (!bitRead(rules_triggers, rules_trigger_count)) { - bitSet(rules_triggers, rules_trigger_count); + if (!bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set])) { + bitSet(rules_triggers[rule_set], rules_trigger_count[rule_set]); } else { match = false; } } else { - bitClear(rules_triggers, rules_trigger_count); + bitClear(rules_triggers[rule_set], rules_trigger_count[rule_set]); } } @@ -262,24 +264,19 @@ bool RulesRuleMatch(String &event, String &rule) /*******************************************************************************************/ -bool RulesProcess() +bool RuleSetProcess(byte rule_set, String &event_saved) { bool serviced = false; char stemp[10]; delay(0); // Prohibit possible loop software watchdog -//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event = %s, Rule = %s"), mqtt_data, Settings.rules); +//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]); //AddLog(LOG_LEVEL_DEBUG); - if (!Settings.flag.rules_enabled) { return serviced; } // Not enabled - if (!strlen(Settings.rules)) { return serviced; } // No rules + String rules = Settings.rules[rule_set]; - String event_saved = mqtt_data; - event_saved.toUpperCase(); - String rules = Settings.rules; - - rules_trigger_count = 0; + rules_trigger_count[rule_set] = 0; int plen = 0; while (true) { rules = rules.substring(plen); // Select relative to last rule @@ -304,7 +301,7 @@ bool RulesProcess() //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event |%s|, Rule |%s|, Command(s) |%s|"), event.c_str(), event_trigger.c_str(), commands.c_str()); //AddLog(LOG_LEVEL_DEBUG); - if (RulesRuleMatch(event, event_trigger)) { + if (RulesRuleMatch(rule_set, event, event_trigger)) { commands.trim(); String ucommand = commands; ucommand.toUpperCase(); @@ -331,25 +328,42 @@ bool RulesProcess() ExecuteCommand(command); serviced = true; } - rules_trigger_count++; + rules_trigger_count[rule_set]++; } return serviced; } /*******************************************************************************************/ +bool RulesProcess() +{ + bool serviced = false; + + String event_saved = mqtt_data; + event_saved.toUpperCase(); + + for (byte i = 0; i < MAX_RULE_SETS; i++) { + if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { + if (RuleSetProcess(i, event_saved)) { serviced = true; } + } + } + return serviced; +} + void RulesInit() { - if (Settings.rules[0] == '\0') { - Settings.flag.rules_enabled = 0; - Settings.flag.rules_once = 0; + for (byte i = 0; i < MAX_RULE_SETS; i++) { + if (Settings.rules[i][0] == '\0') { + bitWrite(Settings.rule_enabled, i, 0); + bitWrite(Settings.rule_once, i, 0); + } } rules_teleperiod = 0; } void RulesEvery50ms() { - if (Settings.flag.rules_enabled) { + if (Settings.rule_enabled) { // Any rule enabled if (rules_new_power != rules_old_power) { if (rules_old_power != -1) { for (byte i = 0; i < devices_present; i++) { @@ -381,7 +395,7 @@ void RulesEvery50ms() void RulesEverySecond() { - if (Settings.flag.rules_enabled) { + if (Settings.rule_enabled) { // Any rule enabled for (byte i = 0; i < MAX_RULE_TIMERS; i++) { if (rules_timer[i] != 0L) { // Timer active? if (TimeReached(rules_timer[i])) { // Timer finished? @@ -416,39 +430,36 @@ boolean RulesCommand() if (-1 == command_code) { serviced = false; // Unknown command } - else if (CMND_RULE == command_code) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules))) { + else if ((CMND_RULE == command_code) && (index > 0) && (index <= MAX_RULE_SETS)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules[index -1]))) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { switch (XdrvMailbox.payload) { case 0: // Off case 1: // On - Settings.flag.rules_enabled = XdrvMailbox.payload; +// Settings.flag.rules_enabled = XdrvMailbox.payload; + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); break; case 2: // Toggle - Settings.flag.rules_enabled ^= 1; +// Settings.flag.rules_enabled ^= 1; + bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1); break; case 4: // Off case 5: // On - Settings.flag.rules_once = XdrvMailbox.payload &1; +// Settings.flag.rules_once = XdrvMailbox.payload &1; + bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1); break; case 6: // Toggle - Settings.flag.rules_once ^= 1; +// Settings.flag.rules_once ^= 1; + bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1); break; } } else { -/* - String uc_data = XdrvMailbox.data; // Do not allow Rule to be used within a rule - uc_data.toUpperCase(); - String uc_command = command; - uc_command += " "; // Distuingish from RuleTimer - uc_command.toUpperCase(); - if (!uc_data.indexOf(uc_command)) { strlcpy(Settings.rules, XdrvMailbox.data, sizeof(Settings.rules)); } -*/ - strlcpy(Settings.rules, XdrvMailbox.data, sizeof(Settings.rules)); + strlcpy(Settings.rules[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1])); } - rules_triggers = 0; // Reset once flag + rules_triggers[index -1] = 0; // Reset once flag } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Once\":\"%s\",\"Rules\":\"%s\"}"), command, GetStateText(Settings.flag.rules_enabled), GetStateText(Settings.flag.rules_once), Settings.rules); + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), + command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]); } else if ((CMND_RULETIMER == command_code) && (index > 0) && (index <= MAX_RULE_TIMERS)) { if (XdrvMailbox.data_len > 0) { From 9f329d5fb0c5341427f10b9913572b20cd7b2ab6 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 24 May 2018 16:23:20 +0200 Subject: [PATCH 3/5] Add rule support for IrReceive and RfReceive 5.14.0b * Add rule support for IrReceive and RfReceive (#2758) --- sonoff/_releasenotes.ino | 3 ++- sonoff/settings.ino | 1 - sonoff/sonoff.h | 2 +- sonoff/sonoff.ino | 9 ++++----- sonoff/support.ino | 6 ++---- sonoff/xdrv_00_mqtt.ino | 12 +++--------- sonoff/xdrv_02_irremote.ino | 1 + sonoff/xdrv_04_snfbridge.ino | 1 + sonoff/xdrv_08_serial_bridge.ino | 1 + sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 9 +++------ sonoff/xdrv_interface.ino | 6 ++++++ 12 files changed, 25 insertions(+), 28 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index e89fc9140..59db833a6 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,6 @@ /* 5.14.0b - * Increase rule storage space to 3 rule sets of 512 characters using commands rule1, rule2 and rule3 + * Add two rule sets of 511 characters using commands rule1, rule2 and rule3 + * Add rule support for IrReceive and RfReceive (#2758) * * 5.14.0a * Add feature information to Status 4 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index ac71c9cac..11b893910 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -889,7 +889,6 @@ void SettingsDelta() Settings.longitude = (int)((double)LONGITUDE * 1000000); } if (Settings.version < 0x050C000B) { -// memset(&Settings.rules, 0x00, sizeof(Settings.rules)); Settings.rules[0][0] = '\0'; } if (Settings.version < 0x050C000D) { diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 35a50952f..517b755ae 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -188,7 +188,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, - FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR}; + FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ad159489b..82e745b73 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1177,11 +1177,9 @@ boolean SendKey(byte key, byte device, byte state) MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain); #endif // USE_DOMOTICZ result = true; -#ifdef USE_RULES } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); - result = RulesProcess(); -#endif // USE_RULES + result = XdrvRulesProcess(); } #ifdef USE_KNX KnxSendButtonPower(key, device, state); @@ -1300,11 +1298,11 @@ void ExecuteCommand(char *cmnd) void PublishStatus(uint8_t payload) { - uint8_t option = 1; + uint8_t option = STAT; char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +4)]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++; + if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++; // TELE if ((!Settings.flag.mqtt_enabled) && (6 == payload)) payload = 99; if (!energy_flg && (9 == payload)) payload = 99; @@ -2168,6 +2166,7 @@ void SerialInput() serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); +// XdrvRulesProcess(); serial_in_byte_counter = 0; } } diff --git a/sonoff/support.ino b/sonoff/support.ino index b5ec74df9..2bc80c5eb 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1700,14 +1700,12 @@ void RtcSecond() snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); AddLog(LOG_LEVEL_DEBUG); -#ifdef USE_RULES if (local_time < 1451602800) { // 2016-01-01 strncpy_P(mqtt_data, PSTR("{\"Time\":{\"Initialized\":1}}"), sizeof(mqtt_data)); } else { strncpy_P(mqtt_data, PSTR("{\"Time\":{\"Set\":1}}"), sizeof(mqtt_data)); } - RulesProcess(); -#endif // USE_RULES + XdrvRulesProcess(); } else { ntp_sync_minute++; // Try again in next minute } @@ -1788,7 +1786,7 @@ void AdcEvery50ms() adc_last_value = new_value; uint16_t value = adc_last_value / 10; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); - RulesProcess(); + XdrvRulesProcess(); } } } diff --git a/sonoff/xdrv_00_mqtt.ino b/sonoff/xdrv_00_mqtt.ino index c3eda47d2..5d688e721 100644 --- a/sonoff/xdrv_00_mqtt.ino +++ b/sonoff/xdrv_00_mqtt.ino @@ -315,10 +315,8 @@ void MqttDisconnected(int state) snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, mqtt_retry_counter); AddLog(LOG_LEVEL_INFO); -#ifdef USE_RULES strncpy_P(mqtt_data, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(mqtt_data)); - RulesProcess(); -#endif // USE_RULES + XdrvRulesProcess(); } void MqttConnected() @@ -370,17 +368,13 @@ void MqttConnected() tele_period = Settings.tele_period -9; } status_update_timer = 2; -#ifdef USE_RULES strncpy_P(mqtt_data, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(mqtt_data)); - RulesProcess(); -#endif // USE_RULES + XdrvRulesProcess(); XdrvCall(FUNC_MQTT_INIT); } mqtt_initial_connection_state = 0; -#ifdef USE_RULES strncpy_P(mqtt_data, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(mqtt_data)); - RulesProcess(); -#endif // USE_RULES + XdrvRulesProcess(); } #ifdef USE_MQTT_TLS diff --git a/sonoff/xdrv_02_irremote.ino b/sonoff/xdrv_02_irremote.ino index e2d4a1019..eed1fd228 100644 --- a/sonoff/xdrv_02_irremote.ino +++ b/sonoff/xdrv_02_irremote.ino @@ -110,6 +110,7 @@ void IrReceiveCheck() snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":\"%lX\"}}"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, (uint32_t)results.value); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + XdrvRulesProcess(); #ifdef USE_DOMOTICZ unsigned long value = results.value | (iridx << 28); // [Protocol:4, Data:28] DomoticzSensor(DZ_COUNT, value); // Send data as Domoticz Counter value diff --git a/sonoff/xdrv_04_snfbridge.ino b/sonoff/xdrv_04_snfbridge.ino index 20c9fa3d1..8aa300f5d 100644 --- a/sonoff/xdrv_04_snfbridge.ino +++ b/sonoff/xdrv_04_snfbridge.ino @@ -97,6 +97,7 @@ void SonoffBridgeReceived() snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\",\"" D_CMND_RFKEY "\":%s}}"), sync_time, low_time, high_time, received_id, rfkey); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); #ifdef USE_DOMOTICZ DomoticzSensor(DZ_COUNT, received_id); // Send rid as Domoticz Counter value #endif // USE_DOMOTICZ diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 455179f98..653649b91 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -61,6 +61,7 @@ void SerialBridgeInput() serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); +// XdrvRulesProcess(); serial_bridge_in_byte_counter = 0; } } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 7528dcfad..bc517ae1a 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -287,7 +287,7 @@ void TimerEverySecond() #ifdef USE_RULES if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); - RulesProcess(); + XdrvRulesProcess(); } else #endif // USE_RULES if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power); } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 678f95705..1afe38621 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -80,8 +80,6 @@ enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM }; const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM ; -char rules[MAX_RULE_SIZE]; - String rules_event_value; unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 }; uint8_t rules_quota = 0; @@ -436,20 +434,16 @@ boolean RulesCommand() switch (XdrvMailbox.payload) { case 0: // Off case 1: // On -// Settings.flag.rules_enabled = XdrvMailbox.payload; bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); break; case 2: // Toggle -// Settings.flag.rules_enabled ^= 1; bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1); break; case 4: // Off case 5: // On -// Settings.flag.rules_once = XdrvMailbox.payload &1; bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1); break; case 6: // Toggle -// Settings.flag.rules_once ^= 1; bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1); break; } @@ -526,6 +520,9 @@ boolean Xdrv10(byte function) case FUNC_COMMAND: result = RulesCommand(); break; + case FUNC_RULES_PROCESS: + result = RulesProcess(); + break; } return result; } diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 09f056ece..d075f3136 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -175,6 +175,11 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t return XdrvCall(FUNC_MQTT_DATA); } +boolean XdrvRulesProcess() +{ + return XdrvCall(FUNC_RULES_PROCESS); +} + /*********************************************************************************************\ * Function call to all xdrv * @@ -188,6 +193,7 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t * FUNC_SHOW_SENSOR * FUNC_EVERY_SECOND * FUNC_EVERY_50_MSECOND + * FUNC_RULES_PROCESS \*********************************************************************************************/ boolean XdrvCall(byte Function) From e6daeda43e8838aafe6941321d97f0cf79609691 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 24 May 2018 16:36:12 +0200 Subject: [PATCH 4/5] Fix initial rule3 clearence --- sonoff/settings.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 11b893910..170087767 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -907,7 +907,7 @@ void SettingsDelta() SettingsDefaultSet_5_13_1c(); } if (Settings.version < 0x050E0002) { - for (byte i = 1; i < MAX_RULE_SETS -1; i++) { + for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } Settings.rule_enabled = Settings.flag.rules_enabled; From d1db31fc0a9fa7d8d7aa5bf193c91e1cc10377c2 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 24 May 2018 17:08:14 +0200 Subject: [PATCH 5/5] Fix rule string comparison --- sonoff/xdrv_10_rules.ino | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 1afe38621..abaf700a2 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -179,7 +179,7 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) } } - char tmp_value[CMDSZ] = { 0 }; + char rule_svalue[CMDSZ] = { 0 }; double rule_value = 0; if (pos > 0) { String rule_param = rule_name.substring(pos + 1); @@ -198,13 +198,13 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) } } rule_param.toUpperCase(); - snprintf(tmp_value, sizeof(tmp_value), rule_param.c_str()); + snprintf(rule_svalue, sizeof(rule_svalue), rule_param.c_str()); - int temp_value = GetStateNumber(tmp_value); + int temp_value = GetStateNumber(rule_svalue); if (temp_value > -1) { rule_value = temp_value; } else { - rule_value = CharToDouble((char*)tmp_value); // 0.1 - This saves 9k code over toFLoat()! + rule_value = CharToDouble((char*)rule_svalue); // 0.1 - This saves 9k code over toFLoat()! } rule_name = rule_name.substring(0, pos); // "CURRENT" } @@ -218,7 +218,7 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) const char* str_value = root[rule_task][rule_name]; //snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), -// rule_task.c_str(), rule_name.c_str(), tmp_value, rules_trigger_count[rule_set], bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); +// rule_task.c_str(), rule_name.c_str(), rule_svalue, rules_trigger_count[rule_set], bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); //AddLog(LOG_LEVEL_DEBUG); if (!root[rule_task][rule_name].success()) { return false; } @@ -231,13 +231,14 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) value = CharToDouble((char*)str_value); switch (compare) { case '>': - if (value > rule_value) match = true; + if (value > rule_value) { match = true; } break; case '<': - if (value < rule_value) match = true; + if (value < rule_value) { match = true; } break; case '=': - if (value == rule_value) match = true; +// if (value == rule_value) { match = true; } // Compare values - only decimals or partly hexadecimals + if (!strcasecmp(str_value, rule_svalue)) { match = true; } // Compare strings - this also works for hexadecimals break; case ' ': match = true; // Json value but not needed