From 6a5c0d29e87e400c1dc8c6aa2df1b0954faa6bd4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 23 Aug 2018 16:05:51 +0200 Subject: [PATCH] 6.1.1.9 - Fixes and Additions 6.1.1.9 * Allow user override of define MAX_RULE_TIMERS (#3561) * Allow user override of define MAX_RULE_VARS * Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525) * Fix OtaMagic when file path contains a dash (-) (#3563) --- sonoff/_changelog.ino | 8 ++++- sonoff/i18n.h | 1 + sonoff/settings.h | 6 ++-- sonoff/sonoff.h | 6 +++- sonoff/sonoff.ino | 51 +++++++++++++++++++------------ sonoff/sonoff_template.h | 21 ++++++++++++- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 11 +++++++ sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_10_rules.ino | 27 ++++++++-------- sonoff/xdrv_11_knx.ino | 8 +++++ sonoff/xdrv_12_home_assistant.ino | 51 ++++++++++++++++++++++++++++++- sonoff/xsns_01_counter.ino | 12 ++++++-- 13 files changed, 160 insertions(+), 46 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 9aa7f6837..f2cb1fb32 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,10 @@ -/* 6.1.1.8 +/* 6.1.1.9 + * Allow user override of define MAX_RULE_TIMERS (#3561) + * Allow user override of define MAX_RULE_VARS + * Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525) + * Fix OtaMagic when file path contains a dash (-) (#3563) + * + * 6.1.1.8 * Fix MQTT reconnection detection when using TasmotaMqtt library (#3558) * Add build time setting of ButtonTopic and SwitchTopic (#3414) * Add display features and dynamic buffering diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 967eb857d..235f0cc04 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -447,6 +447,7 @@ const char S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s\":\"%d (" D const char S_JSON_COMMAND_NVALUE[] PROGMEM = "{\"%s\":%d}"; const char S_JSON_COMMAND_LVALUE[] PROGMEM = "{\"%s\":%lu}"; const char S_JSON_COMMAND_SVALUE[] PROGMEM = "{\"%s\":\"%s\"}"; +const char S_JSON_COMMAND_HVALUE[] PROGMEM = "{\"%s\":\"#%X\"}"; const char S_JSON_COMMAND_ASTERIX[] PROGMEM = "{\"%s\":\"" D_ASTERIX "\"}"; const char S_JSON_COMMAND_XVALUE[] PROGMEM = "{\"%s\":%s}"; // %s must provide quotes on non-number diff --git a/sonoff/settings.h b/sonoff/settings.h index 4beaf71b4..bd93d8b38 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -195,7 +195,7 @@ struct SYSCFG { char hostname[33]; // 165 char syslog_host[33]; // 186 - byte free_1A7[1]; // 1A7 + byte free1A7[1]; // 1A7 uint16_t syslog_port; // 1A8 byte syslog_level; // 1AA @@ -298,7 +298,7 @@ struct SYSCFG { byte ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 - byte free_542[2]; // 542 + byte free542[2]; // 542 uint32_t ip_address[4]; // 544 unsigned long energy_kWhtotal; // 554 @@ -324,7 +324,7 @@ struct SYSCFG { byte free_717[183]; // 717 - char mems[RULES_MAX_MEMS][10]; // 7CE + char mems[MAX_RULE_MEMS][10]; // 7CE // 800 Full - no more 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 diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 2efb831b0..fd0b8430b 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -45,10 +45,14 @@ typedef unsigned long power_t; // Power (Relay) type #define MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices #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_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 +// Changes to the following defines have no impact on settings layout +#define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) +#define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) + #define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] #define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic #define MQTT_TOKEN_ID "%id%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8e2889fb3..68be98d56 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -88,7 +88,7 @@ const char kTasmotaCommands[] PROGMEM = D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_FANSPEED "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|" - D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|" + D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" @@ -831,7 +831,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) restart_flag = 2; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); - byte jsflg = 0; for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (GPIO_USER == cmodule.gp.io[i]) { if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); @@ -850,13 +849,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) mytmplt cmodule; memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); for (byte i = 0; i < GPIO_SENSOR_END; i++) { - if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); - } - jsflg = 1; if (!GetUsedInModule(i, cmodule.gp.io)) { + if (!jsflg) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + } + jsflg = 1; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kSensorNames)); if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == GPIO_SENSOR_END -1)) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); @@ -897,7 +896,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_range); } else if ((CMND_COUNTER == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { - if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { + if ((data_len > 0) && ((pin[GPIO_CNTR1 + index -1] < 99) || (pin[GPIO_CNTR1_NP + index -1] < 99))) { if ((dataBuf[0] == '-') || (dataBuf[0] == '+')) { RtcSettings.pulse_counter[index -1] += payload32; Settings.pulse_counter[index -1] += payload32; @@ -909,7 +908,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]); } else if ((CMND_COUNTERTYPE == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { - if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) { + if ((payload >= 0) && (payload <= 1) && ((pin[GPIO_CNTR1 + index -1] < 99) || (pin[GPIO_CNTR1_NP + index -1] < 99))) { bitWrite(Settings.pulse_counter_type, index -1, payload &1); RtcSettings.pulse_counter[index -1] = 0; Settings.pulse_counter[index -1] = 0; @@ -1502,9 +1501,9 @@ boolean MqttShowSensor() int json_data_start = strlen(mqtt_data); for (byte i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { + if ((pin[GPIO_SWT1 +i] < 99) || (pin[GPIO_SWT1_NP +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { #else - if (pin[GPIO_SWT1 +i] < 99) { + if (pin[GPIO_SWT1 +i] < 99) || (pin[GPIO_SWT1_NP +i] < 99) { #endif // USE_TM1638 boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i])); @@ -1636,6 +1635,10 @@ void ButtonHandler() button_present = 1; button = digitalRead(pin[GPIO_KEY1 +button_index]); } + else if ((pin[GPIO_KEY1_NP +button_index] < 99) && !blockgpio0) { + button_present = 1; + button = digitalRead(pin[GPIO_KEY1_NP +button_index]); + } } if (button_present) { @@ -1752,7 +1755,7 @@ void SwitchHandler(byte mode) uint8_t switchflag; for (byte i = 0; i < MAX_SWITCHES; i++) { - if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { + if ((pin[GPIO_SWT1 +i] < 99) || (pin[GPIO_SWT1_NP +i] < 99) || (mode)) { if (holdwallswitch[i]) { holdwallswitch[i]--; @@ -1764,7 +1767,11 @@ void SwitchHandler(byte mode) if (mode) { button = virtualswitch[i]; } else { - button = digitalRead(pin[GPIO_SWT1 +i]); + if (pin[GPIO_SWT1 +i] < 99) { + button = digitalRead(pin[GPIO_SWT1 +i]); + } else { + button = digitalRead(pin[GPIO_SWT1_NP +i]); + } } if (button != lastwallswitch[i]) { @@ -1975,9 +1982,9 @@ void StateLoop() strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); #ifndef BE_MINIMAL if (RtcSettings.ota_loader) { - char *bch = strrchr(mqtt_data, '/'); // only consider filename after last backslash prevent change of urls having "-" in it - char *pch = strrchr((bch!=NULL)?bch:mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch!=NULL)?bch:mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin + char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it + char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin + char *ech = strrchr((bch != NULL) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin if (!pch) pch = ech; if (pch) { mqtt_data[pch - mqtt_data] = '\0'; @@ -2410,6 +2417,9 @@ void GpioInit() if (pin[GPIO_KEY1 +i] < 99) { pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); } + else if (pin[GPIO_KEY1_NP +i] < 99) { + pinMode(pin[GPIO_KEY1_NP +i], (16 == pin[GPIO_KEY1_NP +i]) ? INPUT_PULLDOWN_16 : INPUT); + } } for (byte i = 0; i < MAX_LEDS; i++) { if (pin[GPIO_LED1 +i] < 99) { @@ -2420,9 +2430,12 @@ void GpioInit() for (byte i = 0; i < MAX_SWITCHES; i++) { lastwallswitch[i] = 1; // Init global to virtual switch state; if (pin[GPIO_SWT1 +i] < 99) { - pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 :INPUT_PULLUP); + pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check - + } + else if (pin[GPIO_SWT1_NP +i] < 99) { + pinMode(pin[GPIO_SWT1_NP +i], (16 == pin[GPIO_SWT1_NP +i]) ? INPUT_PULLDOWN_16 : INPUT); + lastwallswitch[i] = digitalRead(pin[GPIO_SWT1_NP +i]); // Set global now so doesn't change the saved power state on first switch check } virtualswitch[i] = lastwallswitch[i]; } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 62221d938..180c24aec 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -104,6 +104,22 @@ enum UserSelectablePins { GPIO_TM16CLK, // TM1638 Clock GPIO_TM16DIO, // TM1638 Data I/O GPIO_TM16STB, // TM1638 Strobe + GPIO_SWT1_NP, // User connected external switches + GPIO_SWT2_NP, + GPIO_SWT3_NP, + GPIO_SWT4_NP, + GPIO_SWT5_NP, + GPIO_SWT6_NP, + GPIO_SWT7_NP, + GPIO_SWT8_NP, + GPIO_KEY1_NP, // Button usually connected to GPIO0 + GPIO_KEY2_NP, + GPIO_KEY3_NP, + GPIO_KEY4_NP, + GPIO_CNTR1_NP, + GPIO_CNTR2_NP, + GPIO_CNTR3_NP, + GPIO_CNTR4_NP, GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -150,7 +166,10 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|" D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|" D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX "|" - D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB; + D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB "|" + D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|" + D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" + D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|"; /********************************************************************************************/ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index ea98a83b6..58b36d16e 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06010108 +#define VERSION 0x06010109 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 3c2238be7..cf62cdba0 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -179,6 +179,17 @@ double CharToDouble(char *str) return result; } +int TextToInt(char *str) +{ + char *p; + uint8_t radix = 10; + if ('#' == str[0]) { + radix = 16; + str++; + } + return strtol(str, &p, radix); +} + char* dtostrfd(double number, unsigned char prec, char *s) { return dtostrf(number, 1, prec, s); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 38929b8ff..79b0e2c6b 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -380,7 +380,7 @@ void HandleDomoticzConfiguration() page.replace("{2", String((int)Settings.domoticz_relay_idx[i])); page.replace("{3", String((int)Settings.domoticz_key_idx[i])); } - if (pin[GPIO_SWT1 +i] < 99) { + if ((pin[GPIO_SWT1 +i] < 99) || (pin[GPIO_SWT1_NP +i] < 99)) { page += FPSTR(HTTP_FORM_DOMOTICZ_SWITCH); page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 40560f286..176a2a1c5 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -63,9 +63,6 @@ * RuleTimer2 100 \*********************************************************************************************/ -#define MAX_RULE_TIMERS 8 -#define RULES_MAX_VARS 5 - #ifndef ULONG_MAX #define ULONG_MAX 0xffffffffUL #endif @@ -97,7 +94,7 @@ uint8_t rules_trigger_count[MAX_RULE_SETS] = { 0 }; uint8_t rules_teleperiod = 0; char event_data[100]; -char vars[RULES_MAX_VARS][10] = { 0 }; +char vars[MAX_RULE_VARS][10] = { 0 }; /*******************************************************************************************/ @@ -168,7 +165,7 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) rule_task = rule.substring(5, pos); // "INA219" or "SYSTEM" } - String rule_name = rule.substring(pos +1); // "CURRENT>0.100" or "BOOT" or "%var1%" + String rule_name = rule.substring(pos +1); // "CURRENT>0.100" or "BOOT" or "%var1%" or "MINUTE|5" char compare = ' '; pos = rule_name.indexOf(">"); @@ -195,14 +192,14 @@ bool RulesRuleMatch(byte rule_set, String &event, String &rule) double rule_value = 0; if (pos > 0) { String rule_param = rule_name.substring(pos + 1); - for (byte i = 0; i < RULES_MAX_VARS; i++) { + for (byte i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1); if (rule_param.startsWith(stemp)) { rule_param = vars[i]; break; } } - for (byte i = 0; i < RULES_MAX_MEMS; i++) { + for (byte i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); if (rule_param.startsWith(stemp)) { rule_param = Settings.mems[i]; @@ -326,11 +323,11 @@ bool RuleSetProcess(byte rule_set, String &event_saved) // if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception commands.replace(F("%value%"), rules_event_value); - for (byte i = 0; i < RULES_MAX_VARS; i++) { + for (byte i = 0; i < MAX_RULE_VARS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1); commands.replace(stemp, vars[i]); } - for (byte i = 0; i < RULES_MAX_MEMS; i++) { + for (byte i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); commands.replace(stemp, Settings.mems[i]); } @@ -569,40 +566,40 @@ boolean RulesCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } - else if ((CMND_VAR == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { + else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1])); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } - else if ((CMND_MEM == command_code) && (index > 0) && (index <= RULES_MAX_MEMS)) { + else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) { if (XdrvMailbox.data_len > 0) { strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1])); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } - else if ((CMND_ADD == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { + else if ((CMND_ADD == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, 2, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } - else if ((CMND_SUB == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { + else if ((CMND_SUB == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, 2, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } - else if ((CMND_MULT == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { + else if ((CMND_MULT == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data); dtostrfd(tempvar, 2, vars[index -1]); } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } - else if ((CMND_SCALE == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { + else if ((CMND_SCALE == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index ca5e22090..be1fbe1d7 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -485,10 +485,18 @@ void KNX_INIT() { if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } } + for (int i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + } for (int i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) { if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } } + for (int i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.gp.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + } if (GetUsedInModule(GPIO_DHT11, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_DHT22, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } if (GetUsedInModule(GPIO_SI7021, my_module.gp.io)) { device_param[KNX_TEMPERATURE-1].show = true; } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index e0faaf000..11fa69261 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -151,7 +151,7 @@ void HAssDiscoverButton() if (!button_index && ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module))) { button_present = 1; } else { - if (pin[GPIO_KEY1 + button_index] < 99) { + if ((pin[GPIO_KEY1 + button_index] < 99) || (pin[GPIO_KEY1_NP + button_index] < 99)) { button_present = 1; } } @@ -206,6 +206,50 @@ void HAssDiscovery(uint8_t mode) } } +/* +#define D_CMND_HASSDISCOVER "HassDiscover" + +enum HassCommands { CMND_HASSDISCOVER }; +const char kHassCommands[] PROGMEM = D_CMND_HASSDISCOVER ; + +boolean HassCommand() +{ + char command[CMDSZ]; + boolean serviced = true; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kHassCommands); + if (-1 == command_code) { + serviced = false; // Unknown command + } + else if (CMND_HASSDISCOVER == command_code) { + if (XdrvMailbox.data_len > 0) { + switch (XdrvMailbox.payload) { + case 0: // Off + case 1: // On + Settings.flag.hass_discovery = XdrvMailbox.payload; + break; + case 2: // Toggle + Settings.flag.hass_discovery ^= 1; + break; + case 4: // Off + case 5: // On + Settings.flag.hass_light = XdrvMailbox.payload &1; + break; + case 6: // Toggle + Settings.flag.hass_light ^= 1; + break; + } + HAssDiscovery(1); + } + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Force light\":\"%s\"}"), + command, GetStateText(Settings.flag.hass_discovery), GetStateText(Settings.flag.hass_light)); + } + else serviced = false; // Unknown command + + return serviced; +} +*/ + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -221,6 +265,11 @@ boolean Xdrv12(byte function) case FUNC_MQTT_INIT: HAssDiscovery(0); break; +/* + case FUNC_COMMAND: + result = HassCommand(); + break; +*/ } } return result; diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 4ae01d4a0..192c07973 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -64,7 +64,7 @@ void CounterUpdate4() void CounterSaveState() { for (byte i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { + if ((pin[GPIO_CNTR1 +i] < 99) || (pin[GPIO_CNTR1_NP +i] < 99)) { Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; } } @@ -80,6 +80,10 @@ void CounterInit() pinMode(pin[GPIO_CNTR1 +i], INPUT_PULLUP); attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); } + else if (pin[GPIO_CNTR1_NP +i] < 99) { + pinMode(pin[GPIO_CNTR1_NP +i], INPUT); + attachInterrupt(pin[GPIO_CNTR1_NP +i], counter_callbacks[i], FALLING); + } } } @@ -96,7 +100,7 @@ void CounterShow(boolean json) byte dsxflg = 0; byte header = 0; for (byte i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { + if ((pin[GPIO_CNTR1 +i] < 99) || (pin[GPIO_CNTR1_NP +i] < 99)) { if (bitRead(Settings.pulse_counter_type, i)) { dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); } else { @@ -124,7 +128,9 @@ void CounterShow(boolean json) #endif // USE_WEBSERVER } } - if(bitRead(Settings.pulse_counter_type, i)) RtcSettings.pulse_counter[i]=0xFFFFFFFF; // Set Timer to max in case of no more interrupts due to stall of measured device + if (bitRead(Settings.pulse_counter_type, i)) { + RtcSettings.pulse_counter[i] = 0xFFFFFFFF; // Set Timer to max in case of no more interrupts due to stall of measured device + } } if (json) { if (header) {