diff --git a/README.md b/README.md index 792c8af10..efa0760e9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.1.2** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.1.3** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### **** ATTENTION Version 5.x.x specific information **** diff --git a/api/arduino/sonoff.ino.bin b/api/arduino/sonoff.ino.bin index 9725e41c3..52b7f10ab 100644 Binary files a/api/arduino/sonoff.ino.bin and b/api/arduino/sonoff.ino.bin differ diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index b81a7dcdb..c14a67400 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,7 @@ -/* 5.1.2 20170519 +/* 5.1.3 20170520 + * Add Domoticz Counter + * + * 5.1.2 20170519 * Fix Counter/Timer JSON message and update Counter/Timer on webpage * Fix WS2812 Domoticz related regression issues * diff --git a/sonoff/settings.h b/sonoff/settings.h index 4b719efe1..ef244a812 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -197,7 +197,7 @@ struct SYSCFG { char mqtt_fulltopic[101]; // 5.1.1 - unsigned long pCounter[4]; + unsigned long pCounter[MAX_COUNTERS]; uint16_t pCounterType; uint16_t pCounterDebounce; @@ -209,7 +209,7 @@ struct RTCMEM { uint8_t power; unsigned long hlw_kWhtoday; unsigned long hlw_kWhtotal; - unsigned long pCounter[4]; + unsigned long pCounter[MAX_COUNTERS]; } rtcMem; // See issue https://github.com/esp8266/Arduino/issues/2913 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 5b52b7daa..0a7282d3a 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -642,7 +642,7 @@ void CFG_Delta() if (sysCfg.version < 0x05010100) { sysCfg.pCounterType = 0; sysCfg.pCounterDebounce = 0; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_COUNTERS; i++) { sysCfg.pCounter[i] = 0; rtcMem.pCounter[i] = 0; } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 7767e9a40..c022965e2 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -24,7 +24,7 @@ - Select IDE Tools - Flash size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05010200 // 5.1.2 +#define VERSION 0x05010300 // 5.1.3 enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -116,7 +116,7 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; #define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection #define APP_POWER 0 // Default saved power state Off -#define MAX_DEVICE 1 // Max number of devices +#define MAX_COUNTERS 4 // Max number of counter sensors #define MAX_PULSETIMERS 4 // Max number of supported pulse timers #define WS2812_MAX_LEDS 256 // Max number of LEDs @@ -240,7 +240,7 @@ int tele_period = 0; // Tele period timer String Log[MAX_LOG_LINES]; // Web log buffer byte logidx = 0; // Index in Web log buffer byte logajaxflg = 0; // Reset web console log -byte Maxdevice = MAX_DEVICE; // Max number of devices supported +byte Maxdevice = 0; // Max number of devices supported int status_update_timer = 0; // Refresh initial status uint16_t pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer uint16_t blink_timer = 0; // Power cycle timer @@ -251,7 +251,6 @@ uint8_t blink_powersave; // Blink start power save state uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command uint8_t latching_power = 0; // Power state at latching start uint8_t latching_relay_pulse = 0; // Latching relay pulse timer -unsigned long pTimeLast[4]; // Last counter time in milli seconds #ifdef USE_MQTT_TLS WiFiClientSecure espClient; // Wifi Secure Client @@ -1211,14 +1210,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } snprintf_P(svalue, sizeof(svalue), PSTR("%s}}"),svalue); } - else if (!strcmp_P(type,PSTR("COUNTER")) && (index > 0) && (index <= 4)) { + else if (!strcmp_P(type,PSTR("COUNTER")) && (index > 0) && (index <= MAX_COUNTERS)) { if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { rtcMem.pCounter[index -1] = payload16; sysCfg.pCounter[index -1] = payload16; } snprintf_P(svalue, sizeof(svalue), PSTR("{\"Counter%d\":%d}"), index, rtcMem.pCounter[index -1]); } - else if (!strcmp_P(type,PSTR("COUNTERTYPE")) && (index > 0) && (index <= 4)) { + else if (!strcmp_P(type,PSTR("COUNTERTYPE")) && (index > 0) && (index <= MAX_COUNTERS)) { if ((data_len > 0) && (payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) { bitWrite(sysCfg.pCounterType, index -1, payload &1); rtcMem.pCounter[index -1] = 0; @@ -1799,8 +1798,6 @@ void state_mqttPresent(char* svalue, uint16_t ssvalue) void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson) { - char stemp[16]; - snprintf_P(svalue, ssvalue, PSTR("%s{\"Time\":\"%s\""), svalue, getDateTime().c_str()); for (byte i = 0; i < 4; i++) { if (pin[GPIO_SWT1 +i] < 99) { @@ -1809,17 +1806,7 @@ void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson) *djson = 1; } } - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(sysCfg.pCounterType, i)) { - dtostrf((double)rtcMem.pCounter[i] / 1000, 1, 3, stemp); - } else { - dtostrf(rtcMem.pCounter[i], 1, 0, stemp); - } - snprintf_P(svalue, ssvalue, PSTR("%s, \"Counter%d\":%s"), svalue, i +1, stemp); - *djson = 1; - } - } + counter_mqttPresent(svalue, ssvalue, djson); #ifndef USE_ADC_VCC if (pin[GPIO_ADC0] < 99) { snprintf_P(svalue, ssvalue, PSTR("%s, \"AnalogInput0\":%d"), svalue, analogRead(A0)); diff --git a/sonoff/support.ino b/sonoff/support.ino index 01acad6eb..529d3efcc 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -947,70 +947,6 @@ void rtc_init() tickerRTC.attach(1, rtc_second); } -/*********************************************************************************************\ - * Counter sensors (water meters, electricity meters etc.) -\*********************************************************************************************/ - -void counter_update(byte index) -{ -// char log[LOGSZ]; - - unsigned long pTime = millis() - pTimeLast[index -1]; - if (pTime > sysCfg.pCounterDebounce) { - pTimeLast[index -1] = millis(); - if (bitRead(sysCfg.pCounterType, index -1)) { - rtcMem.pCounter[index -1] = pTime; - } else { - rtcMem.pCounter[index -1]++; - } - -// snprintf_P(log, sizeof(log), PSTR("CNTR: Interrupt %d"), index); -// addLog(LOG_LEVEL_DEBUG, log); - } -} - -void counter_update1() -{ - counter_update(1); -} - -void counter_update2() -{ - counter_update(2); -} - -void counter_update3() -{ - counter_update(3); -} - -void counter_update4() -{ - counter_update(4); -} - -void counter_savestate() -{ - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - sysCfg.pCounter[i] = rtcMem.pCounter[i]; - } - } -} - -void counter_init() -{ - typedef void (*function) () ; - function counter_callbacks[] = { counter_update1, counter_update2, counter_update3, counter_update4 }; - - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - pinMode(pin[GPIO_CNTR1 +i], INPUT_PULLUP); - attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); - } - } -} - /*********************************************************************************************\ * Miscellaneous \*********************************************************************************************/ diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 9c21066b7..12f2c630c 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -250,8 +250,6 @@ const char HTTP_TABLE100[] PROGMEM = ""; const char HTTP_COUNTER[] PROGMEM = "
"; -const char HTTP_SNS_COUNTER[] PROGMEM = - ""; const char HTTP_SNS_TEMP[] PROGMEM = ""; const char HTTP_SNS_HUM[] PROGMEM = @@ -450,7 +448,6 @@ void handleRoot() void handleAjax2() { char svalue[16]; - char sensor[80]; if (strlen(webServer->arg("o").c_str())) { do_cmnd_power(atoi(webServer->arg("o").c_str()), 2); @@ -461,17 +458,7 @@ void handleAjax2() } String tpage = ""; - for (byte i = 0; i < 4; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(sysCfg.pCounterType, i)) { - dtostrf((double)rtcMem.pCounter[i] / 1000, 1, 3, svalue); - } else { - dtostrf(rtcMem.pCounter[i], 1, 0, svalue); - } - snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, svalue, (bitRead(sysCfg.pCounterType, i)) ? " Sec" : ""); - tpage += sensor; - } - } + tpage += counter_webPresent(); if (hlw_flg) { tpage += hlw_webPresent(); } diff --git a/sonoff/xdrv_domoticz.ino b/sonoff/xdrv_domoticz.ino index bb63559d0..50fee13e8 100644 --- a/sonoff/xdrv_domoticz.ino +++ b/sonoff/xdrv_domoticz.ino @@ -19,7 +19,7 @@ #ifdef USE_DOMOTICZ -#define DOMOTICZ_MAX_SENSORS 5 +#define DOMOTICZ_MAX_SENSORS 6 #ifdef USE_WEBSERVER const char HTTP_FORM_DOMOTICZ[] PROGMEM = @@ -40,7 +40,7 @@ const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = #endif // USE_WEBSERVER const char domoticz_sensors[DOMOTICZ_MAX_SENSORS][14] PROGMEM = - { "Temp", "Temp,Hum", "Temp,Hum,Baro", "Power,Energy", "Illuminance" }; + { "Temp", "Temp,Hum", "Temp,Hum,Baro", "Power,Energy", "Illuminance", "Count" }; boolean domoticz_subscribe = false; int domoticz_update_timer = 0; @@ -329,6 +329,13 @@ void domoticz_sensor5(uint16_t lux) dom_sensor(4, data); } +void domoticz_sensor6(uint32_t count) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d"), count); + dom_sensor(5, data); +} + /*********************************************************************************************\ * Presentation \*********************************************************************************************/ @@ -400,10 +407,11 @@ void domoticz_saveSettings() sysCfg.domoticz_relay_idx[0], sysCfg.domoticz_relay_idx[1], sysCfg.domoticz_relay_idx[2], sysCfg.domoticz_relay_idx[3], sysCfg.domoticz_update_timer); addLog(LOG_LEVEL_INFO, log); - snprintf_P(log, sizeof(log), PSTR("HTTP: key %d, %d, %d, %d, switch %d, %d, %d, %d, sensor %d, %d, %d, %d, %d"), + snprintf_P(log, sizeof(log), PSTR("HTTP: key %d, %d, %d, %d, switch %d, %d, %d, %d, sensor %d, %d, %d, %d, %d, %d"), sysCfg.domoticz_key_idx[0], sysCfg.domoticz_key_idx[1], sysCfg.domoticz_key_idx[2], sysCfg.domoticz_key_idx[3], sysCfg.domoticz_switch_idx[0], sysCfg.domoticz_switch_idx[1], sysCfg.domoticz_switch_idx[2], sysCfg.domoticz_switch_idx[3], - sysCfg.domoticz_sensor_idx[0], sysCfg.domoticz_sensor_idx[1], sysCfg.domoticz_sensor_idx[2], sysCfg.domoticz_sensor_idx[3], sysCfg.domoticz_sensor_idx[4]); + sysCfg.domoticz_sensor_idx[0], sysCfg.domoticz_sensor_idx[1], sysCfg.domoticz_sensor_idx[2], sysCfg.domoticz_sensor_idx[3], + sysCfg.domoticz_sensor_idx[4], sysCfg.domoticz_sensor_idx[5]); addLog(LOG_LEVEL_INFO, log); } #endif // USE_WEBSERVER diff --git a/sonoff/xsns_counter.ino b/sonoff/xsns_counter.ino new file mode 100644 index 000000000..f940887c9 --- /dev/null +++ b/sonoff/xsns_counter.ino @@ -0,0 +1,139 @@ +/* + xsns_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Sonoff-Tasmota + + Copyright (C) 2017 Maarten Damen and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/*********************************************************************************************\ + * Counter sensors (water meters, electricity meters etc.) +\*********************************************************************************************/ + +unsigned long pTimeLast[MAX_COUNTERS]; // Last counter time in milli seconds + +void counter_update(byte index) +{ +// char log[LOGSZ]; + + unsigned long pTime = millis() - pTimeLast[index -1]; + if (pTime > sysCfg.pCounterDebounce) { + pTimeLast[index -1] = millis(); + if (bitRead(sysCfg.pCounterType, index -1)) { + rtcMem.pCounter[index -1] = pTime; + } else { + rtcMem.pCounter[index -1]++; + } + +// snprintf_P(log, sizeof(log), PSTR("CNTR: Interrupt %d"), index); +// addLog(LOG_LEVEL_DEBUG, log); + } +} + +void counter_update1() +{ + counter_update(1); +} + +void counter_update2() +{ + counter_update(2); +} + +void counter_update3() +{ + counter_update(3); +} + +void counter_update4() +{ + counter_update(4); +} + +void counter_savestate() +{ + for (byte i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + sysCfg.pCounter[i] = rtcMem.pCounter[i]; + } + } +} + +void counter_init() +{ + typedef void (*function) () ; + function counter_callbacks[] = { counter_update1, counter_update2, counter_update3, counter_update4 }; + + for (byte i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + pinMode(pin[GPIO_CNTR1 +i], INPUT_PULLUP); + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + } + } +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +void counter_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson) +{ + char stemp[16]; + + byte dsxflg = 0; + for (byte i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + if (bitRead(sysCfg.pCounterType, i)) { + dtostrf((double)rtcMem.pCounter[i] / 1000, 1, 3, stemp); + } else { + dsxflg++; + dtostrf(rtcMem.pCounter[i], 1, 0, stemp); + } + snprintf_P(svalue, ssvalue, PSTR("%s, \"Counter%d\":%s"), svalue, i +1, stemp); + *djson = 1; +#ifdef USE_DOMOTICZ + if (1 == dsxflg) { + domoticz_sensor6(rtcMem.pCounter[i]); + dsxflg++; + } +#endif // USE_DOMOTICZ + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_COUNTER[] PROGMEM = + ""; + +String counter_webPresent() +{ + String page = ""; + char stemp[16]; + char sensor[80]; + + for (byte i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + if (bitRead(sysCfg.pCounterType, i)) { + dtostrf((double)rtcMem.pCounter[i] / 1000, 1, 3, stemp); + } else { + dtostrf(rtcMem.pCounter[i], 1, 0, stemp); + } + snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, stemp, (bitRead(sysCfg.pCounterType, i)) ? " Sec" : ""); + page += sensor; + } + } + return page; +} +#endif // USE_WEBSERVER + diff --git a/sonoff/xsns_ds18x20.ino b/sonoff/xsns_ds18x20.ino index 5f1ec5aab..a20bb6b91 100644 --- a/sonoff/xsns_ds18x20.ino +++ b/sonoff/xsns_ds18x20.ino @@ -201,7 +201,7 @@ void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson) svalue, stemp1, i +1, dsbstype, ds18x20_address(i).c_str(), stemp2); strcpy(stemp1, ", "); #ifdef USE_DOMOTICZ - if (dsxflg == 1) domoticz_sensor1(stemp2); + if (1 == dsxflg) domoticz_sensor1(stemp2); #endif // USE_DOMOTICZ } }
Counter%d%s%s
%s Temperature%s°%c
Counter%d%s%s