mirror of https://github.com/arendst/Tasmota.git
parent
26d3a8c191
commit
70ccdfe9b9
|
@ -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 ****
|
||||
|
||||
|
|
Binary file not shown.
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -250,8 +250,6 @@ const char HTTP_TABLE100[] PROGMEM =
|
|||
"<table style='width:100%'>";
|
||||
const char HTTP_COUNTER[] PROGMEM =
|
||||
"<br/><div id='t' name='t' style='text-align:center;'></div>";
|
||||
const char HTTP_SNS_COUNTER[] PROGMEM =
|
||||
"<tr><th>Counter%d</th><td>%s%s</td></tr>";
|
||||
const char HTTP_SNS_TEMP[] PROGMEM =
|
||||
"<tr><th>%s Temperature</th><td>%s°%c</td></tr>";
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*********************************************************************************************\
|
||||
* 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 =
|
||||
"<tr><th>Counter%d</th><td>%s%s</td></tr>";
|
||||
|
||||
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
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue