5.0.4 20170505
* Add Sonoff Pow Energy Total up to 40 MWh
* Add command EnergyReset 1|2|3 to reset Energy counters (#406)
* Fix Domoticz Energy logging (#411)
* Add command PowerOnState 4 to keep relay always on and disabling all
power control (#418)
This commit is contained in:
arendst 2017-05-05 17:57:05 +02:00
parent 77da1dfdc1
commit 7ce5b4cba5
7 changed files with 121 additions and 47 deletions

View File

@ -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.0.3** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
Current version is **5.0.4** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
### **** ATTENTION Version 5.0.x specific information ****

Binary file not shown.

View File

@ -1,4 +1,10 @@
/* 5.0.3 20170504
/* 5.0.4 20170505
* Add Sonoff Pow Energy Total up to 40 MWh
* Add command EnergyReset 1|2|3 to reset Energy counters (#406)
* Fix Domoticz Energy logging (#411)
* Add command PowerOnState 4 to keep relay always on and disabling all power control (#418)
*
* 5.0.3 20170504
* Add command SensorRetain on|off to enable retaining of mqtt message tele/sonoff/SENSOR (#74)
* Change WifiConfig timeout from 60 seconds to 180 seconds (#212)
* Change Sonoff Touch command Ledstate functionality by turning led on if power is off (#214)

View File

@ -172,6 +172,9 @@ struct SYSCFG {
// 4.0.9
uint32_t ip_address[4];
// 5.0.4
unsigned long hlw_kWhtotal;
} sysCfg;
struct RTCMEM {
@ -179,6 +182,7 @@ struct RTCMEM {
byte osw_flag;
byte nu1;
unsigned long hlw_kWhtoday;
unsigned long hlw_kWhtotal;
} rtcMem;
// See issue https://github.com/esp8266/Arduino/issues/2913

View File

@ -448,6 +448,10 @@ void CFG_DefaultSet2()
// 5.0.2
CFG_DefaultSet_5_0_2();
// 5.0.4
// sysCfg.hlw_kWhtotal = 0;
rtcMem.hlw_kWhtotal = 0;
}
/********************************************************************************************/
@ -622,7 +626,10 @@ void CFG_Delta()
sysCfg.savedata = SAVE_DATA;
}
if (sysCfg.version < 0x05000400) {
sysCfg.hlw_kWhtotal = 0;
rtcMem.hlw_kWhtotal = 0;
}
sysCfg.version = VERSION;
}
}

View File

@ -10,7 +10,7 @@
* ====================================================
*/
#define VERSION 0x05000300 // 5.0.3
#define VERSION 0x05000400 // 5.0.4
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};
@ -319,31 +319,35 @@ void setLatchingRelay(uint8_t power, uint8_t state)
}
}
void setRelay(uint8_t power)
void setRelay(uint8_t rpower)
{
uint8_t state;
if (4 == sysCfg.poweronstate) { // All on and stay on
power = (1 << Maxdevice) -1;
rpower = power;
}
if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
Serial.write(0xA0);
Serial.write(0x04);
Serial.write(power);
Serial.write(rpower);
Serial.write(0xA1);
Serial.write('\n');
Serial.flush();
}
else if (SONOFF_LED == sysCfg.module) {
sl_setPower(power &1);
sl_setPower(rpower &1);
}
else if (EXS_RELAY == sysCfg.module) {
setLatchingRelay(power, 1);
setLatchingRelay(rpower, 1);
}
else {
for (byte i = 0; i < Maxdevice; i++) {
state = power &1;
state = rpower &1;
if (pin[GPIO_REL1 +i] < 99) {
digitalWrite(pin[GPIO_REL1 +i], rel_inverted[i] ? !state : state);
}
power >>= 1;
rpower >>= 1;
}
}
hlw_setPowerSteadyCounter(2);
@ -949,8 +953,13 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
return;
}
else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 3)) {
if ((data_len > 0) && (payload >= 0) && (payload <= 4)) {
sysCfg.poweronstate = payload;
if (4 == sysCfg.poweronstate) {
for(byte i = 1; i <= Maxdevice; i++) {
do_cmnd_power(i, 1);
}
}
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"PowerOnState\":%d}"), sysCfg.poweronstate);
}
@ -2490,32 +2499,38 @@ void setup()
if (MOTOR == sysCfg.module) {
sysCfg.poweronstate = 1; // Needs always on else in limbo!
}
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
if (0 == sysCfg.poweronstate) { // All off
power = 0;
setRelay(power);
}
else if (1 == sysCfg.poweronstate) { // All on
power = (1 << Maxdevice) -1;
setRelay(power);
}
else if (2 == sysCfg.poweronstate) { // All saved state toggle
power = sysCfg.power & ((1 << Maxdevice) -1) ^ 0xFF;
if (sysCfg.flag.savestate) {
if (4 == sysCfg.poweronstate) { // Allways on
setRelay(power);
} else {
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
switch (sysCfg.poweronstate) {
case 0: // All off
power = 0;
setRelay(power);
break;
case 1: // All on
power = (1 << Maxdevice) -1;
setRelay(power);
break;
case 2: // All saved state toggle
power = sysCfg.power & ((1 << Maxdevice) -1) ^ 0xFF;
if (sysCfg.flag.savestate) {
setRelay(power);
}
break;
case 3: // All saved state
power = sysCfg.power & ((1 << Maxdevice) -1);
if (sysCfg.flag.savestate) {
setRelay(power);
}
break;
}
}
else if (3 == sysCfg.poweronstate) { // All saved state
} else {
power = sysCfg.power & ((1 << Maxdevice) -1);
if (sysCfg.flag.savestate) {
setRelay(power);
}
}
} else {
power = sysCfg.power & ((1 << Maxdevice) -1);
if (sysCfg.flag.savestate) {
setRelay(power);
}
}
blink_powersave = power;

View File

@ -116,15 +116,17 @@ void hlw_200mS()
hlw_fifth_second = 0;
if (hlw_EDcntr) {
hlw_len = 1000000 / hlw_EDcntr;
hlw_len = 10000 / hlw_EDcntr;
hlw_EDcntr = 0;
hlw_temp = (HLW_PREF * sysCfg.hlw_pcal) / hlw_len;
hlw_kWhtoday += (hlw_temp * 100) / 36;
hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / 36;
hlw_kWhtoday += hlw_temp;
rtcMem.hlw_kWhtoday = hlw_kWhtoday;
}
if (rtcTime.Valid) {
if (rtc_loctime() == rtc_midnight()) {
sysCfg.hlw_kWhyesterday = hlw_kWhtoday;
sysCfg.hlw_kWhtotal += (hlw_kWhtoday / 1000);
rtcMem.hlw_kWhtotal = sysCfg.hlw_kWhtotal;
hlw_kWhtoday = 0;
rtcMem.hlw_kWhtoday = hlw_kWhtoday;
hlw_mkwh_state = 3;
@ -174,10 +176,12 @@ void hlw_savestate()
{
sysCfg.hlw_kWhdoy = (rtcTime.Valid) ? rtcTime.DayOfYear : 0;
sysCfg.hlw_kWhtoday = hlw_kWhtoday;
sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal;
}
boolean hlw_readEnergy(byte option, float &ed, uint16_t &e, uint16_t &w, uint16_t &u, float &i, float &c)
boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, uint16_t &u, float &i, float &c)
{
unsigned long cur_kWhtoday = hlw_kWhtoday;
unsigned long hlw_len;
unsigned long hlw_temp;
unsigned long hlw_w;
@ -190,8 +194,10 @@ boolean hlw_readEnergy(byte option, float &ed, uint16_t &e, uint16_t &w, uint16_
//snprintf_P(log, sizeof(log), PSTR("HLW: CF %d, CF1U %d (%d), CF1I %d (%d)"), hlw_cf_plen, hlw_cf1u_plen, hlw_cf1u_pcntmax, hlw_cf1i_plen, hlw_cf1i_pcntmax);
//addLog(LOG_LEVEL_DEBUG, log);
if (hlw_kWhtoday) {
ed = (float)hlw_kWhtoday / 100000000;
et = (float)(rtcMem.hlw_kWhtotal + (cur_kWhtoday / 1000)) / 100000;
if (cur_kWhtoday) {
ed = (float)cur_kWhtoday / 100000000;
} else {
ed = 0;
}
@ -265,6 +271,9 @@ void hlw_init()
hlw_Ecntr = 0;
hlw_EDcntr = 0;
hlw_kWhtoday = (RTC_Valid()) ? rtcMem.hlw_kWhtoday : 0;
if (sysCfg.hlw_kWhtotal > rtcMem.hlw_kWhtotal) {
rtcMem.hlw_kWhtotal = sysCfg.hlw_kWhtotal;
}
hlw_SELflag = 0; // Voltage;
@ -311,6 +320,7 @@ void hlw_margin_chk()
{
char log[LOGSZ];
char svalue[200]; // was MESSZ
float pet;
float ped;
float pi;
float pc;
@ -327,7 +337,7 @@ void hlw_margin_chk()
return;
}
hlw_readEnergy(0, ped, pe, pw, pu, pi, pc);
hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc);
if (power && (sysCfg.hlw_pmin || sysCfg.hlw_pmax || sysCfg.hlw_umin || sysCfg.hlw_umax || sysCfg.hlw_imin || sysCfg.hlw_imax)) {
piv = (uint16_t)(pi * 1000);
@ -473,6 +483,31 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len
}
snprintf_P(svalue, ssvalue, PSTR("{\"CurrentHigh\":\"%d%s\"}"), sysCfg.hlw_imax, (sysCfg.flag.value_units) ? " mA" : "");
}
else if (!strcmp_P(type,PSTR("ENERGYRESET"))) {
if ((data_len > 0) && (payload >= 1) && (payload <= 3)) {
switch (payload) {
case 1:
hlw_kWhtoday = 0;
rtcMem.hlw_kWhtoday = 0;
sysCfg.hlw_kWhtoday = 0;
break;
case 2:
sysCfg.hlw_kWhyesterday = 0;
break;
case 3:
rtcMem.hlw_kWhtotal = 0;
sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal;
break;
}
}
char stemp0[10];
char stemp1[10];
char stemp2[10];
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, sysCfg.flag.energy_resolution, stemp0);
dtostrf((float)rtcMem.hlw_kWhtoday / 100000000, 1, sysCfg.flag.energy_resolution, stemp1);
dtostrf((float)(rtcMem.hlw_kWhtotal + (hlw_kWhtoday / 1000)) / 100000, 1, sysCfg.flag.energy_resolution, stemp2);
snprintf_P(svalue, ssvalue, PSTR("{\"EnergyReset\":{\"Total\":%s, \"Yesterday\":%s, \"Today\":%s}}"), stemp2, stemp0, stemp1);
}
else if (!strcmp_P(type,PSTR("HLWPCAL"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
sysCfg.hlw_pcal = (payload > 9999) ? payload : HLW_PREF_PULSE; // 12530
@ -558,7 +593,9 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
char stemp1[10];
char stemp2[10];
char stemp3[10];
char stemp4[10];
char speriod[20];
float pet;
float ped;
float pi;
float pc;
@ -566,23 +603,24 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
uint16_t pw;
uint16_t pu;
hlw_readEnergy(option, ped, pe, pw, pu, pi, pc);
hlw_readEnergy(option, pet, ped, pe, pw, pu, pi, pc);
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, sysCfg.flag.energy_resolution, stemp0);
dtostrf(ped, 1, sysCfg.flag.energy_resolution, stemp1);
dtostrf(pc, 1, 2, stemp2);
dtostrf(pi, 1, 3, stemp3);
dtostrf(pet, 1, sysCfg.flag.energy_resolution, stemp4);
snprintf_P(speriod, sizeof(speriod), PSTR(", \"Period\":%d"), pe);
snprintf_P(svalue, ssvalue, PSTR("%s\"Yesterday\":%s, \"Today\":%s%s, \"Power\":%d, \"Factor\":%s, \"Voltage\":%d, \"Current\":%s}"),
svalue, stemp0, stemp1, (option) ? speriod : "", pw, stemp2, pu, stemp3);
snprintf_P(svalue, ssvalue, PSTR("%s\"Total\":%s, \"Yesterday\":%s, \"Today\":%s%s, \"Power\":%d, \"Factor\":%s, \"Voltage\":%d, \"Current\":%s}"),
svalue, stemp4, stemp0, stemp1, (option) ? speriod : "", pw, stemp2, pu, stemp3);
#ifdef USE_DOMOTICZ
dtostrf(ped * 1000, 1, 1, stemp1);
dtostrf(pet * 1000, 1, 1, stemp1);
domoticz_sensor4(pw, stemp1);
#endif // USE_DOMOTICZ
}
void hlw_mqttPresent()
{
// {"Time":"2017-03-04T13:37:24", "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000}
// {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000}
char svalue[200]; // was MESSZ
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", "), getDateTime().c_str());
@ -604,7 +642,8 @@ const char HTTP_ENERGY_SNS[] PROGMEM =
"<tr><th>Power</th><td>%d W</td></tr>"
"<tr><th>Power Factor</th><td>%s</td></tr>"
"<tr><th>Energy Today</th><td>%s kWh</td></tr>"
"<tr><th>Energy Yesterday</th><td>%s kWh</td></tr>";
"<tr><th>Energy Yesterday</th><td>%s kWh</td></tr>"
"<tr><th>Energy Total</th><td>%s kWh</td></tr>";
String hlw_webPresent()
{
@ -613,7 +652,9 @@ String hlw_webPresent()
char stemp2[10];
char stemp3[10];
char stemp4[10];
char sensor[300];
char stemp5[10];
char sensor[320];
float pet;
float ped;
float pi;
float pc;
@ -621,13 +662,14 @@ String hlw_webPresent()
uint16_t pw;
uint16_t pu;
hlw_readEnergy(0, ped, pe, pw, pu, pi, pc);
hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc);
dtostrf(pi, 1, 3, stemp);
dtostrf(pc, 1, 2, stemp2);
dtostrf(ped, 1, sysCfg.flag.energy_resolution, stemp3);
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, sysCfg.flag.energy_resolution, stemp4);
snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, pu, stemp, pw, stemp2, stemp3, stemp4);
dtostrf(pet, 1, sysCfg.flag.energy_resolution, stemp5);
snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, pu, stemp, pw, stemp2, stemp3, stemp4, stemp5);
page += sensor;
return page;
}