From d6560e89bd10f2d9884d868050636ee24b62c580 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 3 Sep 2019 10:39:51 +0200 Subject: [PATCH 01/40] sml update modbus decoder --- sonoff/xsns_53_sml.ino | 303 +++++++++++++++++++++++++++++------------ 1 file changed, 214 insertions(+), 89 deletions(-) diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index 3e0d56300..d8ac958d3 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -140,6 +140,11 @@ struct METER_DESC { uint16_t flag; int32_t params; char prefix[8]; + int8_t trxpin; + uint8_t tsecs; + char *txmem; + uint8_t index; + uint8_t max_index; }; // meter list , enter new meters here @@ -167,7 +172,7 @@ struct METER_DESC { #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS"}}; + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; const uint8_t meter[]= "1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" "1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" @@ -185,7 +190,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS"}}; + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; const uint8_t meter[]= "1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" "1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" @@ -199,7 +204,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML"}}; + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär const uint8_t meter[]= //0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff @@ -218,7 +223,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML"}}; + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär // verbrauch total const uint8_t meter[]= @@ -236,7 +241,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML"}}; + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär // verbrauch total const uint8_t meter[]= @@ -252,7 +257,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"strom"}}; + [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; const uint8_t meter[]= //0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff "1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" @@ -275,7 +280,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML"}}; + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; const uint8_t meter[]= //0x77,0x07,0x01,0x00,0x01,0x08,0x01,0xff "1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" @@ -291,9 +296,9 @@ const uint8_t meter[]= #define METERS_USED 3 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS"}, // harware serial RX pin - [1]={14,'s',0,SML_BAUDRATE,"SML"}, // GPIO14 software serial - [2]={4,'o',0,SML_BAUDRATE,"OBIS2"}}; // GPIO4 software serial + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, // harware serial RX pin + [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, // GPIO14 software serial + [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; // GPIO4 software serial // 3 Zähler definiert const uint8_t meter[]= @@ -320,8 +325,8 @@ const uint8_t meter[]= #define METERS_USED 2 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1"}, // harware serial RX pin - [1]={14,'o',0,SML_BAUDRATE,"OBIS2"}}; // GPIO14 software serial + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, // harware serial RX pin + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; // GPIO14 software serial // 2 Zähler definiert const uint8_t meter[]= @@ -342,9 +347,9 @@ const uint8_t meter[]= #define METERS_USED 3 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1"}, // harware serial RX pin - [1]={14,'o',0,SML_BAUDRATE,"OBIS2"}, - [2]={1,'o',0,SML_BAUDRATE,"OBIS3"}}; + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, // harware serial RX pin + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, + [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; // 3 Zähler definiert const uint8_t meter[]= @@ -372,7 +377,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'o',0,SML_BAUDRATE,"OBIS"}}; +[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; const uint8_t meter[]= "1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" "1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" @@ -385,7 +390,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 1 struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'s',0,SML_BAUDRATE,"SML"}}; +[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär const uint8_t meter[]= //0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff @@ -407,7 +412,7 @@ const uint8_t meter[]= #undef METERS_USED #define METERS_USED 3 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS"}, // harware serial RX pin + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, // harware serial RX pin [1]={14,'c',0,50,"Gas"}, // GPIO14 gas counter [2]={1,'c',0,10,"Wasser"}}; // water counter @@ -430,9 +435,9 @@ const uint8_t meter[]= #define METERS_USED 3 struct METER_DESC const meter_desc[METERS_USED]={ - [0]={1,'c',0,10,"H20"}, // GPIO1 Wasser Zähler - [1]={4,'c',0,50,"GAS"}, // GPIO4 gas Zähler - [2]={3,'s',0,SML_BAUDRATE,"SML"}}; // SML harware serial RX pin + [0]={1,'c',0,10,"H20",-1,1,0}, // GPIO1 Wasser Zähler + [1]={4,'c',0,50,"GAS",-1,1,0}, // GPIO4 gas Zähler + [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // SML harware serial RX pin const uint8_t meter[]= //----------------------------Wasserzähler--sensor53 c1------------------------------------ @@ -516,7 +521,7 @@ char meter_id[MAX_METERS][METER_ID_SIZE]; #define EBUS_SYNC 0xaa #define EBUS_ESC 0xa9 uint8_t ebus_pos; - +uint8_t mbus_pos; #ifdef USE_MEDIAN_FILTER // median filter, should be odd size @@ -786,32 +791,20 @@ uint8_t dump2log=0; bool Serial_available() { uint8_t num=dump2log&7; - if (num<1 || num>meters_used) return Serial.available(); - if (num==1) { - return Serial.available(); - } else { - return meter_ss[num-1]->available(); - } + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->available(); } uint8_t Serial_read() { uint8_t num=dump2log&7; - if (num<1 || num>meters_used) return Serial.read(); - if (num==1) { - return Serial.read(); - } else { - return meter_ss[num-1]->read(); - } + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->read(); } uint8_t Serial_peek() { uint8_t num=dump2log&7; - if (num<1 || num>meters_used) return Serial.peek(); - if (num==1) { - return Serial.peek(); - } else { - return meter_ss[num-1]->peek(); - } + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->peek(); } void Dump2log(void) { @@ -1154,15 +1147,13 @@ uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ) { void sml_shift_in(uint32_t meters,uint32_t shard) { uint32_t count; - if (meter_desc_p[meters].type!='e') { + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m') { // shift in for (count=0; countread(); + uint8_t iob=(uint8_t)meter_ss[meters]->read(); if (meter_desc_p[meters].type=='o') { smltbuf[meters][SML_BSIZ-1]=iob&0x7f; @@ -1170,6 +1161,13 @@ void sml_shift_in(uint32_t meters,uint32_t shard) { smltbuf[meters][SML_BSIZ-1]=iob; } else if (meter_desc_p[meters].type=='r') { smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='m') { + smltbuf[meters][mbus_pos] = iob; + mbus_pos++; + if (mbus_pos>=9) { + SML_Decode(meters); + mbus_pos=0; + } } else { if (iob==EBUS_SYNC) { // should be end of telegramm @@ -1200,7 +1198,7 @@ void sml_shift_in(uint32_t meters,uint32_t shard) { } } sb_counter++; - if (meter_desc_p[meters].type!='e') SML_Decode(meters); + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m') SML_Decode(meters); } @@ -1211,14 +1209,8 @@ uint32_t meters; for (meters=0; metersavailable()) { - sml_shift_in(meters,0); - } + while (meter_ss[meters]->available()) { + sml_shift_in(meters,0); } } } @@ -1348,7 +1340,8 @@ void SML_Decode(uint8_t index) { } else { // compare value uint8_t found=1; - int32_t ebus_dval=99; + uint32_t ebus_dval=99; + float mbus_dval=99; while (*mp!='@') { if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { if (*mp++!=*cp++) { @@ -1363,7 +1356,7 @@ void SML_Decode(uint8_t index) { found=0; } } else { - // ebus or raw + // ebus mbus or raw // XXHHHHSSUU if (*mp=='x' && *(mp+1)=='x') { //ignore @@ -1379,7 +1372,7 @@ void SML_Decode(uint8_t index) { ebus_dval=val; mp+=2; } - else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s'){ + else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s') { int16_t val = *cp|(*(cp+1)<<8); ebus_dval=val; mp+=4; @@ -1389,7 +1382,15 @@ void SML_Decode(uint8_t index) { int8_t val = *cp++; ebus_dval=val; mp+=2; - } else { + } + else if (*mp=='f' && *(mp+1)=='f' && *(mp+2)=='f' && *(mp+3)=='f' && *(mp+4)=='f' && *(mp+5)=='f' && *(mp+6)=='f' && *(mp+7)=='f') { + uint32_t val= (*(cp+0)<<24)|(*(cp+1)<<16)|(*(cp+2)<<8)|(*(cp+3)<<0); + float *fp=(float*)&val; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else { uint8_t val = hexnibble(*mp++) << 4; val |= hexnibble(*mp++); if (val!=*cp++) { @@ -1418,7 +1419,7 @@ void SML_Decode(uint8_t index) { } } else { double dval; - if (meter_desc_p[mindex].type!='e' && meter_desc_p[mindex].type!='r') { + if (meter_desc_p[mindex].type!='e' && meter_desc_p[mindex].type!='r' && meter_desc_p[mindex].type!='m') { // get numeric values if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { dval=xCharToDouble((char*)cp); @@ -1426,7 +1427,7 @@ void SML_Decode(uint8_t index) { dval=sml_getvalue(cp,mindex); } } else { - // ebus + // ebus or mbus if (*mp=='b') { mp++; uint8_t shift=*mp&7; @@ -1434,7 +1435,23 @@ void SML_Decode(uint8_t index) { ebus_dval&=1; mp+=2; } - dval=ebus_dval; + if (*mp=='i') { + // mbus index + mp++; + uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); + if (mb_index!=meter_desc_p[mindex].index) { + goto nextsect; + } + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); + if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; + if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; + dval=mbus_dval; + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp); + mp++; + } else { + dval=ebus_dval; + } + } #ifdef USE_MEDIAN_FILTER meter_vars[vindex]=median(&sml_mf[vindex],dval); @@ -1782,13 +1799,42 @@ void SML_Init(void) { lp++; script_meter_desc[index].prefix[7]=0; for (uint32_t cnt=0; cnt<8; cnt++) { - if (*lp==SCRIPT_EOL) { + if (*lp==SCRIPT_EOL || *lp==',') { script_meter_desc[index].prefix[cnt]=0; - lp--; break; } script_meter_desc[index].prefix[cnt]=*lp++; } + if (*lp==',') { + lp++; + script_meter_desc[index].trxpin=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].tsecs=strtol(lp,&lp,10); + if (*lp==',') { + lp++; + char txbuff[256]; + uint32_t txlen=0,tx_entries=1; + for (uint32_t cnt=0; cntbegin(meter_desc_p[meters].params)) { meter_ss[meters]->flush(); } - } + if (meter_ss[meters]->hardwareSerial()) { ClaimSerial(); } + } } @@ -1958,25 +2005,102 @@ uint32_t ctime=millis(); } } -#ifdef SML_SEND_SEQ -#define SML_SEQ_PERIOD 5 -uint8_t sml_seq_cnt; -void SendSeq(void) { - sml_seq_cnt++; - if (sml_seq_cnt>SML_SEQ_PERIOD) { - sml_seq_cnt=0; - // send sequence every N Seconds - uint8_t sequence[]={0x2F,0x3F,0x21,0x0D,0x0A,0}; - uint8_t *ucp=sequence; - while (*ucp) { - uint8_t iob=*ucp++; - // for no parity disable next line - iob|=(CalcEvenParity(iob)<<7); - Serial.write(iob); +#ifdef USE_SCRIPT +char *SML_Get_Sequence(char *cp,uint32_t index) { + if (!index) return cp; + uint32_t cindex=0; + while (cp) { + cp=strchr(cp,','); + if (cp) { + cp++; + cindex++; + if (cindex==index) { + return cp; + } } } } +uint8_t sml_250ms_cnt; + + +void SML_Check_Send(void) { + sml_250ms_cnt++; + for (uint32_t cnt=0; cnt=0 && script_meter_desc[cnt].txmem) { + if ((sml_250ms_cnt%script_meter_desc[cnt].tsecs)==0) { + if (script_meter_desc[cnt].max_index>1) { + script_meter_desc[cnt].index++; + if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { + script_meter_desc[cnt].index=0; + } + char *cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); + SML_Send_Seq(cnt,cp); + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),cp); + } else { + SML_Send_Seq(cnt,script_meter_desc[cnt].txmem); + } + } + } + } +} + +uint8_t sml_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + return crc; +} + +// send sequence every N Seconds +void SML_Send_Seq(uint32_t meter,char *seq) { + uint8_t sbuff[32]; + uint8_t *ucp=sbuff,slen; + char *cp=seq; + while (*cp) { + if (!*cp || !*(cp+1)) break; + if (*cp==',') break; + uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); + cp+=2; + *ucp++=iob; + slen++; + if (slen>=sizeof(sbuff)) break; + } + if (script_meter_desc[meter].type=='m') { + *ucp++=0; + *ucp++=2; + // append crc + uint16_t crc = MBUS_calculateCRC(sbuff,6); + *ucp++=lowByte(crc); + *ucp++=highByte(crc); + slen+=4; + } + meter_ss[meter]->write(sbuff,slen); +} +#endif // USE_SCRIPT +/* // for odd parity init with 1 uint8_t CalcEvenParity(uint8_t data) { uint8_t parity=0; @@ -1987,7 +2111,7 @@ uint8_t parity=0; } return parity; } -#endif +*/ // dump to log shows serial data on console @@ -2053,6 +2177,7 @@ void SML_CounterSaveState(void) { + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -2070,11 +2195,11 @@ bool Xsns53(byte function) { if (dump2log) Dump2log(); else SML_Poll(); break; -#ifdef SML_SEND_SEQ - case FUNC_EVERY_SECOND: - SendSeq(); +#ifdef USE_SCRIPT + case FUNC_EVERY_250_MSECOND: + SML_Check_Send(); break; -#endif +#endif // USE_SCRIPT case FUNC_JSON_APPEND: SML_Show(1); break; From d5005e29d93410d51a88399500e3a86b5392fb75 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Tue, 3 Sep 2019 10:54:01 +0200 Subject: [PATCH 02/40] sml update (add modus , optimizations) --- sonoff/xsns_53_sml.ino | 44 +++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index d8ac958d3..b5421c966 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -1740,6 +1740,14 @@ void SML_Init(void) { #ifdef USE_SCRIPT + + for (uint32_t cnt=0;cntM",-2,0); if (meter_script==99) { // use script definition @@ -2056,24 +2064,6 @@ uint8_t sml_hexnibble(char chr) { return rVal; } - -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - return crc; -} - // send sequence every N Seconds void SML_Send_Seq(uint32_t meter,char *seq) { uint8_t sbuff[32]; @@ -2100,6 +2090,24 @@ void SML_Send_Seq(uint32_t meter,char *seq) { meter_ss[meter]->write(sbuff,slen); } #endif // USE_SCRIPT + +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + return crc; +} + /* // for odd parity init with 1 uint8_t CalcEvenParity(uint8_t data) { From d44104135e7194120715c3267236dc93e316bb8a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 21:15:36 +0200 Subject: [PATCH 03/40] Fix turning on/off all power when limit is reached Fix turning on/off all power when limit is reached (#6340) --- sonoff/xdrv_03_energy.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 13c6c1e97..70b6c7eea 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -300,7 +300,7 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); - ExecuteCommandPower(1, POWER_OFF, SRC_MAXPOWER); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); if (!Energy.mplr_counter) { Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; } @@ -322,7 +322,7 @@ void EnergyMarginCheck(void) if (Energy.mplr_counter) { Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - ExecuteCommandPower(1, POWER_ON, SRC_MAXPOWER); + SetAllPower(POWER_ALL_ON, SRC_MAXPOWER); } else { Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); @@ -340,7 +340,7 @@ void EnergyMarginCheck(void) Energy.max_energy_state = 1; Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - ExecuteCommandPower(1, POWER_ON, SRC_MAXENERGY); + SetAllPower(POWER_ALL_ON, SRC_MAXENERGY); } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; @@ -348,7 +348,7 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); - ExecuteCommandPower(1, POWER_OFF, SRC_MAXENERGY); + SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); } } #endif // USE_ENERGY_POWER_LIMIT From b3562e030e2468600adc33a1fae2e24e0e3774c6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 21:53:20 +0200 Subject: [PATCH 04/40] Init Energy Total on energy monitoring devices with Energy Total Register Init Energy Total on energy monitoring devices with Energy Total Register (#6282) --- sonoff/xdrv_03_energy.ino | 16 ++++++++++++++++ sonoff/xnrg_03_pzem004t.ino | 7 +------ sonoff/xnrg_05_pzem_ac.ino | 7 +------ sonoff/xnrg_06_pzem_dc.ino | 7 +------ sonoff/xnrg_09_sdm120.ino | 11 ++--------- 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 70b6c7eea..2b29e0472 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -146,6 +146,22 @@ void EnergyUpdateToday(void) } } +void EnergyUpdateTotal(float value, bool kwh) +{ + uint32_t multiplier = (kwh) ? 100000 : 100; // kWh or Wh to deca milli Wh + + if (0 == Energy.start_energy || (value < Energy.start_energy)) { + Energy.start_energy = value; // Init after restart and handle roll-over if any + RtcSettings.energy_kWhtotal = (unsigned long)(value * multiplier); + Energy.kWhtoday = 0; + } + else if (value != Energy.start_energy) { + Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * multiplier); + Energy.start_energy = value; + } + EnergyUpdateToday(); +} + /*********************************************************************************************/ void Energy200ms(void) diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 4083d9b38..b31f29582 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -181,12 +181,7 @@ void PzemEvery200ms(void) Energy.active_power = value; break; case 4: // Total energy as 99999Wh - if (!Energy.start_energy || (value < Energy.start_energy)) Energy.start_energy = value; // Init after restart and hanlde roll-over if any - if (value != Energy.start_energy) { - Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * 100); - Energy.start_energy = value; - } - EnergyUpdateToday(); + EnergyUpdateTotal(value, false); break; } pzem_read_state++; diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 79f97e508..04f71c524 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -82,12 +82,7 @@ void PzemAcEverySecond(void) Energy.power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh - if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any - if (energy != Energy.start_energy) { - Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100); - Energy.start_energy = energy; - } - EnergyUpdateToday(); + EnergyUpdateTotal(energy, false); // } } } diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 4c8db837d..1ad65a88a 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -61,12 +61,7 @@ void PzemDcEverySecond(void) Energy.active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh - if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any - if (energy != Energy.start_energy) { - Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100); - Energy.start_energy = energy; - } - EnergyUpdateToday(); + EnergyUpdateTotal(energy, false); } } diff --git a/sonoff/xnrg_09_sdm120.ino b/sonoff/xnrg_09_sdm120.ino index 34242b2ca..8640eca9f 100644 --- a/sonoff/xnrg_09_sdm120.ino +++ b/sonoff/xnrg_09_sdm120.ino @@ -94,7 +94,7 @@ void SDM120Every200ms(void) Energy.data_valid = 0; float value; - ((uint8_t*)&value)[3] = buffer[3]; // Get float values + ((uint8_t*)&value)[3] = buffer[3]; // Get float values ((uint8_t*)&value)[2] = buffer[4]; ((uint8_t*)&value)[1] = buffer[5]; ((uint8_t*)&value)[0] = buffer[6]; @@ -129,14 +129,7 @@ void SDM120Every200ms(void) break; case 7: - if (!Energy.start_energy || (value < Energy.start_energy)) { // 484.708 kWh - Energy.start_energy = value; // Init after restart and hanlde roll-over if any - } - if (value != Energy.start_energy) { - Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * 100000); // kWh to deca milli Wh - Energy.start_energy = value; - } - EnergyUpdateToday(); + EnergyUpdateTotal(value, true); // 484.708 kWh break; #ifdef USE_SDM220 From 8e4dd169f380b9c696d1e2420dfbe3934272f644 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 21:56:17 +0200 Subject: [PATCH 05/40] Init Energy Total on energy monitoring devices with Energy Total Register Init Energy Total on energy monitoring devices with Energy Total Register (#6282) --- sonoff/xdrv_03_energy.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 2b29e0472..4ebc1bfa1 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -154,6 +154,7 @@ void EnergyUpdateTotal(float value, bool kwh) Energy.start_energy = value; // Init after restart and handle roll-over if any RtcSettings.energy_kWhtotal = (unsigned long)(value * multiplier); Energy.kWhtoday = 0; + RtcSettings.energy_kWhtoday = 0; } else if (value != Energy.start_energy) { Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * multiplier); From 1478f1624a6f948d77fc597a6f1a6ebbbc66d8e8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 22:22:36 +0200 Subject: [PATCH 06/40] Add restore power state when limiit restored Add restore power state when limiit restored (#6340) --- sonoff/sonoff.ino | 8 ++++++++ sonoff/xdrv_03_energy.ino | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f45411b37..7368294a3 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -598,6 +598,14 @@ void SetAllPower(uint8_t state, int source) } } +void RestoreAllPower(power_t power_set, int source) +{ + if (power != power_set) { + SetDevicePower(power, source); + MqttPublishAllPowerState(); + } +} + void MqttShowPWMState(void) { ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 4ebc1bfa1..d18a62960 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -110,6 +110,8 @@ struct ENERGY { bool max_current_flag = false; #ifdef USE_ENERGY_POWER_LIMIT + power_t mp_last_power = 0; + power_t me_last_power = 0; uint16_t mplh_counter = 0; uint16_t mplw_counter = 0; uint8_t mplr_counter = 0; @@ -317,6 +319,7 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); + Energy.mp_last_power = power; SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); if (!Energy.mplr_counter) { Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; @@ -339,7 +342,7 @@ void EnergyMarginCheck(void) if (Energy.mplr_counter) { Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - SetAllPower(POWER_ALL_ON, SRC_MAXPOWER); + RestoreAllPower(Energy.mp_last_power, SRC_MAXPOWER); } else { Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); @@ -357,7 +360,7 @@ void EnergyMarginCheck(void) Energy.max_energy_state = 1; Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - SetAllPower(POWER_ALL_ON, SRC_MAXENERGY); + RestoreAllPower(Energy.me_last_power, SRC_MAXENERGY); } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; @@ -365,6 +368,7 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); + Energy.me_last_power = power; SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); } } From 41f76c51287fa65388e40770672249ed71cfd08b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 22:27:54 +0200 Subject: [PATCH 07/40] Add restore power state when limit is restored Add restore power state when limit is restored (#6340) --- sonoff/sonoff.ino | 7 ++++--- sonoff/xdrv_03_energy.ino | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 7368294a3..05d72c8d9 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -598,10 +598,11 @@ void SetAllPower(uint8_t state, int source) } } -void RestoreAllPower(power_t power_set, int source) +void RestorePower(power_t power_set, int source) { - if (power != power_set) { - SetDevicePower(power, source); + power_t new_state = power | power_set; + if (power != new_state) { + SetDevicePower(new_state, source); MqttPublishAllPowerState(); } } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index d18a62960..7962c628d 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -342,7 +342,7 @@ void EnergyMarginCheck(void) if (Energy.mplr_counter) { Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - RestoreAllPower(Energy.mp_last_power, SRC_MAXPOWER); + RestorePower(Energy.mp_last_power, SRC_MAXPOWER); } else { Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); @@ -360,7 +360,7 @@ void EnergyMarginCheck(void) Energy.max_energy_state = 1; Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - RestoreAllPower(Energy.me_last_power, SRC_MAXENERGY); + RestorePower(Energy.me_last_power, SRC_MAXENERGY); } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; From 34eed717fae5c6528ef3fae45ab92380c4b3217a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 3 Sep 2019 23:04:49 +0200 Subject: [PATCH 08/40] Add command Power0 0/1/2/Off/On/Toggle to control all power outputs at once Add command Power0 0/1/2/Off/On/Toggle to control all power outputs at once (#6340) --- sonoff/_changelog.ino | 1 + sonoff/support_command.ino | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 06bd9d956..157514766 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -6,6 +6,7 @@ * Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support * Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding * Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report + * Add command Power0 0/1/2/Off/On/Toggle to control all power outputs at once (#6340) * * 6.6.0.8 20190827 * Add Tuya Energy monitoring by Shantur Rathore diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 6c2dc78a8..688ba0c71 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -258,10 +258,19 @@ void CmndPower(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { if ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > 4)) { XdrvMailbox.payload = 9; } -// Settings.flag.device_index_enable = user_index; +// Settings.flag.device_index_enable = XdrvMailbox.usridx; ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); mqtt_data[0] = '\0'; } + else if (0 == XdrvMailbox.index) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + if (2 == XdrvMailbox.payload) { + XdrvMailbox.payload = (power) ? 0 : 1; + } + SetAllPower(XdrvMailbox.payload, SRC_IGNORE); + mqtt_data[0] = '\0'; + } + } } void CmndStatus(void) From 636e8425454df8ee9b6262ff50a923717f140871 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Sep 2019 10:10:25 +0200 Subject: [PATCH 09/40] Restore initial energy total default behaviour regression from yesterday Restore initial energy total default behaviour regression from yesterday --- sonoff/xdrv_03_energy.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 7962c628d..476a9d9ae 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -154,9 +154,9 @@ void EnergyUpdateTotal(float value, bool kwh) if (0 == Energy.start_energy || (value < Energy.start_energy)) { Energy.start_energy = value; // Init after restart and handle roll-over if any - RtcSettings.energy_kWhtotal = (unsigned long)(value * multiplier); - Energy.kWhtoday = 0; - RtcSettings.energy_kWhtoday = 0; +// RtcSettings.energy_kWhtotal = (unsigned long)(value * multiplier); +// Energy.kWhtoday = 0; +// RtcSettings.energy_kWhtoday = 0; } else if (value != Energy.start_energy) { Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * multiplier); From f88e87cfde982bb3bbbfaa27a275777ba0166bf9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Sep 2019 12:20:04 +0200 Subject: [PATCH 10/40] Refactor and document power control Refactor and document power control --- sonoff/sonoff.h | 6 +- sonoff/sonoff.ino | 171 +++++++++++++++++++++------------ sonoff/support_button.ino | 12 +-- sonoff/support_command.ino | 14 +-- sonoff/support_switch.ino | 20 ++-- sonoff/xdrv_02_mqtt.ino | 4 +- sonoff/xdrv_03_energy.ino | 8 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xdrv_22_sonoff_ifan.ino | 2 +- sonoff/xdsp_08_ILI9488.ino | 2 +- sonoff/xdsp_10_RA8876.ino | 2 +- 13 files changed, 149 insertions(+), 98 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 6b0c52ce4..b8bf44814 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -231,7 +231,11 @@ enum EmulationOptions {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESULT_OR_TELE }; -enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, power_nu1, POWER_OFF_NO_STATE, POWER_ON_NO_STATE, power_nu2, POWER_SHOW_STATE }; +enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, + POWER_OFF_NO_STATE = 8, POWER_ON_NO_STATE, POWER_TOGGLE_NO_STATE, + POWER_SHOW_STATE = 16 }; +enum SendKeyPowerOptions { POWER_HOLD = 3, CLEAR_RETAIN = 9 }; +enum SendKeyOptions { KEY_BUTTON, KEY_SWITCH }; enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 05d72c8d9..cced9283d 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -90,6 +90,7 @@ unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer unsigned long blink_timer = 0; // Power cycle timer unsigned long backlog_delay = 0; // Command backlog delay power_t power = 0; // Current copy of Settings.power +power_t last_power = 0; // Last power set state power_t blink_power; // Blink power state power_t blink_mask = 0; // Blink relay active mask power_t blink_powersave; // Blink start power save state @@ -201,7 +202,9 @@ char* Format(char* output, const char* input, int size) } } } - if (!digits) { strlcpy(output, input, size); } + if (!digits) { + strlcpy(output, input, size); + } return output; } @@ -258,7 +261,9 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic } fulltopic.replace(F("#"), ""); fulltopic.replace(F("//"), "/"); - if (!fulltopic.endsWith("/")) fulltopic += "/"; + if (!fulltopic.endsWith("/")) { + fulltopic += "/"; + } snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); return stopic; } @@ -270,7 +275,9 @@ char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic) char* GetStateText(uint8_t state) { - if (state > 3) { state = 1; } + if (state > 3) { + state = 1; + } return Settings.state_text[state]; } @@ -312,7 +319,9 @@ void SetDevicePower(power_t rpower, int source) power_t mask = 1; uint8_t count = 0; for (uint32_t j = 0; j < devices_present; j++) { - if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; } + if ((Settings.interlock[i] & mask) && (rpower & mask)) { + count++; + } mask <<= 1; } if (count > 1) { @@ -323,6 +332,10 @@ void SetDevicePower(power_t rpower, int source) } } + if (rpower) { // Any power set + last_power = rpower; + } + XdrvMailbox.index = rpower; XdrvCall(FUNC_SET_POWER); // Signal power state @@ -353,10 +366,56 @@ void SetDevicePower(power_t rpower, int source) } } +void RestorePower(bool publish_power, int source) +{ + if (power != last_power) { + SetDevicePower(last_power, source); + if (publish_power) { + MqttPublishAllPowerState(); + } + } +} + +void SetAllPower(uint8_t state, int source) +{ +// state 0 = POWER_OFF = Relay Off +// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) +// state 2 = POWER_TOGGLE = Toggle relay +// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState +// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState +// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState +// state 16 = POWER_SHOW_STATE = Show power state + + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE + publish_power = false; + } + if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { + power_t all_on = (1 << devices_present) -1; + switch (state) { + case POWER_OFF: + power = 0; + break; + case POWER_ON: + power = all_on; + break; + case POWER_TOGGLE: + power ^= all_on; // Complement current state + } + SetDevicePower(power, source); + } + if (publish_power) { + MqttPublishAllPowerState(); + } +} + void SetLedPowerIdx(uint8_t led, uint8_t state) { - if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present - if (pin[GPIO_LED2] < 99) { led = 1; } + if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present + if (pin[GPIO_LED2] < 99) { + led = 1; + } } if (pin[GPIO_LED1 + led] < 99) { uint8_t mask = 1 << led; @@ -372,11 +431,11 @@ void SetLedPowerIdx(uint8_t led, uint8_t state) void SetLedPower(uint8_t state) { - if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2 + if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2 SetLedPowerIdx(0, state); } else { power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power + for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power bool tstate = (power & mask); SetLedPowerIdx(i, tstate); mask <<= 1; @@ -395,7 +454,7 @@ void SetLedLink(uint8_t state) { uint8_t led_pin = pin[GPIO_LEDLNK]; uint8_t led_inv = ledlnk_inverted; - if (99 == led_pin) { // Legacy - LED1 is status + if (99 == led_pin) { // Legacy - LED1 is status led_pin = pin[GPIO_LED1]; led_inv = bitRead(led_inverted, 0); } @@ -426,13 +485,13 @@ uint16_t GetPulseTimer(uint8_t index) bool SendKey(uint8_t key, uint8_t device, uint8_t state) { -// key 0 = button_topic -// key 1 = switch_topic -// state 0 = off -// state 1 = on -// state 2 = toggle -// state 3 = hold -// state 9 = clear retain flag +// key 0 = KEY_BUTTON = button_topic +// key 1 = KEY_SWITCH = switch_topic +// state 0 = POWER_OFF = off +// state 1 = POWER_ON = on +// state 2 = POWER_TOGGLE = toggle +// state 3 = POWER_HOLD = hold +// state 9 = CLEAR_RETAIN = clear retain flag char stopic[TOPSZ]; char scommand[CMDSZ]; @@ -442,23 +501,25 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > devices_present)) { device = 1; } // Only allow number of buttons up to number of devices + if (!key && (device > devices_present)) { + device = 1; // Only allow number of buttons up to number of devices + } GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - if (9 == state) { + if (CLEAR_RETAIN == state) { mqtt_data[0] = '\0'; } else { - if ((Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (2 == state)) { - state = ~(power >> (device -1)) &1; + if ((Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (POWER_TOGGLE == state)) { + state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON } snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); } #ifdef USE_DOMOTICZ if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain)); + MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); } #else - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain)); + MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; } else { @@ -474,14 +535,15 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) void ExecuteCommandPower(uint8_t device, uint8_t state, int source) { // device = Relay number 1 and up -// state 0 = Relay Off -// state 1 = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) -// state 2 = Toggle relay -// state 3 = Blink relay -// state 4 = Stop blinking relay -// state 6 = Relay Off and no publishPowerState -// state 7 = Relay On and no publishPowerState -// state 9 = Show power state +// state 0 = POWER_OFF = Relay Off +// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) +// state 2 = POWER_TOGGLE = Toggle relay +// state 3 = POWER_BLINK = Blink relay +// state 4 = POWER_BLINK_STOP = Stop blinking relay +// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState +// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState +// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState +// state 16 = POWER_SHOW_STATE = Show power state // ShowSource(source); @@ -495,16 +557,20 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) } #endif // USE_SONOFF_IFAN - uint8_t publish_power = 1; - if ((POWER_OFF_NO_STATE == state) || (POWER_ON_NO_STATE == state)) { - state &= 1; - publish_power = 0; + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE + publish_power = false; } - if ((device < 1) || (device > devices_present)) device = 1; + if ((device < 1) || (device > devices_present)) { + device = 1; + } active_device = device; - if (device <= MAX_PULSETIMERS) { SetPulseTimer(device -1, 0); } + if (device <= MAX_PULSETIMERS) { + SetPulseTimer(device -1, 0); + } power_t mask = 1 << (device -1); // Device to control if (state <= POWER_TOGGLE) { if ((blink_mask & mask)) { @@ -546,7 +612,9 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) #ifdef USE_KNX KnxUpdatePowerState(device, power); #endif // USE_KNX - if (publish_power && Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } + if (publish_power && Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); } @@ -566,10 +634,14 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) uint8_t flag = (blink_mask & mask); blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); - if (flag) ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state + if (flag) { + ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state + } return; } - if (publish_power) MqttPublishPowerState(device); + if (publish_power) { + MqttPublishPowerState(device); + } } void StopAllPowerBlink(void) @@ -586,27 +658,6 @@ void StopAllPowerBlink(void) } } -void SetAllPower(uint8_t state, int source) -{ - if ((POWER_ALL_OFF == state) || (POWER_ALL_ON == state)) { - power = 0; - if (POWER_ALL_ON == state) { - power = (1 << devices_present) -1; - } - SetDevicePower(power, source); - MqttPublishAllPowerState(); - } -} - -void RestorePower(power_t power_set, int source) -{ - power_t new_state = power | power_set; - if (power != new_state) { - SetDevicePower(new_state, source); - MqttPublishAllPowerState(); - } -} - void MqttShowPWMState(void) { ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); diff --git a/sonoff/support_button.ino b/sonoff/support_button.ino index c32011b42..5c8db5d09 100644 --- a/sonoff/support_button.ino +++ b/sonoff/support_button.ino @@ -165,7 +165,7 @@ void ButtonHandler(void) if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second } if (button_pressed) { - if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } } @@ -174,7 +174,7 @@ void ButtonHandler(void) if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); - if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } } else { @@ -199,14 +199,14 @@ void ButtonHandler(void) if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger - Button.press_counter[button_index] = 0; // Discard button press to disable functionality + Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger + Button.press_counter[button_index] = 0; // Discard button press to disable functionality DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); } } if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold Button.press_counter[button_index] = 0; - SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set + SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set } } else { if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer @@ -241,7 +241,7 @@ void ButtonHandler(void) #if defined(USE_LIGHT) && defined(ROTARY_V1) if (!((0 == button_index) && RotaryButtonPressed())) { #endif - if (single_press && SendKey(0, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set // Success } else { if (Button.press_counter[button_index] < 3) { // Single or Double press diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 688ba0c71..7a79d2d4b 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -257,19 +257,19 @@ void CmndDelay(void) void CmndPower(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { - if ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > 4)) { XdrvMailbox.payload = 9; } + if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { + XdrvMailbox.payload = POWER_SHOW_STATE; + } // Settings.flag.device_index_enable = XdrvMailbox.usridx; ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); mqtt_data[0] = '\0'; } else if (0 == XdrvMailbox.index) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - if (2 == XdrvMailbox.payload) { - XdrvMailbox.payload = (power) ? 0 : 1; - } - SetAllPower(XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; + if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { + XdrvMailbox.payload = POWER_SHOW_STATE; } + SetAllPower(XdrvMailbox.payload, SRC_IGNORE); + mqtt_data[0] = '\0'; } } diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 40bbcc2b9..940fcdb1d 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -143,7 +143,7 @@ void SwitchHandler(uint8_t mode) if (Switch.hold_timer[i]) { Switch.hold_timer[i]--; if (0 == Switch.hold_timer[i]) { - SendKey(1, i +1, 3); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT } } @@ -152,10 +152,10 @@ void SwitchHandler(uint8_t mode) // enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; if (button != Switch.last_state[i]) { - switchflag = 3; + switchflag = POWER_TOGGLE +1; switch (Settings.switchmode[i]) { case TOGGLE: - switchflag = 2; // Toggle + switchflag = POWER_TOGGLE; // Toggle break; case FOLLOW: switchflag = button &1; // Follow wall switch state @@ -165,17 +165,17 @@ void SwitchHandler(uint8_t mode) break; case PUSHBUTTON: if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - switchflag = 2; // Toggle with pushbutton to Gnd + switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd } break; case PUSHBUTTON_INV: if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - switchflag = 2; // Toggle with releasing pushbutton from Gnd + switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd } break; case PUSHBUTTON_TOGGLE: if (button != Switch.last_state[i]) { - switchflag = 2; // Toggle with any pushbutton change + switchflag = POWER_TOGGLE; // Toggle with any pushbutton change } break; case PUSHBUTTONHOLD: @@ -184,7 +184,7 @@ void SwitchHandler(uint8_t mode) } if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { Switch.hold_timer[i] = 0; - switchflag = 2; // Toggle with pushbutton to Gnd + switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd } break; case PUSHBUTTONHOLD_INV: @@ -193,13 +193,13 @@ void SwitchHandler(uint8_t mode) } if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { Switch.hold_timer[i] = 0; - switchflag = 2; // Toggle with pushbutton to Gnd + switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd } break; } - if (switchflag < 3) { - if (!SendKey(1, i +1, switchflag)) { // Execute command via MQTT + if (switchflag <= POWER_TOGGLE) { + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) } } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 10e3eca9c..8de1a3d1e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -894,7 +894,7 @@ void CmndButtonRetain(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { for (uint32_t i = 1; i <= MAX_KEYS; i++) { - SendKey(0, i, 9); // Clear MQTT retain in broker + SendKey(KEY_BUTTON, i, CLEAR_RETAIN); // Clear MQTT retain in broker } } Settings.flag.mqtt_button_retain = XdrvMailbox.payload; @@ -907,7 +907,7 @@ void CmndSwitchRetain(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { - SendKey(1, i, 9); // Clear MQTT retain in broker + SendKey(KEY_SWITCH, i, CLEAR_RETAIN); // Clear MQTT retain in broker } } Settings.flag.mqtt_switch_retain = XdrvMailbox.payload; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 476a9d9ae..f139e46aa 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -110,8 +110,6 @@ struct ENERGY { bool max_current_flag = false; #ifdef USE_ENERGY_POWER_LIMIT - power_t mp_last_power = 0; - power_t me_last_power = 0; uint16_t mplh_counter = 0; uint16_t mplw_counter = 0; uint8_t mplr_counter = 0; @@ -319,7 +317,6 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); - Energy.mp_last_power = power; SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); if (!Energy.mplr_counter) { Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; @@ -342,7 +339,7 @@ void EnergyMarginCheck(void) if (Energy.mplr_counter) { Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - RestorePower(Energy.mp_last_power, SRC_MAXPOWER); + RestorePower(true, SRC_MAXPOWER); } else { Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); @@ -360,7 +357,7 @@ void EnergyMarginCheck(void) Energy.max_energy_state = 1; Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - RestorePower(Energy.me_last_power, SRC_MAXENERGY); + RestorePower(true, SRC_MAXENERGY); } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; @@ -368,7 +365,6 @@ void EnergyMarginCheck(void) Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); - Energy.me_last_power = power; SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); } } diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index e5bd2705f..33acefc76 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -306,7 +306,7 @@ bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg if (device <= MAX_DOMOTICZ_IDX) { if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); MqttPublish(domoticz_in_topic); result = true; } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 674cbfb9b..4b767e77c 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -296,7 +296,7 @@ void TimerEverySecond(void) if (xtimer.days & days) { Settings.timer[i].arm = xtimer.repeat; #if defined(USE_RULES) || defined(USE_SCRIPT) - if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands + if (POWER_BLINK == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); XdrvRulesProcess(); } else diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 73e388fbc..94b320c86 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -575,7 +575,7 @@ void KNX_CB_Action(message_t const &msg, void *arg) else if (chan->type < 17) // Toggle Relays { if (!toggle_inhibit) { - ExecuteCommandPower((chan->type) -8, 2, SRC_KNX); + ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); if (Settings.flag.knx_enable_enhancement) { toggle_inhibit = TOGGLE_INHIBIT_TIME; } diff --git a/sonoff/xdrv_22_sonoff_ifan.ino b/sonoff/xdrv_22_sonoff_ifan.ino index b2d9838f8..0dbb31d50 100644 --- a/sonoff/xdrv_22_sonoff_ifan.ino +++ b/sonoff/xdrv_22_sonoff_ifan.ino @@ -96,7 +96,7 @@ void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) fans = kIFan03Speed[fanspeed]; } for (uint32_t i = 2; i < 5; i++) { - uint8_t state = (fans &1) + 6; // Add no publishPowerState + uint8_t state = (fans &1) + POWER_OFF_NO_STATE; // Add no publishPowerState ExecuteCommandPower(i, state, SRC_IGNORE); // Use relay 2, 3 and 4 fans >>= 1; } diff --git a/sonoff/xdsp_08_ILI9488.ino b/sonoff/xdsp_08_ILI9488.ino index 51cb0fd4c..a4467fcdd 100644 --- a/sonoff/xdsp_08_ILI9488.ino +++ b/sonoff/xdsp_08_ILI9488.ino @@ -165,7 +165,7 @@ if (2 == ili9488_ctouch_counter) { uint8_t bflags=buttons[count]->vpower&0x7f; if (!bflags) { // real button - if (!SendKey(0, count+1, POWER_TOGGLE)) { + if (!SendKey(KEY_BUTTON, count+1, POWER_TOGGLE)) { ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON); } buttons[count]->xdrawButton(bitRead(power,count)); diff --git a/sonoff/xdsp_10_RA8876.ino b/sonoff/xdsp_10_RA8876.ino index d77ed6c00..ff404af56 100644 --- a/sonoff/xdsp_10_RA8876.ino +++ b/sonoff/xdsp_10_RA8876.ino @@ -166,7 +166,7 @@ if (2 == ra8876_ctouch_counter) { uint8_t bflags=buttons[count]->vpower&0x7f; if (!bflags) { // real button - if (!SendKey(0, count+1, POWER_TOGGLE)) { + if (!SendKey(KEY_BUTTON, count+1, POWER_TOGGLE)) { ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON); } buttons[count]->xdrawButton(bitRead(power,count)); From 1304252d0893b468b8e7d4e6e7c1843d586a9c23 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Sep 2019 12:47:58 +0200 Subject: [PATCH 11/40] Refactor sonoff.ino Refactor sonoff.ino --- sonoff/sonoff.ino | 60 +++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index cced9283d..a06dd1170 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -173,7 +173,7 @@ String backlog[MAX_BACKLOG]; // Command backlog char* Format(char* output, const char* input, int size) { char *token; - uint8_t digits = 0; + uint32_t digits = 0; if (strstr(input, "%") != nullptr) { strlcpy(output, input, size); @@ -222,7 +222,7 @@ char* GetOtaUrl(char *otaurl, size_t otaurl_size) return otaurl; } -char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic) +char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) { /* prefix 0 = Cmnd prefix 1 = Stat @@ -268,12 +268,12 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic return stopic; } -char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic) +char* GetFallbackTopic_P(char *stopic, uint32_t prefix, const char* subtopic) { return GetTopic_P(stopic, prefix +4, nullptr, subtopic); } -char* GetStateText(uint8_t state) +char* GetStateText(uint32_t state) { if (state > 3) { state = 1; @@ -283,7 +283,7 @@ char* GetStateText(uint8_t state) /********************************************************************************************/ -void SetLatchingRelay(power_t lpower, uint8_t state) +void SetLatchingRelay(power_t lpower, uint32_t state) { // power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off // power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off @@ -296,7 +296,7 @@ void SetLatchingRelay(power_t lpower, uint8_t state) } for (uint32_t i = 0; i < devices_present; i++) { - uint8_t port = (i << 1) + ((latching_power >> i) &1); + uint32_t port = (i << 1) + ((latching_power >> i) &1); if (pin[GPIO_REL1 +port] < 99) { digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); } @@ -305,8 +305,6 @@ void SetLatchingRelay(power_t lpower, uint8_t state) void SetDevicePower(power_t rpower, int source) { - uint8_t state; - ShowSource(source); if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on @@ -317,7 +315,7 @@ void SetDevicePower(power_t rpower, int source) if (Settings.flag.interlock) { // Allow only one or no relay set for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { power_t mask = 1; - uint8_t count = 0; + uint32_t count = 0; for (uint32_t j = 0; j < devices_present; j++) { if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; @@ -357,7 +355,7 @@ void SetDevicePower(power_t rpower, int source) } else { for (uint32_t i = 0; i < devices_present; i++) { - state = rpower &1; + power_t state = rpower &1; if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); } @@ -376,7 +374,7 @@ void RestorePower(bool publish_power, int source) } } -void SetAllPower(uint8_t state, int source) +void SetAllPower(uint32_t state, int source) { // state 0 = POWER_OFF = Relay Off // state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) @@ -410,7 +408,7 @@ void SetAllPower(uint8_t state, int source) } } -void SetLedPowerIdx(uint8_t led, uint8_t state) +void SetLedPowerIdx(uint32_t led, uint32_t state) { if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present if (pin[GPIO_LED2] < 99) { @@ -418,7 +416,7 @@ void SetLedPowerIdx(uint8_t led, uint8_t state) } } if (pin[GPIO_LED1 + led] < 99) { - uint8_t mask = 1 << led; + uint32_t mask = 1 << led; if (state) { state = 1; led_power |= mask; @@ -429,7 +427,7 @@ void SetLedPowerIdx(uint8_t led, uint8_t state) } } -void SetLedPower(uint8_t state) +void SetLedPower(uint32_t state) { if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2 SetLedPowerIdx(0, state); @@ -443,17 +441,17 @@ void SetLedPower(uint8_t state) } } -void SetLedPowerAll(uint8_t state) +void SetLedPowerAll(uint32_t state) { for (uint32_t i = 0; i < leds_present; i++) { SetLedPowerIdx(i, state); } } -void SetLedLink(uint8_t state) +void SetLedLink(uint32_t state) { - uint8_t led_pin = pin[GPIO_LEDLNK]; - uint8_t led_inv = ledlnk_inverted; + uint32_t led_pin = pin[GPIO_LEDLNK]; + uint32_t led_inv = ledlnk_inverted; if (99 == led_pin) { // Legacy - LED1 is status led_pin = pin[GPIO_LED1]; led_inv = bitRead(led_inverted, 0); @@ -464,26 +462,24 @@ void SetLedLink(uint8_t state) } } -void SetPulseTimer(uint8_t index, uint16_t time) +void SetPulseTimer(uint32_t index, uint32_t time) { pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; } -uint16_t GetPulseTimer(uint8_t index) +uint32_t GetPulseTimer(uint32_t index) { - uint16_t result = 0; - long time = TimePassedSince(pulse_timer[index]); if (time < 0) { time *= -1; - result = (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; + return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; } - return result; + return 0; } /********************************************************************************************/ -bool SendKey(uint8_t key, uint8_t device, uint8_t state) +bool SendKey(uint32_t key, uint32_t device, uint32_t state) { // key 0 = KEY_BUTTON = button_topic // key 1 = KEY_SWITCH = switch_topic @@ -532,7 +528,7 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) return result; } -void ExecuteCommandPower(uint8_t device, uint8_t state, int source) +void ExecuteCommandPower(uint32_t device, uint32_t state, int source) { // device = Relay number 1 and up // state 0 = POWER_OFF = Relay Off @@ -631,7 +627,7 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source) return; } else if (POWER_BLINK_STOP == state) { - uint8_t flag = (blink_mask & mask); + bool flag = (blink_mask & mask); blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); if (flag) { @@ -884,7 +880,7 @@ void Every250mSeconds(void) { // As the max amount of sleep = 250 mSec this loop should always be taken... - uint8_t blinkinterval = 1; + uint32_t blinkinterval = 1; state_250mS++; state_250mS &= 0x3; @@ -1250,10 +1246,10 @@ void SerialInput(void) void GpioInit(void) { - uint8_t mpin; + uint32_t mpin; if (!ValidModule(Settings.module)) { - uint8_t module = MODULE; + uint32_t module = MODULE; if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } Settings.module = module; Settings.last_module = module; @@ -1290,7 +1286,7 @@ void GpioInit(void) my_adc0 = Settings.my_adc0; // Set User selected Module sensors } my_module_flag = ModuleFlag(); - uint8_t template_adc0 = my_module_flag.data &15; + uint32_t template_adc0 = my_module_flag.data &15; if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { my_adc0 = template_adc0; // Force Template override } @@ -1664,8 +1660,6 @@ void setup(void) XsnsCall(FUNC_INIT); } -uint32_t _counter = 0; - void loop(void) { uint32_t my_sleep = millis(); From 138ed6def98160b2f86dbbab8db8f0319c97b7c1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Sep 2019 12:58:37 +0200 Subject: [PATCH 12/40] Refactoring Refactoring --- sonoff/sonoff.ino | 8 ++++---- sonoff/xdrv_01_webserver.ino | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index a06dd1170..abe71d647 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -303,7 +303,7 @@ void SetLatchingRelay(power_t lpower, uint32_t state) } } -void SetDevicePower(power_t rpower, int source) +void SetDevicePower(power_t rpower, uint32_t source) { ShowSource(source); @@ -364,7 +364,7 @@ void SetDevicePower(power_t rpower, int source) } } -void RestorePower(bool publish_power, int source) +void RestorePower(bool publish_power, uint32_t source) { if (power != last_power) { SetDevicePower(last_power, source); @@ -374,7 +374,7 @@ void RestorePower(bool publish_power, int source) } } -void SetAllPower(uint32_t state, int source) +void SetAllPower(uint32_t state, uint32_t source) { // state 0 = POWER_OFF = Relay Off // state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) @@ -528,7 +528,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) return result; } -void ExecuteCommandPower(uint32_t device, uint32_t state, int source) +void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) { // device = Relay number 1 and up // state 0 = POWER_OFF = Relay Off diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c50bef2da..01f5cde34 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -500,7 +500,7 @@ static bool WifiIsInManagerMode(){ return (HTTP_MANAGER == Web.state || HTTP_MANAGER_RESET_ONLY == Web.state); } -void ShowWebSource(int source) +void ShowWebSource(uint32_t source) { if ((source > 0) && (source < SRC_MAX)) { char stemp1[20]; @@ -508,7 +508,7 @@ void ShowWebSource(int source) } } -void ExecuteWebCommand(char* svalue, int source) +void ExecuteWebCommand(char* svalue, uint32_t source) { ShowWebSource(source); ExecuteCommand(svalue, SRC_IGNORE); From af1edb0cdb351b1d74f8ee23630bab0ab829888c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Sep 2019 18:06:34 +0200 Subject: [PATCH 13/40] Add command Time 1/2/3 to select JSON time format ISO + Epoch, ISO or Epoch * Add time to more events (#6337) * Add command Time 1/2/3 to select JSON time format ISO + Epoch, ISO or Epoch --- sonoff/_changelog.ino | 2 ++ sonoff/settings.h | 3 +-- sonoff/sonoff.ino | 2 +- sonoff/support.ino | 43 +++++++++++++++++++++++++++----- sonoff/support_command.ino | 19 ++++++++++++-- sonoff/xdrv_03_energy.ino | 13 +++++----- sonoff/xdrv_05_irremote.ino | 2 +- sonoff/xdrv_05_irremote_full.ino | 2 +- sonoff/xdrv_06_snfbridge.ino | 5 ++-- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_15_pca9685.ino | 3 +-- sonoff/xdrv_17_rcswitch.ino | 2 +- sonoff/xdrv_23_zigbee_impl.ino | 10 ++++---- sonoff/xdsp_08_ILI9488.ino | 3 +-- sonoff/xdsp_10_RA8876.ino | 3 +-- sonoff/xsns_29_mcp230xx.ino | 12 +++------ sonoff/xsns_40_pn532.ino | 12 +++------ sonoff/xsns_44_sps30.ino | 3 +-- sonoff/xsns_51_rdm6300.ino | 3 +-- sonoff/xsns_52_ibeacon.ino | 3 +-- sonoff/xsns_53_sml.ino | 12 +++------ 21 files changed, 95 insertions(+), 64 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 157514766..4e79a7200 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,8 @@ * Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding * Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report * Add command Power0 0/1/2/Off/On/Toggle to control all power outputs at once (#6340) + * Add time to more events (#6337) + * Add command Time 1/2/3 to select JSON time format ISO + Epoch, ISO or Epoch * * 6.6.0.8 20190827 * Add Tuya Energy monitoring by Shantur Rathore diff --git a/sonoff/settings.h b/sonoff/settings.h index 20b3202b6..f326dc529 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -105,8 +105,7 @@ typedef union { uint32_t spare01 : 1; uint32_t spare02 : 1; uint32_t spare03 : 1; - uint32_t spare04 : 1; - uint32_t spare05 : 1; + uint32_t time_format : 2; // (v6.6.0.9) - CMND_TIME uint32_t calc_resolution : 3; uint32_t weight_resolution : 2; uint32_t frequency_resolution : 2; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index abe71d647..f6641e5ce 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1234,7 +1234,7 @@ void SerialInput(void) if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_in_byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), + ResponseTime_P(PSTR(",\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/support.ino b/sonoff/support.ino index 4ada71ad2..e6707510e 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -870,7 +870,24 @@ uint32_t WebColor(uint32_t i) * Response data handling \*********************************************************************************************/ -int Response_P(const char* format, ...) // Content send snprintf_P char data +const uint16_t TIMESZ = 100; // Max number of characters in time string + +char* ResponseGetTime(uint32_t format, char* time_str) +{ + switch (format) { + case 1: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + break; + case 2: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); + break; + default: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); + } + return time_str; +} + +int Response_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed va_list args; @@ -880,6 +897,20 @@ int Response_P(const char* format, ...) // Content send snprintf_P char data return len; } +int ResponseTime_P(const char* format, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list args; + va_start(args, format); + + ResponseGetTime(Settings.flag2.time_format, mqtt_data); + + int mlen = strlen(mqtt_data); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + va_end(args); + return len + mlen; +} + int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed @@ -891,15 +922,15 @@ int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char d return len + mlen; } -int ResponseAppendTime(void) +int ResponseAppendTimeFormat(uint32_t format) { - return ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); + char time_str[TIMESZ]; + return ResponseAppend_P(ResponseGetTime(format, time_str)); } -int ResponseBeginTime(void) +int ResponseAppendTime(void) { - mqtt_data[0] = '\0'; - return ResponseAppendTime(); + return ResponseAppendTimeFormat(Settings.flag2.time_format); } int ResponseJsonEnd(void) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 7a79d2d4b..1b91dc11b 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -1276,10 +1276,25 @@ void CmndReset(void) void CmndTime(void) { +// payload 0 = (re-)enable NTP +// payload 1 = Time format {"Time":"2019-09-04T14:31:29","Epoch":1567600289} +// payload 2 = Time format {"Time":"2019-09-04T14:31:29"} +// payload 3 = Time format {"Time":1567600289} +// payload 4 = reserved +// payload 1451602800 - disable NTP and set time to epoch + + uint32_t format = Settings.flag2.time_format; if (XdrvMailbox.data_len > 0) { - RtcSetTime(XdrvMailbox.payload); + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + Settings.flag2.time_format = XdrvMailbox.payload -1; + format = Settings.flag2.time_format; + } else { + format = 0; // {"Time":"2019-09-04T14:31:29","Epoch":1567600289} + RtcSetTime(XdrvMailbox.payload); + } } - ResponseBeginTime(); + mqtt_data[0] = '\0'; + ResponseAppendTimeFormat(format); ResponseJsonEnd(); } diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index f139e46aa..d5e814a47 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -314,7 +314,7 @@ void EnergyMarginCheck(void) } else { Energy.mplh_counter--; if (!Energy.mplh_counter) { - Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); @@ -337,11 +337,11 @@ void EnergyMarginCheck(void) if (Energy.mplr_counter) { Energy.mplr_counter--; if (Energy.mplr_counter) { - Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); RestorePower(true, SRC_MAXPOWER); } else { - Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); } @@ -355,14 +355,14 @@ void EnergyMarginCheck(void) energy_daily_u = (uint16_t)(Energy.daily * 1000); if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { Energy.max_energy_state = 1; - Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); RestorePower(true, SRC_MAXENERGY); } else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { Energy.max_energy_state = 2; dtostrfd(Energy.daily, 3, mqtt_data); - Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); @@ -376,9 +376,10 @@ void EnergyMarginCheck(void) void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} - ResponseBeginTime(); int tele_period_save = tele_period; tele_period = 2; + mqtt_data[0] = '\0'; + ResponseAppendTime(); EnergyShow(true); tele_period = tele_period_save; ResponseJsonEnd(); diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 59b152a32..cc0614264 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -154,7 +154,7 @@ void IrReceiveCheck(void) } else { snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); } - Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, svalue); if (Settings.flag3.receive_raw) { diff --git a/sonoff/xdrv_05_irremote_full.ino b/sonoff/xdrv_05_irremote_full.ino index 4d64e31e4..3c82bee21 100644 --- a/sonoff/xdrv_05_irremote_full.ino +++ b/sonoff/xdrv_05_irremote_full.ino @@ -220,7 +220,7 @@ void IrReceiveCheck(void) // if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { ir_lasttime = now; - Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); if (Settings.flag3.receive_raw) { ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index c7b57c0c1..67ca582fb 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -214,7 +214,7 @@ void SonoffBridgeReceivedRaw(void) if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing - Response_P(PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); for (uint32_t i = 0; i < serial_in_byte_counter; i++) { ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); if (0xB1 == serial_in_buffer[1]) { @@ -226,6 +226,7 @@ void SonoffBridgeReceivedRaw(void) } ResponseAppend_P(PSTR("\"}}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); + XdrvRulesProcess(); } @@ -294,7 +295,7 @@ void SonoffBridgeReceived(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); } - Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), sync_time, low_time, high_time, stemp, rfkey); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index 98bb6a830..8a0543858 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -71,7 +71,7 @@ void SerialBridgeInput(void) if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), + ResponseTime_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 906207851..fb1a923d5 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -166,8 +166,7 @@ bool PCA9685_Command(void) void PCA9685_OutputTelemetry(bool telemetry) { if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); + ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); for (uint32_t pin=0;pin<16;pin++) { ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 902304f0b..9d6d33660 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -67,7 +67,7 @@ void RfReceiveCheck(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); } - Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), stemp, bits, protocol, delay); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdrv_23_zigbee_impl.ino b/sonoff/xdrv_23_zigbee_impl.ino index 1f44a7ab5..1653ed78c 100644 --- a/sonoff/xdrv_23_zigbee_impl.ino +++ b/sonoff/xdrv_23_zigbee_impl.ino @@ -156,10 +156,10 @@ public: void publishMQTTReceived(void) { char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZCLRECEIVED "\":{\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), - _frame_control, _manuf_code, _transact_seq, _cmd_id, - hex_char); + ResponseTime_P(PSTR(",\"" D_JSON_ZIGBEEZCLRECEIVED "\":{\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), + _frame_control, _manuf_code, _transact_seq, _cmd_id, + hex_char); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLSENT)); XdrvRulesProcess(); } @@ -834,7 +834,7 @@ void ZigbeeInput(void) SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); // remove SOF, LEN and FCS ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); + ResponseTime_P(PSTR(",\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED)); XdrvRulesProcess(); diff --git a/sonoff/xdsp_08_ILI9488.ino b/sonoff/xdsp_08_ILI9488.ino index a4467fcdd..da20efbcb 100644 --- a/sonoff/xdsp_08_ILI9488.ino +++ b/sonoff/xdsp_08_ILI9488.ino @@ -124,8 +124,7 @@ void ILI9488_InitDriver() #ifdef USE_TOUCH_BUTTONS void ILI9488_MQTT(uint8_t count,const char *cp) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"RA8876\":{\"%s%d\":\"%d\"}}"), mqtt_data,cp,count+1,(buttons[count]->vpower&0x80)>>7); + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } // check digitizer hit diff --git a/sonoff/xdsp_10_RA8876.ino b/sonoff/xdsp_10_RA8876.ino index ff404af56..2abeda94b 100644 --- a/sonoff/xdsp_10_RA8876.ino +++ b/sonoff/xdsp_10_RA8876.ino @@ -109,8 +109,7 @@ void RA8876_InitDriver() #ifdef USE_TOUCH_BUTTONS void RA8876_MQTT(uint8_t count,const char *cp) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"RA8876\":{\"%s%d\":\"%d\"}}"), mqtt_data,cp,count+1,(buttons[count]->vpower&0x80)>>7); + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index cd4973458..caefb67e8 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -303,8 +303,7 @@ void MCP230xx_CheckForInterrupt(void) { break; } if (int_tele) { - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); } @@ -730,8 +729,7 @@ void MCP230xx_OutputTelemetry(void) { } if (outputcount) { char stt[7]; - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"MCP230_OUT\":{")); + ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); @@ -746,8 +744,7 @@ void MCP230xx_OutputTelemetry(void) { #endif // USE_MCP230xx_OUTPUT void MCP230xx_Interrupt_Counter_Report(void) { - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"MCP230_INTTIMER\":{")); + ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); @@ -761,8 +758,7 @@ void MCP230xx_Interrupt_Counter_Report(void) { void MCP230xx_Interrupt_Retain_Report(void) { uint16_t retainresult = 0; - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"MCP_INTRETAIN\":{")); + ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_retain_flag) { ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index 17527aa7e..333ae7524 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -494,12 +494,10 @@ void PN532_ScanForTag(void) pn532_function = 0; #endif // USE_PN532_DATA_FUNCTION - ResponseBeginTime(); - #ifdef USE_PN532_DATA_FUNCTION - ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); #else - ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); #endif // USE_PN532_DATA_FUNCTION MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -541,8 +539,7 @@ bool PN532_Command(void) if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) { pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00... AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased")); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"PN532\":{\"COMMAND\":\"E\"}}")); + ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"E\"}}")); return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) { @@ -558,8 +555,7 @@ bool PN532_Command(void) pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string pn532_function = 2; AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); + ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); return serviced; } } diff --git a/sonoff/xsns_44_sps30.ino b/sonoff/xsns_44_sps30.ino index 1b1434044..20dc8a8f0 100644 --- a/sonoff/xsns_44_sps30.ino +++ b/sonoff/xsns_44_sps30.ino @@ -253,8 +253,7 @@ void SPS30_Show(bool json) { void CmdClean(void) { sps30_cmd(SPS_CMD_CLEAN); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); + ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xsns_51_rdm6300.ino b/sonoff/xsns_51_rdm6300.ino index 7fc168d7d..2a42b2a08 100644 --- a/sonoff/xsns_51_rdm6300.ino +++ b/sonoff/xsns_51_rdm6300.ino @@ -106,8 +106,7 @@ void RDM6300_ScanForTag() { memcpy(rdm_uid_str,&rdm_buffer[2],8); rdm_uid_str[9]=0; - Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - ResponseAppend_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); /* char command[24]; diff --git a/sonoff/xsns_52_ibeacon.ino b/sonoff/xsns_52_ibeacon.ino index dbd56abd1..1df541d82 100644 --- a/sonoff/xsns_52_ibeacon.ino +++ b/sonoff/xsns_52_ibeacon.ino @@ -547,8 +547,7 @@ void ibeacon_mqtt(const char *mac,const char *rssi) { memcpy(s_rssi,rssi,4); s_rssi[4]=0; int16_t n_rssi=atoi(s_rssi); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"" D_CMND_IBEACON "_%s\":{\"RSSI\":%d}}"),s_mac,n_rssi); + ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "_%s\":{\"RSSI\":%d}}"),s_mac,n_rssi); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xsns_53_sml.ino b/sonoff/xsns_53_sml.ino index b5421c966..9dabb29cd 100644 --- a/sonoff/xsns_53_sml.ino +++ b/sonoff/xsns_53_sml.ino @@ -1505,8 +1505,7 @@ void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex) { if (dp&0x10) { // immediate mqtt dtostrfd(meter_vars[index],dp&0xf,tpowstr); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%s}}"),meter_desc_p[mindex].prefix,jname,tpowstr); + ResponseTime_P(PSTR(",\"%s\":{\"%s\":%s}}"),meter_desc_p[mindex].prefix,jname,tpowstr); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } } @@ -2136,8 +2135,7 @@ bool XSNS_53_cmd(void) { // set dump mode cp++; dump2log=atoi(cp); - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); } else if (*cp=='c') { // set ounter cp++; @@ -2157,12 +2155,10 @@ bool XSNS_53_cmd(void) { } } } - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"counter%d: %d\"}}"),index,RtcSettings.pulse_counter[index-1]); + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"counter%d: %d\"}}"),index,RtcSettings.pulse_counter[index-1]); } else if (*cp=='r') { // restart - ResponseBeginTime(); - ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"restart\"}}")); + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"restart\"}}")); SML_CounterSaveState(); SML_Init(); } else { From efd1870d5ec5f7704ddbd3809c7e7487f510b0b7 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 3 Sep 2019 11:23:44 +0100 Subject: [PATCH 14/40] Tuya: Make Tuya Mcu implementation more configurable. More and more Tuya MCU based devices are coming in the market and people requesting to support them. This patch makes Tuya module more configurable and easier to add new functionalities. Its not just a dimmer or a switch anymore. After this Patch Tuya MCU module has a list of supported functions and the user would need to map the functionId to dpId of their device. Once mapped correctly the Tuya module will take care for handling proper function for dpId. Currently functions supported are 1. Relays1 to 8 : FunctionID 11 to 18 2. Dimmer : FunctionID 21 3. Power ( Deca Watt ) : Function ID 31 4. Current ( milli Amps ) : Function ID 32 5. Voltage ( deca Volts ) : Function ID 33 The changes are - Use a TuyaMCU command to map DPs to Functions instead of many different SetOptions. SetOption41, 44, 45, 46, 65 won't be needed after this patch. - TuyaMCU command takes argument like `11,1` which means Map Function id 11 (Relay1) to DPID 1 - Migrates old settings flags and options to new TuyaMap command --- sonoff/i18n.h | 4 + sonoff/settings.h | 11 +- sonoff/settings.ino | 35 +++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_16_tuyadimmer.ino | 257 ++++++++++++++++++++++++++-------- 5 files changed, 249 insertions(+), 60 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 463ec13cf..287476dd7 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -444,6 +444,10 @@ #define D_CMND_LATITUDE "Latitude" #define D_CMND_LONGITUDE "Longitude" +// Commands xdrv_16_tuyadimmer.ino + +#define D_CMND_TUYA_MCU "TuyaMCU" + // Commands xdrv_23_zigbee.ino #define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend" #define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived" diff --git a/sonoff/settings.h b/sonoff/settings.h index f326dc529..bc8564cca 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -185,6 +185,14 @@ typedef struct { uint32_t last_return_kWhtotal; } EnergyUsage; + +typedef struct { + uint8_t fnid = 0; + uint8_t dpid = 0; +} TuyaFnidDpidMap; + +const uint8_t MAX_TUYA_FUNCTIONS = 16; + /* struct SYSCFG { unsigned long cfg_holder; // 000 Pre v6 header @@ -366,8 +374,9 @@ struct SYSCFG { char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b uint8_t data8[32]; // E00 uint16_t data16[16]; // E20 + TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E40 32 bytes - uint8_t free_e20[448]; // E40 + uint8_t free_e20[416]; // E60 // FFF last location } Settings; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 4bdae99ff..7c44bf053 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1096,6 +1096,41 @@ void SettingsDelta(void) Settings.sbaudrate = Settings.ex_sbaudrate * 4; } + if (Settings.version < 0x0606000A) { + uint8_t tuyaindex = 0; + if (Settings.param[P_TUYA_DIMMER_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 21; //TUYA_MCU_FUNC_DIMMER; // Move Tuya Dimmer Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_DIMMER_ID]; + tuyaindex++; + } else if (Settings.flag3.tuya_disable_dimmer == 1) { + Settings.tuya_fnid_map[tuyaindex].fnid = 11; //TUYA_MCU_FUNC_REL1; // Create FnID for Switches + Settings.tuya_fnid_map[tuyaindex].dpid = 1; + tuyaindex++; + } + if (Settings.param[P_TUYA_RELAYS] > 0) { + for (uint8_t i = 0 ; i < Settings.param[P_TUYA_RELAYS]; i++) { + Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; //TUYA_MCU_FUNC_REL2+; // Create FnID for Switches + Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; + tuyaindex++; + } + } + if (Settings.param[P_TUYA_POWER_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 31; //TUYA_MCU_FUNC_POWER; // Move Tuya Power Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_POWER_ID]; + tuyaindex++; + } + if (Settings.param[P_TUYA_VOLTAGE_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 33; //TUYA_MCU_FUNC_VOLTAGE; // Move Tuya Voltage Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_VOLTAGE_ID]; + tuyaindex++; + } + if (Settings.param[P_TUYA_CURRENT_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 32; //TUYA_MCU_FUNC_CURRENT; // Move Tuya Current Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_CURRENT_ID]; + tuyaindex++; + } + + } Settings.version = VERSION; SettingsSave(1); } diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index e614fbf36..962434a63 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060009; +const uint32_t VERSION = 0x0606000A; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 608236f4b..452a65346 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -61,10 +61,130 @@ struct TUYA { int byte_counter = 0; // Index in serial receive buffer } Tuya; + +enum TuyaSupportedFunctions { + TUYA_MCU_FUNC_NONE, + // TUYA_MCU_FUNC_KEY1 = 1, // Buttons + // TUYA_MCU_FUNC_KEY2, + // TUYA_MCU_FUNC_KEY3, + // TUYA_MCU_FUNC_KEY4, + TUYA_MCU_FUNC_REL1 = 11, // Relays + TUYA_MCU_FUNC_REL2, + TUYA_MCU_FUNC_REL3, + TUYA_MCU_FUNC_REL4, + TUYA_MCU_FUNC_REL5, + TUYA_MCU_FUNC_REL6, + TUYA_MCU_FUNC_REL7, + TUYA_MCU_FUNC_REL8, + TUYA_MCU_FUNC_DIMMER = 21, + TUYA_MCU_FUNC_POWER = 31, + TUYA_MCU_FUNC_CURRENT, + TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_LAST = 255 +}; + +const char kTuyaCommand[] PROGMEM = "|" // No prefix + D_CMND_TUYA_MCU; + +void (* const TuyaCommand[])(void) PROGMEM = { + &CmndTuyaMcu +}; + + +/* + +TuyaMap fnid,dpid + +*/ + +void CmndTuyaMcu(void) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint8_t parm[3] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + + if (TuyaFuncIdValid(parm[0])) { + TuyaAddMcuFunc(parm[0], parm[1]); + restart_flag = 2; + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); + } + + } + + Response_P(PSTR("[")); + bool added = false; + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"fnId\":%d, \"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); + added = true; + } + } + ResponseAppend_P(PSTR("]")); +} + /*********************************************************************************************\ * Internal Functions \*********************************************************************************************/ +void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { + bool added = false; + + if (fnId == 0 || dpId == 0) { // Delete entry + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + break; + } + } + } else { // Add or update + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { + if (!added) { // Update entry if exisiting entry or add + Settings.tuya_fnid_map[i].fnid = fnId; + Settings.tuya_fnid_map[i].dpid = dpId; + added = true; + } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { // Remove existing entry if added to empty place + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + } + } + } + } +} + +inline bool TuyaFuncIdValid(uint8_t fnId) { + return (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || + fnId == TUYA_MCU_FUNC_DIMMER || + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE); +} + +uint8_t TuyaGetFuncId(uint8_t dpid) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpid) { + return Settings.tuya_fnid_map[i].fnid; + } + } + return TUYA_MCU_FUNC_NONE; +} + +uint8_t TuyaGetDpId(uint8_t fnId) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid == fnId) { + return Settings.tuya_fnid_map[i].dpid; + } + } + return 0; +} + void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) { uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); @@ -146,24 +266,26 @@ bool TuyaSetChannels(void) void LightSerialDuty(uint8_t duty) { - if (duty > 0 && !Tuya.ignore_dim && TuyaSerial) { + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); + if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - if (Settings.flag3.tuya_disable_dimmer == 0) { duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); if (Tuya.new_dim != duty) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); - TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + TuyaSendValue(dpid, duty); } } - } else { + } else if (dpid > 0) { Tuya.ignore_dim = false; // reset flag if (Settings.flag3.tuya_disable_dimmer == 0) { duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set } + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); // } } @@ -189,6 +311,7 @@ void TuyaResetWifi(void) void TuyaPacketProcess(void) { char scmnd[20]; + uint8_t fnId = TUYA_MCU_FUNC_NONE; switch (Tuya.buffer[3]) { @@ -201,57 +324,60 @@ void TuyaPacketProcess(void) break; case TUYA_CMD_STATE: - if (Tuya.buffer[5] == 5) { // on/off packet + fnId = TuyaGetFuncId(Tuya.buffer[6]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]); + // if (TuyaFuncIdValid(fnId)) { + if (Tuya.buffer[5] == 5) { // on/off packet - /*if ((power || Settings.light_dimmer > 0) && (power != Tuya.buffer[10])) { - ExecuteCommandPower(1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - }*/ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Device-%d --> MCU State: %s Current State:%s"),Tuya.buffer[6],Tuya.buffer[10]?"On":"Off",bitRead(power, Tuya.buffer[6]-1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, Tuya.buffer[6]-1))) { - ExecuteCommandPower(Tuya.buffer[6], Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } - else if (Tuya.buffer[5] == 8) { // Long value packet - - if (Settings.flag3.tuya_disable_dimmer == 0) { - if (!Settings.param[P_TUYA_DIMMER_ID]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]); - Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6]; - } - if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); - Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Device-%d --> MCU State: %s Current State:%s"),Tuya.buffer[6],Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } + } + else if (Tuya.buffer[5] == 8) { // Long value packet + if (fnId == TUYA_MCU_FUNC_DIMMER) { + // if (!Settings.param[P_TUYA_DIMMER_ID]) { + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]); + // Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6]; + // } + // if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); + Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; -#ifdef USE_ENERGY_SENSOR - if (Settings.param[P_TUYA_VOLTAGE_ID] == Tuya.buffer[6]) { - Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Settings.param[P_TUYA_VOLTAGE_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - } else if (Settings.param[P_TUYA_CURRENT_ID] == Tuya.buffer[6]) { - Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Settings.param[P_TUYA_CURRENT_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - } else if (Settings.param[P_TUYA_POWER_ID] == Tuya.buffer[6]) { - Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Settings.param[P_TUYA_POWER_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); - - if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) { - Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; - EnergyUpdateToday(); + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } + // } } - Tuya.lastPowerCheckTime = Rtc.utc_time; - } else if (Settings.param[P_TUYA_DIMMER_ID] != Tuya.buffer[6]){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Unknown ID=%d"), Tuya.buffer[6]); - } -#endif // USE_ENERGY_SENSOR - } + #ifdef USE_ENERGY_SENSOR + else if (fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + } else if (fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) { + Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; + } + #endif // USE_ENERGY_SENSOR + + } + // } else { + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]); + // } break; case TUYA_CMD_WIFI_RESET: @@ -266,9 +392,9 @@ void TuyaPacketProcess(void) break; case TUYA_CMD_MCU_CONF: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); - if (Tuya.buffer[5] == 2) { + if (Tuya.buffer[5] == 2) { // Processing by ESP module mode uint8_t led1_gpio = Tuya.buffer[6]; uint8_t key1_gpio = Tuya.buffer[7]; bool key1_set = false; @@ -307,7 +433,17 @@ bool TuyaModuleSelected(void) Settings.my_gp.io[3] = GPIO_TUYA_RX; restart_flag = 2; } - if (Settings.flag3.tuya_disable_dimmer == 0) { + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_REL1) == 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + SettingsSaveAll(); + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { light_type = LT_SERIAL1; } else { light_type = LT_BASIC; @@ -318,10 +454,12 @@ bool TuyaModuleSelected(void) void TuyaInit(void) { - devices_present += Settings.param[P_TUYA_RELAYS]; // SetOption41 - Add virtual relays if present - if (!Settings.param[P_TUYA_DIMMER_ID]) { - Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; + for(uint8_t i = TUYA_MCU_FUNC_REL2; i <= TUYA_MCU_FUNC_REL8; i++) { + if (TuyaGetDpId(i) != 0) { + devices_present++; + } } + Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); if (Tuya.buffer != nullptr) { TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); @@ -434,11 +572,11 @@ int Xnrg08(uint8_t function) if (TUYA_DIMMER == my_module_type) { if (FUNC_PRE_INIT == function) { if (!energy_flg) { - if (Settings.param[P_TUYA_POWER_ID] != 0) { - if (Settings.param[P_TUYA_CURRENT_ID] == 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { Energy.current_available = false; } - if (Settings.param[P_TUYA_VOLTAGE_ID] == 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { Energy.voltage_available = false; } energy_flg = XNRG_08; @@ -486,6 +624,9 @@ bool Xdrv16(uint8_t function) case FUNC_SET_CHANNELS: result = TuyaSetChannels(); break; + case FUNC_COMMAND: + result = DecodeCommand(kTuyaCommand, TuyaCommand); + break; } } return result; From 1d7a058155a68a4e53d4ea71f9d0accfa8cd9ccd Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 3 Sep 2019 11:57:13 +0100 Subject: [PATCH 15/40] Tuya MCU: Add support for Switches1 to 4 FunctionIDs 1 to 4 --- sonoff/xdrv_16_tuyadimmer.ino | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 452a65346..66f649603 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -64,10 +64,10 @@ struct TUYA { enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, - // TUYA_MCU_FUNC_KEY1 = 1, // Buttons - // TUYA_MCU_FUNC_KEY2, - // TUYA_MCU_FUNC_KEY3, - // TUYA_MCU_FUNC_KEY4, + TUYA_MCU_FUNC_SWT1 = 1, // Buttons + TUYA_MCU_FUNC_SWT2, + TUYA_MCU_FUNC_SWT3, + TUYA_MCU_FUNC_SWT4, TUYA_MCU_FUNC_REL1 = 11, // Relays TUYA_MCU_FUNC_REL2, TUYA_MCU_FUNC_REL3, @@ -162,7 +162,8 @@ void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { } inline bool TuyaFuncIdValid(uint8_t fnId) { - return (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || + return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || + (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || fnId == TUYA_MCU_FUNC_DIMMER || (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE); } @@ -330,10 +331,17 @@ void TuyaPacketProcess(void) if (Tuya.buffer[5] == 5) { // on/off packet if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Device-%d --> MCU State: %s Current State:%s"),Tuya.buffer[6],Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } + } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1) != Tuya.buffer[10]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1, Tuya.buffer[10]); + SwitchHandler(1); + } } } From 982f0b9573a13d535bb0498e166e2c9ae5cf8619 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 3 Sep 2019 12:23:05 +0100 Subject: [PATCH 16/40] TuyaMCU: Rename Tuya Dimmer to Tuya MCU to make it more clear. --- sonoff/my_user_config.h | 2 +- sonoff/sonoff_post.h | 10 +++++----- sonoff/sonoff_template.h | 6 +++--- sonoff/support_command.ino | 2 +- sonoff/support_features.ino | 2 +- sonoff/{xdrv_16_tuyadimmer.ino => xdrv_16_tuyamcu.ino} | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename sonoff/{xdrv_16_tuyadimmer.ino => xdrv_16_tuyamcu.ino} (99%) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index f55fc774f..a18adc7b7 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -307,7 +307,7 @@ // -- Optional modules ---------------------------- #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer +#define USE_TUYA_MCU // Add support for Tuya Serial MCU #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index cc2b8b237..271325da1 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -85,7 +85,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c // -- Optional modules ------------------------- #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer +#define USE_TUYA_MCU // Add support for Tuya Serial MCU #ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 // Default dimmer Id #endif @@ -217,7 +217,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#ifndef USE_SONOFF_IFAN #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) //#endif -#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -345,7 +345,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c // -- Optional modules ------------------------- #undef USE_BUZZER // Disable support for a buzzer (+0k6 code) #undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) #undef USE_DS18x20 // Disable Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) @@ -436,7 +436,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c // -- Optional modules ------------------------- #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) -//#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -517,7 +517,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c // -- Optional modules ------------------------- #undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code) -#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU #undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) #undef ROTARY_V1 // Disable support for MI Desk Lamp diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 85f1a8c8d..cdfe75e23 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -541,7 +541,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 -#ifdef USE_TUYA_DIMMER +#ifdef USE_TUYA_MCU GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface #endif @@ -749,7 +749,7 @@ const uint8_t kModuleNiceList[] PROGMEM = { OBI2, MANZOKU_EU_4, ESP_SWITCH, // Switch Devices -#ifdef USE_TUYA_DIMMER +#ifdef USE_TUYA_MCU TUYA_DIMMER, // Dimmer Devices #endif #ifdef USE_ARMTRONIX_DIMMERS @@ -1728,7 +1728,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) 0, 0, 0 }, - { "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer) + { "Tuya MCU", // Tuya MCU device (ESP8266 w/ separate MCU) // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 GPIO_USER, // Virtual Button (controlled by MCU) GPIO_USER, // GPIO01 MCU serial control diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 1b91dc11b..a11c6b8c1 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -661,7 +661,7 @@ void CmndSetoption(void) IrReceiveUpdateThreshold(); break; #endif -#ifdef USE_TUYA_DIMMER +#ifdef USE_TUYA_MCU case P_TUYA_RELAYS: case P_TUYA_POWER_ID: case P_TUYA_CURRENT_ID: diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index 42144d191..8265e4cb9 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -171,7 +171,7 @@ void GetFeatures(void) #ifdef USE_PCA9685 feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino #endif -#if defined(USE_LIGHT) && defined(USE_TUYA_DIMMER) +#if defined(USE_LIGHT) && defined(USE_TUYA_MCU) feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino #endif #ifdef USE_RC_SWITCH diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyamcu.ino similarity index 99% rename from sonoff/xdrv_16_tuyadimmer.ino rename to sonoff/xdrv_16_tuyamcu.ino index 66f649603..edf60fbe3 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -1,5 +1,5 @@ /* - xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota + xdrv_16_tuyamcu.ino - Tuya MCU support for Sonoff-Tasmota Copyright (C) 2019 digiblur, Joel Stein and Theo Arends @@ -18,7 +18,7 @@ */ #ifdef USE_LIGHT -#ifdef USE_TUYA_DIMMER +#ifdef USE_TUYA_MCU #define XDRV_16 16 #define XNRG_08 8 @@ -640,5 +640,5 @@ bool Xdrv16(uint8_t function) return result; } -#endif // USE_TUYA_DIMMER +#endif // USE_TUYA_MCU #endif // USE_LIGHT From c4c8fab42f2359ba61089c770dbe207f65f01825 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 3 Sep 2019 14:00:51 +0100 Subject: [PATCH 17/40] Tuya MCU: Fix Switch ids are 1 incremented in MQTT --- sonoff/xdrv_16_tuyamcu.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index edf60fbe3..745990962 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -336,10 +336,10 @@ void TuyaPacketProcess(void) ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1) != Tuya.buffer[10]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1 + 1, Tuya.buffer[10]); + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]); SwitchHandler(1); } } From ca52a38bc1abe56390ebc8b2e31f6315268cc4f6 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 4 Sep 2019 20:58:17 +0200 Subject: [PATCH 18/40] sendmail --- lib/SENDMAIL/sendemail.cpp | 302 +++++++++++++++++++++++++++++++++++ lib/SENDMAIL/sendemail.h | 39 +++++ sonoff/xdrv_01_webserver.ino | 170 +++++++++++++++++++- 3 files changed, 510 insertions(+), 1 deletion(-) create mode 100755 lib/SENDMAIL/sendemail.cpp create mode 100755 lib/SENDMAIL/sendemail.h diff --git a/lib/SENDMAIL/sendemail.cpp b/lib/SENDMAIL/sendemail.cpp new file mode 100755 index 000000000..b84e1fbaa --- /dev/null +++ b/lib/SENDMAIL/sendemail.cpp @@ -0,0 +1,302 @@ +#include "sendemail.h" + +// enable serial debugging +//#define DEBUG_EMAIL_PORT Serial + +SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : + host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new WiFiClientSecure()) +{ + +} + + + +String SendEmail::readClient() +{ + String r = client->readStringUntil('\n'); + r.trim(); + while (client->available()) { + delay(0); + r += client->readString(); + } + return r; +} + +void SetSerialBaudrate(int baudrate); + +bool SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) +{ + if (!host.length()) + { + return false; + } + client->setTimeout(timeout); + // smtp connect +#ifdef DEBUG_EMAIL_PORT + SetSerialBaudrate(115200); + DEBUG_EMAIL_PORT.print("Connecting: "); + DEBUG_EMAIL_PORT.print(host); + DEBUG_EMAIL_PORT.print(":"); + DEBUG_EMAIL_PORT.println(port); +#endif + +#ifndef ARDUINO_ESP8266_RELEASE_2_4_2 + client->setInsecure(); + bool mfln = client->probeMaxFragmentLength(host.c_str(), port, 512); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.printf("MFLN supported: %s\n", mfln ? "yes" : "no"); +#endif + if (mfln) { + client->setBufferSizes(512, 512); + } +#endif + + if (!client->connect(host.c_str(), port)) + { +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println("Connection failed"); +#endif + return false; + } + + String buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("220"))) + { + return false; + } + + + buffer = F("EHLO "); + buffer += client->localIP().toString(); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("250"))) + { + return false; + } + if (user.length()>0 && passwd.length()>0 ) + { + + //buffer = F("STARTTLS"); + //client->println(buffer); + +if (auth_used==1) { + // plain +#ifdef USE_PLAIN + buffer = F("AUTH PLAIN"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("334"))) + { + return false; + } + + char plainAuth[100]; + memset(plainAuth,sizeof(plainAuth),0); + plainAuth[0] = '\0'; + strcpy(&plainAuth[1], user.c_str()); + strcpy(&plainAuth[2+user.length()],passwd.c_str()); + const char* pA = (const char*)&plainAuth; + char buf[100]; + base64_encode(buf, pA, user.length()+passwd.length()+2); + client->println(buf); + +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buf); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("235"))) + { + return false; + } +#endif + +} else { + + buffer = F("AUTH LOGIN"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("334"))) + { + return false; + } + base64 b; + //buffer = user; + //buffer = b.encode(buffer); + buffer = b.encode(user); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + //DEBUG_EMAIL_PORT.println(user); + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("334"))) + { + return false; + } + //buffer = this->passwd; + //buffer = b.encode(buffer); + buffer = b.encode(passwd); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + //DEBUG_EMAIL_PORT.println(passwd); + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("235"))) + { + return false; + } +} + + } + + // smtp send mail + buffer = F("MAIL FROM:"); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("250"))) + { + return false; + } + buffer = F("RCPT TO:"); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("250"))) + { + return false; + } + + + buffer = F("DATA"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + if (!buffer.startsWith(F("354"))) + { + return false; + } + buffer = F("From: "); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = F("To: "); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = F("Subject: "); + buffer += subject; + buffer += F("\r\n"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = msg; + client->println(buffer); + client->println('.'); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + buffer = F("QUIT"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + DEBUG_EMAIL_PORT.println(buffer); +#endif + return true; +} + +#ifdef USE_PLAIN +void SendEmail::a3_to_a4(unsigned char * a4, unsigned char * a3) { + a4[0] = (a3[0] & 0xfc) >> 2; + a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); + a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); + a4[3] = (a3[2] & 0x3f); +} + +int SendEmail::base64_encode(char *output, const char *input, int inputLen) { + const char* _b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int i = 0, j = 0; + int encLen = 0; + unsigned char a3[3]; + unsigned char a4[4]; + while(inputLen--) { + a3[i++] = *(input++); + if(i == 3) { + a3_to_a4(a4, a3); + for(i = 0; i < 4; i++) { + output[encLen++] = _b64_alphabet[a4[i]]; + } + i = 0; + } + } + if(i) { + for(j = i; j < 3; j++) { + a3[j] = '\0'; + } + a3_to_a4(a4, a3); + for(j = 0; j < i + 1; j++) { + output[encLen++] = _b64_alphabet[a4[j]]; + } + while((i++ < 3)) { + output[encLen++] = '='; + } + } + output[encLen] = '\0'; + return encLen; +} +#endif diff --git a/lib/SENDMAIL/sendemail.h b/lib/SENDMAIL/sendemail.h new file mode 100755 index 000000000..f622fb4e1 --- /dev/null +++ b/lib/SENDMAIL/sendemail.h @@ -0,0 +1,39 @@ +#ifndef __SENDEMAIL_H +#define __SENDEMAIL_H + +//#define DEBUG_EMAIL_PORT + +#include +#include +#include +#include + +class SendEmail +{ + private: + const String host; + const int port; + const String user; + const String passwd; + const int timeout; + const bool ssl; + const int auth_used; +#ifndef ARDUINO_ESP8266_RELEASE_2_4_2 + // use bear ssl + // #include "WiFiClientSecureLightBearSSL.h" + // BearSSL::WiFiClientSecure_light *client; + //BearSSL::WiFiClientSecure* client; + WiFiClientSecure* client; +#else + WiFiClient* client; +#endif + String readClient(); + void a3_to_a4(unsigned char * a4, unsigned char * a3); + int base64_encode(char *output, const char *input, int inputLen); + public: + SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used); + bool send(const String& from, const String& to, const String& subject, const String& msg); + ~SendEmail() {client->stop(); delete client;} +}; + +#endif diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 01f5cde34..00dcd0d49 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1053,6 +1053,7 @@ bool HandleRootStatusRefresh(void) #ifdef USE_SCRIPT_WEB_DISPLAY XdrvCall(FUNC_WEB_SENSOR); #endif + WSContentSend_P(PSTR("")); if (devices_present) { @@ -2350,6 +2351,151 @@ String UrlEncode(const String& text) return encoded; } +#ifdef USE_SENDMAIL + +#include "sendemail.h" + +//SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl); +//SendEmail::send(const String& from, const String& to, const String& subject, const String& msg) +// sendmail [server:port:user:passwd:from:to:subject] data +// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config +// sendmail currently only works with core 2.4.2 + +#define SEND_MAIL_MINRAM 19*1024 + +uint16_t SendMail(char *buffer) { + uint16_t count; + char *params,*oparams; + char *mserv; + uint16_t port; + char *user; + char *pstr; + char *passwd; + char *from; + char *to; + char *subject; + char *cmd; + char secure=0,auth=0; + uint16_t status=1; + SendEmail *mail=0; + + //DebugFreeMem(); + +// return if not enough memory + uint16_t mem=ESP.getFreeHeap(); + if (mem AUTH LOGIN 1 => PLAIN LOGIN + // 2 seconds timeout + #define MAIL_TIMEOUT 2000 + mail = new SendEmail(mserv, port,user,passwd, MAIL_TIMEOUT, auth); + +#ifdef EMAIL_FROM + if (*from=='*') { + from=(char*)EMAIL_FROM; + } +#endif + +exit: + if (mail) { + bool result=mail->send(from,to,subject,cmd); + delete mail; + if (result==true) status=0; + } + + + if (oparams) free(oparams); + return status; +} + +#endif + int WebSend(char *buffer) { // [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON @@ -2462,17 +2608,27 @@ bool JsonWebColor(const char* dataBuf) return true; } -const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ; +#define D_CMND_SENDMAIL "sendmail" +#define D_JSON_MEMORY_ERROR "memory error" + + +const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR; const char kWebCommands[] PROGMEM = "|" // No prefix #ifdef USE_EMULATION D_CMND_EMULATION "|" +#endif +#ifdef USE_SENDMAIL + D_CMND_SENDMAIL "|" #endif D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR; void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_EMULATION &CmndEmulation, +#endif +#ifdef USE_SENDMAIL + &CmndSendmail, #endif &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor }; @@ -2500,6 +2656,18 @@ void CmndEmulation(void) } #endif // USE_EMULATION +#ifdef USE_SENDMAIL +void CmndSendmail(void) +{ + if (XdrvMailbox.data_len > 0) { + uint8_t result = SendMail(XdrvMailbox.data); + char stemp1[20]; + ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + } +} +#endif // USE_SENDMAIL + + void CmndWebServer(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { From dad5b0ffc22ef9b2715ff433a0e44ad2b0d68b9a Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 3 Sep 2019 14:04:07 +0100 Subject: [PATCH 19/40] Tuya MCU: Implement support for Inverted Relays --- sonoff/xdrv_16_tuyamcu.ino | 58 +++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 745990962..61cc584bd 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -80,6 +80,14 @@ enum TuyaSupportedFunctions { TUYA_MCU_FUNC_POWER = 31, TUYA_MCU_FUNC_CURRENT, TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_REL1_INV = 41, // Inverted Relays + TUYA_MCU_FUNC_REL2_INV, + TUYA_MCU_FUNC_REL3_INV, + TUYA_MCU_FUNC_REL4_INV, + TUYA_MCU_FUNC_REL5_INV, + TUYA_MCU_FUNC_REL6_INV, + TUYA_MCU_FUNC_REL7_INV, + TUYA_MCU_FUNC_REL8_INV, TUYA_MCU_FUNC_LAST = 255 }; @@ -93,7 +101,7 @@ void (* const TuyaCommand[])(void) PROGMEM = { /* -TuyaMap fnid,dpid +TuyaMcu fnid,dpid */ @@ -159,13 +167,30 @@ void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { } } } + UpdateDevices(); +} + +void UpdateDevices() { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + uint8_t fnId = Settings.tuya_fnid_map[i].fnid; + if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { //Relay + bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { // Inverted Relay + bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); + } + + } + } } inline bool TuyaFuncIdValid(uint8_t fnId) { return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || fnId == TUYA_MCU_FUNC_DIMMER || - (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE); + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV); } uint8_t TuyaGetFuncId(uint8_t dpid) { @@ -252,7 +277,7 @@ bool TuyaSetPower(void) int16_t source = XdrvMailbox.payload; if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction - TuyaSendBool(active_device, bitRead(rpower, active_device-1)); + TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); status = true; } return status; @@ -335,6 +360,11 @@ void TuyaPacketProcess(void) if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); @@ -446,8 +476,21 @@ bool TuyaModuleSelected(void) TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); } - if (TuyaGetDpId(TUYA_MCU_FUNC_REL1) == 0) { + bool relaySet = false; + + devices_present--; + + for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { + if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || + (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { + relaySet = true; + devices_present++; + } + } + + if (!relaySet) { TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + devices_present++; SettingsSaveAll(); } @@ -457,17 +500,12 @@ bool TuyaModuleSelected(void) light_type = LT_BASIC; } + UpdateDevices(); return true; } void TuyaInit(void) { - for(uint8_t i = TUYA_MCU_FUNC_REL2; i <= TUYA_MCU_FUNC_REL8; i++) { - if (TuyaGetDpId(i) != 0) { - devices_present++; - } - } - Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); if (Tuya.buffer != nullptr) { TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); From 0145c86fe0b5f43219c6b6642907818fca12c777 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 10:02:42 +0200 Subject: [PATCH 20/40] Update settings.h --- sonoff/settings.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index bc8564cca..40be8b25f 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -372,11 +372,9 @@ struct SYSCFG { uint16_t web_refresh; // 7CC char mems[MAX_RULE_MEMS][10]; // 7CE char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b - uint8_t data8[32]; // E00 - uint16_t data16[16]; // E20 - TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E40 32 bytes + TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes - uint8_t free_e20[416]; // E60 + uint8_t free_e20[480]; // E20 // FFF last location } Settings; From 282591a0b2f7fa06fc688cfa789c3c834b5ea8c2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 10:41:08 +0200 Subject: [PATCH 21/40] Bump version to 6.6.0.10 Redesign Tuya support by Shantur Rathore (#6353) --- sonoff/_changelog.ino | 3 +++ sonoff/settings.h | 7 ++++--- sonoff/settings.ino | 34 +++++++++++++++++----------------- sonoff/sonoff.h | 6 +++--- sonoff/support_command.ino | 10 +++++----- sonoff/xdrv_16_tuyamcu.ino | 6 +++--- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4e79a7200..22b29098b 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 6.6.0.10 20190905 + * Redesign Tuya support by Shantur Rathore (#6353) + * * 6.6.0.9 20190828 * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) * Add Full support of all protocols in IRremoteESP8266, to be used on dedicated-IR Tasmota version. Warning: +81k Flash when compiling with USE_IR_REMOTE_FULL diff --git a/sonoff/settings.h b/sonoff/settings.h index 40be8b25f..1746b9d3f 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -371,12 +371,13 @@ struct SYSCFG { unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC char mems[MAX_RULE_MEMS][10]; // 7CE - char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b + char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes - uint8_t free_e20[480]; // E20 + uint8_t free_e20[472]; // E20 - // FFF last location + uint32_t cfg_timestamp; // FF8 + uint32_t cfg_crc4; // FFC } Settings; struct RTCRBT { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 7c44bf053..12227c578 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -1098,35 +1098,35 @@ void SettingsDelta(void) if (Settings.version < 0x0606000A) { uint8_t tuyaindex = 0; - if (Settings.param[P_TUYA_DIMMER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 21; //TUYA_MCU_FUNC_DIMMER; // Move Tuya Dimmer Id to Map - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_DIMMER_ID]; + if (Settings.param[P_ex_TUYA_DIMMER_ID] > 0) { // ex SetOption34 + Settings.tuya_fnid_map[tuyaindex].fnid = 21; // TUYA_MCU_FUNC_DIMMER - Move Tuya Dimmer Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_DIMMER_ID]; tuyaindex++; - } else if (Settings.flag3.tuya_disable_dimmer == 1) { - Settings.tuya_fnid_map[tuyaindex].fnid = 11; //TUYA_MCU_FUNC_REL1; // Create FnID for Switches + } else if (Settings.flag3.tuya_disable_dimmer == 1) { // ex SetOption65 + Settings.tuya_fnid_map[tuyaindex].fnid = 11; // TUYA_MCU_FUNC_REL1 - Create FnID for Switches Settings.tuya_fnid_map[tuyaindex].dpid = 1; tuyaindex++; } - if (Settings.param[P_TUYA_RELAYS] > 0) { - for (uint8_t i = 0 ; i < Settings.param[P_TUYA_RELAYS]; i++) { - Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; //TUYA_MCU_FUNC_REL2+; // Create FnID for Switches + if (Settings.param[P_ex_TUYA_RELAYS] > 0) { + for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { // ex SetOption41 + Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; // TUYA_MCU_FUNC_REL2 - Create FnID for Switches Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; tuyaindex++; } } - if (Settings.param[P_TUYA_POWER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 31; //TUYA_MCU_FUNC_POWER; // Move Tuya Power Id to Map - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_POWER_ID]; + if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { // ex SetOption46 + Settings.tuya_fnid_map[tuyaindex].fnid = 31; // TUYA_MCU_FUNC_POWER - Move Tuya Power Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID]; tuyaindex++; } - if (Settings.param[P_TUYA_VOLTAGE_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 33; //TUYA_MCU_FUNC_VOLTAGE; // Move Tuya Voltage Id to Map - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_VOLTAGE_ID]; + if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { // ex SetOption44 + Settings.tuya_fnid_map[tuyaindex].fnid = 33; // TUYA_MCU_FUNC_VOLTAGE - Move Tuya Voltage Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID]; tuyaindex++; } - if (Settings.param[P_TUYA_CURRENT_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 32; //TUYA_MCU_FUNC_CURRENT; // Move Tuya Current Id to Map - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_TUYA_CURRENT_ID]; + if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { // ex SetOption45 + Settings.tuya_fnid_map[tuyaindex].fnid = 32; // TUYA_MCU_FUNC_CURRENT - Move Tuya Current Id to Map + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; tuyaindex++; } diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index b8bf44814..228765a00 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -243,9 +243,9 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParamIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 - P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42 - P_TUYA_DIMMER_MAX, P_TUYA_VOLTAGE_ID, P_TUYA_CURRENT_ID, P_TUYA_POWER_ID, // SetOption43 .. SetOption46 +enum SettingsParamIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 + P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42 + P_TUYA_DIMMER_MAX, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46 P_ENERGY_TARIFF1, P_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index a11c6b8c1..41b4cfe1d 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -644,7 +644,7 @@ void CmndSetoption(void) param_low = 1; param_high = 250; break; - case P_TUYA_RELAYS: + case P_ex_TUYA_RELAYS: param_high = 8; break; } @@ -662,10 +662,10 @@ void CmndSetoption(void) break; #endif #ifdef USE_TUYA_MCU - case P_TUYA_RELAYS: - case P_TUYA_POWER_ID: - case P_TUYA_CURRENT_ID: - case P_TUYA_VOLTAGE_ID: +// case P_ex_TUYA_RELAYS: +// case P_ex_TUYA_POWER_ID: +// case P_ex_TUYA_CURRENT_ID: +// case P_ex_TUYA_VOLTAGE_ID: case P_TUYA_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 61cc584bd..c609395d7 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -377,11 +377,11 @@ void TuyaPacketProcess(void) } else if (Tuya.buffer[5] == 8) { // Long value packet if (fnId == TUYA_MCU_FUNC_DIMMER) { - // if (!Settings.param[P_TUYA_DIMMER_ID]) { + // if (!Settings.param[P_ex_TUYA_DIMMER_ID]) { // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]); - // Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6]; + // Settings.param[P_ex_TUYA_DIMMER_ID] = Tuya.buffer[6]; // } - // if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) { + // if (Settings.param[P_ex_TUYA_DIMMER_ID] == Tuya.buffer[6]) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { From 1d92436877356f740e253f605b026cdd8173575f Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 5 Sep 2019 11:14:33 +0200 Subject: [PATCH 22/40] sendmail core 2.3 fix --- lib/SENDMAIL/sendemail.cpp | 4 +++- lib/SENDMAIL/sendemail.h | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/SENDMAIL/sendemail.cpp b/lib/SENDMAIL/sendemail.cpp index b84e1fbaa..ab2c90ecd 100755 --- a/lib/SENDMAIL/sendemail.cpp +++ b/lib/SENDMAIL/sendemail.cpp @@ -40,7 +40,8 @@ bool SendEmail::send(const String& from, const String& to, const String& subject DEBUG_EMAIL_PORT.println(port); #endif -#ifndef ARDUINO_ESP8266_RELEASE_2_4_2 +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#else client->setInsecure(); bool mfln = client->probeMaxFragmentLength(host.c_str(), port, 512); #ifdef DEBUG_EMAIL_PORT @@ -51,6 +52,7 @@ bool SendEmail::send(const String& from, const String& to, const String& subject } #endif + if (!client->connect(host.c_str(), port)) { #ifdef DEBUG_EMAIL_PORT diff --git a/lib/SENDMAIL/sendemail.h b/lib/SENDMAIL/sendemail.h index f622fb4e1..394612fc6 100755 --- a/lib/SENDMAIL/sendemail.h +++ b/lib/SENDMAIL/sendemail.h @@ -18,14 +18,14 @@ class SendEmail const int timeout; const bool ssl; const int auth_used; -#ifndef ARDUINO_ESP8266_RELEASE_2_4_2 +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) + WiFiClient* client; +#else // use bear ssl // #include "WiFiClientSecureLightBearSSL.h" // BearSSL::WiFiClientSecure_light *client; - //BearSSL::WiFiClientSecure* client; - WiFiClientSecure* client; -#else - WiFiClient* client; + BearSSL::WiFiClientSecure* client; + //WiFiClientSecure* client; #endif String readClient(); void a3_to_a4(unsigned char * a4, unsigned char * a3); From d1ca5d1bde4c207580c4f84d79586e9fe92c99c0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 12:22:06 +0200 Subject: [PATCH 23/40] Fix exception on AddLogBuffer Fix exception on AddLogBuffer (#6282) --- sonoff/xnrg_09_sdm120.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xnrg_09_sdm120.ino b/sonoff/xnrg_09_sdm120.ino index 8640eca9f..6bd942655 100644 --- a/sonoff/xnrg_09_sdm120.ino +++ b/sonoff/xnrg_09_sdm120.ino @@ -86,7 +86,7 @@ void SDM120Every200ms(void) uint8_t buffer[9]; uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); From db44b058e2b80f38d5faceef5bbfe6361d1f4efb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 12:32:28 +0200 Subject: [PATCH 24/40] Add command Reset 99 to reset bootcount to zero Add command Reset 99 to reset bootcount to zero (#684, #6351) --- sonoff/_changelog.ino | 1 + sonoff/support_command.ino | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 22b29098b..4de80cebe 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /*********************************************************************************************\ * 6.6.0.10 20190905 * Redesign Tuya support by Shantur Rathore (#6353) + * Add command Reset 99 to reset bootcount to zero (#684, #6351) * * 6.6.0.9 20190828 * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 41b4cfe1d..a1bedea89 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -1269,6 +1269,10 @@ void CmndReset(void) restart_flag = 210 + XdrvMailbox.payload; Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; + case 99: + Settings.bootcount = 0; + ResponseCmndDone(); + break; default: ResponseCmndChar(D_JSON_ONE_TO_RESET); } From e0f5ed38af32428af8d2a03c8f2a41fa9036e9f4 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Thu, 5 Sep 2019 11:32:39 +0100 Subject: [PATCH 25/40] TuyaMCU: Cleanup unused tuya_disable_dimmer --- sonoff/xdrv_16_tuyamcu.ino | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index c609395d7..48e97334a 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -297,19 +297,15 @@ void LightSerialDuty(uint8_t duty) if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself } - if (Settings.flag3.tuya_disable_dimmer == 0) { - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); - if (Tuya.new_dim != duty) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); - TuyaSendValue(dpid, duty); - } + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + if (Tuya.new_dim != duty) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + TuyaSendValue(dpid, duty); } } else if (dpid > 0) { Tuya.ignore_dim = false; // reset flag - if (Settings.flag3.tuya_disable_dimmer == 0) { - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set - } + duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); // } @@ -377,20 +373,14 @@ void TuyaPacketProcess(void) } else if (Tuya.buffer[5] == 8) { // Long value packet if (fnId == TUYA_MCU_FUNC_DIMMER) { - // if (!Settings.param[P_ex_TUYA_DIMMER_ID]) { - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]); - // Settings.param[P_ex_TUYA_DIMMER_ID] = Tuya.buffer[6]; - // } - // if (Settings.param[P_ex_TUYA_DIMMER_ID] == Tuya.buffer[6]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); - Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); + Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); - } - // } + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } } #ifdef USE_ENERGY_SENSOR From db51e516b6195a0ec232d691798f6d9cffd37d6b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 16:34:03 +0200 Subject: [PATCH 26/40] Fix core 2.3.0 compilation error due to missing std::swap Fix core 2.3.0 compilation error due to missing std::swap (#6356) --- .../src/internal/NeoEsp8266UartMethod.h | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/NeoPixelBus-2.5.0.09/src/internal/NeoEsp8266UartMethod.h b/lib/NeoPixelBus-2.5.0.09/src/internal/NeoEsp8266UartMethod.h index d45436b24..42c4c63bb 100644 --- a/lib/NeoPixelBus-2.5.0.09/src/internal/NeoEsp8266UartMethod.h +++ b/lib/NeoPixelBus-2.5.0.09/src/internal/NeoEsp8266UartMethod.h @@ -53,7 +53,7 @@ public: }; // this template method class is used to track the data being sent on the uart -// when using our own UART ISR +// when using our own UART ISR // used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes // class NeoEsp8266UartInterruptContext : NeoEsp8266UartContext @@ -77,12 +77,12 @@ public: private: volatile const uint8_t* _asyncBuff; volatile const uint8_t* _asyncBuffEnd; - volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2]; + volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2]; static void ICACHE_RAM_ATTR Isr(void* param); }; -// this template feature class is used a base for all others and contains +// this template feature class is used a base for all others and contains // common methods // class UartFeatureBase @@ -129,7 +129,7 @@ public: } }; -// this template method class is used a base for all others and contains +// this template method class is used a base for all others and contains // common properties and methods // // used by NeoEsp8266Uart and NeoEsp8266AsyncUart @@ -233,14 +233,14 @@ protected: } // detach context, which will disable intr, may disable ISR _context.Detach(T_UARTFEATURE::Index); - + free(_pixelsSending); } void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud) { T_UARTFEATURE::Init(uartBaud); - + // attach the context, which will enable the ISR _context.Attach(T_UARTFEATURE::Index); } @@ -248,7 +248,7 @@ protected: void UpdateUart(bool maintainBufferConsistency) { // Instruct ESP8266 hardware uart to send the pixels asynchronously - _context.StartSending(T_UARTFEATURE::Index, + _context.StartSending(T_UARTFEATURE::Index, _pixels, _pixels + _sizePixels); @@ -264,7 +264,10 @@ protected: } // swap so the user can modify without affecting the async operation - std::swap(_pixelsSending, _pixels); +// std::swap(_pixelsSending, _pixels); + uint8_t *temp = _pixelsSending; + _pixelsSending = _pixels; + _pixels = temp; } private: @@ -383,7 +386,7 @@ private: }; }; -// uart 0 +// uart 0 typedef NeoEsp8266UartMethodBase> NeoEsp8266Uart0Ws2812xMethod; typedef NeoEsp8266UartMethodBase> NeoEsp8266Uart0Sk6812Method; typedef NeoEsp8266UartMethodBase> NeoEsp8266Uart0Apa106Method; From a01de9a9b2b21453e6bcb22a21fe4c5ba1121cf6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 16:56:02 +0200 Subject: [PATCH 27/40] Remove obsolete Tuya code Remove obsolete Tuya code --- sonoff/settings.h | 4 +-- sonoff/settings.ino | 51 +++++++++++++++++++------------------- sonoff/support_command.ino | 20 ++++----------- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index 1746b9d3f..5274edc99 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -78,7 +78,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator - uint32_t tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - Enable or Disable Tuya Serial Dimmer control + uint32_t ex_tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - (Enable or Disable Tuya Serial Dimmer control) - free since 6.6.0.10 uint32_t tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM @@ -377,7 +377,7 @@ struct SYSCFG { uint8_t free_e20[472]; // E20 uint32_t cfg_timestamp; // FF8 - uint32_t cfg_crc4; // FFC + uint32_t cfg_crc32; // FFC } Settings; struct RTCRBT { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 12227c578..97f41e167 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -273,8 +273,9 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses // Version 5.2 allow for more flash space const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) -uint16_t settings_crc = 0; uint32_t settings_location = SETTINGS_LOCATION; +//uint32_t settings_crc32 = 0; +uint16_t settings_crc = 0; uint8_t *settings_buffer = nullptr; /********************************************************************************************/ @@ -331,6 +332,22 @@ uint16_t GetSettingsCrc(void) return crc; } +uint32_t GetSettingsCrc32(void) +{ + // https://create.stephan-brumme.com/crc32/#bitwise + uint32_t crc = 0; + uint8_t *bytes = (uint8_t*)&Settings; + + uint32_t length = sizeof(SYSCFG) -4; // Skip crc + while (length--) { + crc ^= *bytes++; + for (uint32_t j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); + } + } + return ~crc; +} + void SettingsSaveAll(void) { if (Settings.flag.save_state) { @@ -340,9 +357,6 @@ void SettingsSaveAll(void) } XsnsCall(FUNC_SAVE_BEFORE_RESTART); XdrvCall(FUNC_SAVE_BEFORE_RESTART); -#ifdef USE_EEPROM - EepromCommit(); -#endif SettingsSave(0); } @@ -382,31 +396,17 @@ void SettingsSave(uint8_t rotate) } } Settings.save_flag++; + if (UtcTime() > START_VALID_TIME) { + Settings.cfg_timestamp = UtcTime(); + } else { + Settings.cfg_timestamp++; + } Settings.cfg_size = sizeof(SYSCFG); +// Settings.cfg_crc32 = GetSettingsCrc32(); Settings.cfg_crc = GetSettingsCrc(); -#ifdef USE_EEPROM - if (SPIFFS_END == settings_location) { - uint8_t* flash_buffer; - flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; - if (eeprom_data && eeprom_size) { - size_t flash_offset = SPI_FLASH_SEC_SIZE - eeprom_size; - memcpy(flash_buffer + flash_offset, eeprom_data, eeprom_size); // Write dirty EEPROM data - } else { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE); // Read EEPROM area - } - memcpy(flash_buffer, &Settings, sizeof(Settings)); - ESP.flashEraseSector(settings_location); - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE); - delete[] flash_buffer; - } else { - ESP.flashEraseSector(settings_location); - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - } -#else ESP.flashEraseSector(settings_location); ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); -#endif // USE_EEPROM if (!stop_flash_rotate && rotate) { for (uint32_t i = 1; i < CFG_ROTATES; i++) { @@ -418,6 +418,7 @@ void SettingsSave(uint8_t rotate) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); settings_crc = Settings.cfg_crc; +// settings_crc32 = Settings.cfg_crc32; } #endif // FIRMWARE_MINIMAL RtcSettingsSave(); @@ -1102,7 +1103,7 @@ void SettingsDelta(void) Settings.tuya_fnid_map[tuyaindex].fnid = 21; // TUYA_MCU_FUNC_DIMMER - Move Tuya Dimmer Id to Map Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_DIMMER_ID]; tuyaindex++; - } else if (Settings.flag3.tuya_disable_dimmer == 1) { // ex SetOption65 + } else if (Settings.flag3.ex_tuya_disable_dimmer == 1) { // ex SetOption65 Settings.tuya_fnid_map[tuyaindex].fnid = 11; // TUYA_MCU_FUNC_REL1 - Create FnID for Switches Settings.tuya_fnid_map[tuyaindex].dpid = 1; tuyaindex++; diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index a1bedea89..a634ac48f 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -616,26 +616,23 @@ void CmndSetoption(void) #endif // USE_HOME_ASSISTANT } } - else if (1 == ptype) { // SetOption50 .. 81 + else if (1 == ptype) { // SetOption50 .. 81 if (XdrvMailbox.payload <= 1) { bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - if (5 == pindex) { // SetOption55 + if (5 == pindex) { // SetOption55 if (0 == XdrvMailbox.payload) { restart_flag = 2; // Disable mDNS needs restart } } - if (10 == pindex) { // SetOption60 enable or disable traditional sleep + if (10 == pindex) { // SetOption60 enable or disable traditional sleep WiFiSetSleepMode(); // Update WiFi sleep mode accordingly } - if (18 == pindex) { // SetOption68 for multi-channel PWM, requires a reboot - restart_flag = 2; - } - if (15 == pindex) { // SetOption65 for tuya_disable_dimmer requires a reboot + if (18 == pindex) { // SetOption68 for multi-channel PWM, requires a reboot restart_flag = 2; } } } - else { // SetOption32 .. 49 + else { // SetOption32 .. 49 uint32_t param_low = 0; uint32_t param_high = 255; switch (pindex) { @@ -644,9 +641,6 @@ void CmndSetoption(void) param_low = 1; param_high = 250; break; - case P_ex_TUYA_RELAYS: - param_high = 8; - break; } if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { Settings.param[pindex] = XdrvMailbox.payload; @@ -662,10 +656,6 @@ void CmndSetoption(void) break; #endif #ifdef USE_TUYA_MCU -// case P_ex_TUYA_RELAYS: -// case P_ex_TUYA_POWER_ID: -// case P_ex_TUYA_CURRENT_ID: -// case P_ex_TUYA_VOLTAGE_ID: case P_TUYA_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; From ea0fb65845bc050e1b548fb3ebf1d3e91e98b3fb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 17:19:19 +0200 Subject: [PATCH 28/40] Refactor Sendmail Refactor Sendmail --- sonoff/i18n.h | 2 ++ sonoff/xdrv_01_webserver.ino | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 287476dd7..35b51bd1f 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -96,6 +96,7 @@ #define D_JSON_LOW "Low" #define D_JSON_MAC "Mac" #define D_JSON_MASK "Mask" +#define D_JSON_MEMORY_ERROR "Memory error" #define D_JSON_MINIMAL "minimal" #define D_JSON_MODEL "Model" #define D_JSON_MQTT_COUNT "MqttCount" @@ -326,6 +327,7 @@ #define D_CMND_WEBCOLOR "WebColor" #define D_CMND_WEBSENSOR "WebSensor" #define D_CMND_EMULATION "Emulation" +#define D_CMND_SENDMAIL "Sendmail" // Commands xdrv_03_energy.ino #define D_CMND_POWERLOW "PowerLow" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 00dcd0d49..003d9d765 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2608,10 +2608,6 @@ bool JsonWebColor(const char* dataBuf) return true; } -#define D_CMND_SENDMAIL "sendmail" -#define D_JSON_MEMORY_ERROR "memory error" - - const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR; const char kWebCommands[] PROGMEM = "|" // No prefix @@ -2660,9 +2656,9 @@ void CmndEmulation(void) void CmndSendmail(void) { if (XdrvMailbox.data_len > 0) { - uint8_t result = SendMail(XdrvMailbox.data); - char stemp1[20]; - ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + uint8_t result = SendMail(XdrvMailbox.data); + char stemp1[20]; + ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); } } #endif // USE_SENDMAIL From ab89bb53a94385500415af7d46ce6425dc299d3b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 17:45:43 +0200 Subject: [PATCH 29/40] Oops Oops --- sonoff/sonoff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 228765a00..42f71e0b2 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -130,6 +130,8 @@ const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms const uint8_t MAX_STATUS = 11; // Max number of status lines +const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01 + const uint32_t DRIVER_BOOT_DELAY = 1; // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to go through the main loop using delay when needed From a1e9c2d2ac6ccc3ff7da4aae260501a1267f7175 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Sep 2019 18:02:36 +0200 Subject: [PATCH 30/40] Fix SDM120 modbus dump and Domoticz Energy Consumed or Produced Fix SDM120 modbus dump exception and Domoticz Energy Consumed or Produced (#6282) --- sonoff/xdrv_03_energy.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 11 ++++++++--- sonoff/xnrg_05_pzem_ac.ino | 2 +- sonoff/xnrg_06_pzem_dc.ino | 2 +- sonoff/xnrg_09_sdm120.ino | 5 ++++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index d5e814a47..7d40d762d 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -824,7 +824,7 @@ void EnergyShow(bool json) char energy_total1_chr[FLOATSZ]; dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1 char energy_non[2] = "0"; - DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power, 0); + DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power); if (Energy.voltage_available) { DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 33acefc76..a65c82851 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -383,14 +383,19 @@ void DomoticzSensorPowerEnergy(int power, char *energy) DomoticzSensor(DZ_POWER_ENERGY, data); } -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int consumed, int produced) +void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) { //usage1 = energy usage meter tariff 1, This is an incrementing counter //usage2 = energy usage meter tariff 2, This is an incrementing counter //return1 = energy return meter tariff 1, This is an incrementing counter //return2 = energy return meter tariff 2, This is an incrementing counter - //consumed = actual usage power (Watt) - //produced = actual return power (Watt) + //power = if >= 0 actual usage power. if < 0 actual return power (Watt) + int consumed = power; + int produced = 0; + if (power < 0) { + consumed = 0; + produced = -power; + } char data[64]; snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); DomoticzSensor(DZ_P1_SMART_METER, data); diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino index 04f71c524..55814435a 100644 --- a/sonoff/xnrg_05_pzem_ac.ino +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -64,7 +64,7 @@ void PzemAcEverySecond(void) uint8_t buffer[26]; uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer)); if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino index 1ad65a88a..bba38dd3d 100644 --- a/sonoff/xnrg_06_pzem_dc.ino +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -46,7 +46,7 @@ void PzemDcEverySecond(void) uint8_t buffer[22]; uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer)); if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); diff --git a/sonoff/xnrg_09_sdm120.ino b/sonoff/xnrg_09_sdm120.ino index 6bd942655..af8a7e214 100644 --- a/sonoff/xnrg_09_sdm120.ino +++ b/sonoff/xnrg_09_sdm120.ino @@ -86,13 +86,16 @@ void SDM120Every200ms(void) uint8_t buffer[9]; uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer)); if (error) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); } else { Energy.data_valid = 0; + // 0 1 2 3 4 5 6 7 8 + // SA FC BC Fh Fl Sh Sl Cl Ch + // 01 04 04 43 66 33 34 1B 38 = 230.2 Volt float value; ((uint8_t*)&value)[3] = buffer[3]; // Get float values ((uint8_t*)&value)[2] = buffer[4]; From c671eaecb91f71fe681c896a8babec1ba3dfac6d Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Fri, 6 Sep 2019 10:11:50 +0200 Subject: [PATCH 31/40] touch button update, fix display settings font and size --- sonoff/xdrv_13_display.ino | 14 ++++++++++-- sonoff/xdsp_07_sh1106.ino | 4 ++-- sonoff/xdsp_08_ILI9488.ino | 44 +++++++++++++++++++++++++++--------- sonoff/xdsp_10_RA8876.ino | 46 +++++++++++++++++++++++++++++--------- 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 6a0153545..3a144b6c9 100755 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -1247,6 +1247,12 @@ void DisplayInitDriver(void) { XdspCall(FUNC_DISPLAY_INIT_DRIVER); + if (renderer) { + renderer->setTextFont(Settings.display_font); + renderer->setTextSize(Settings.display_size); + } + + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); if (Settings.display_model) { @@ -1376,14 +1382,18 @@ void CmndDisplaySize(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_size = XdrvMailbox.payload; + if (renderer) renderer->setTextSize(Settings.display_size); + else DisplaySetSize(Settings.display_size); } ResponseCmndNumber(Settings.display_size); } void CmndDisplayFont(void) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { + if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { Settings.display_font = XdrvMailbox.payload; + if (renderer) renderer->setTextFont(Settings.display_font); + else DisplaySetFont(Settings.display_font); } ResponseCmndNumber(Settings.display_font); } @@ -1804,7 +1814,7 @@ void Restore_graph(uint8_t num, char *path) { if (!fp) return; char vbuff[32]; char *cp=vbuff; - char buf[2]; + uint8_t buf[2]; uint8_t findex=0; for (uint32_t count=0;count<=gp->xs+4;count++) { diff --git a/sonoff/xdsp_07_sh1106.ino b/sonoff/xdsp_07_sh1106.ino index 1c45a451d..0501233a7 100644 --- a/sonoff/xdsp_07_sh1106.ino +++ b/sonoff/xdsp_07_sh1106.ino @@ -145,13 +145,13 @@ void SH1106Refresh(void) // Every second if (Settings.display_mode) { // Mode 0 is User text switch (Settings.display_mode) { case 1: // Time - Ssd1306Time(); + SH1106Time(); break; case 2: // Local case 3: // Local case 4: // Mqtt case 5: // Mqtt - Ssd1306PrintLog(); + SH1106PrintLog(); break; } } diff --git a/sonoff/xdsp_08_ILI9488.ino b/sonoff/xdsp_08_ILI9488.ino index da20efbcb..071280601 100644 --- a/sonoff/xdsp_08_ILI9488.ino +++ b/sonoff/xdsp_08_ILI9488.ino @@ -127,9 +127,16 @@ void ILI9488_MQTT(uint8_t count,const char *cp) { ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } + +void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} // check digitizer hit void FT6236Check() { uint16_t temp; +uint8_t rbutt=0,vbutt=0; ili9488_ctouch_counter++; if (2 == ili9488_ctouch_counter) { // every 100 ms should be enough @@ -157,17 +164,17 @@ if (2 == ili9488_ctouch_counter) { // now must compare with defined buttons for (uint8_t count=0; countvpower&0x7f; if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { // did hit buttons[count]->press(true); if (buttons[count]->justPressed()) { - uint8_t bflags=buttons[count]->vpower&0x7f; if (!bflags) { - // real button - if (!SendKey(KEY_BUTTON, count+1, POWER_TOGGLE)) { - ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON); + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + ILI9488_RDW_BUTT(count,!pwr); } - buttons[count]->xdrawButton(bitRead(power,count)); } else { // virtual button const char *cp; @@ -185,6 +192,11 @@ if (2 == ili9488_ctouch_counter) { } } } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } } } } @@ -192,15 +204,27 @@ if (2 == ili9488_ctouch_counter) { // no hit for (uint8_t count=0; countvpower&0x7f; buttons[count]->press(false); if (buttons[count]->justReleased()) { uint8_t bflags=buttons[count]->vpower&0x7f; - if (bflags>1) { - // push button - buttons[count]->vpower&=0x7f; - ILI9488_MQTT(count,"PBT"); + if (bflags>0) { + if (bflags>1) { + // push button + buttons[count]->vpower&=0x7f; + ILI9488_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + if (!bflags) { + // check if power button stage changed + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + ILI9488_RDW_BUTT(count,pwr); + } + rbutt++; } } } diff --git a/sonoff/xdsp_10_RA8876.ino b/sonoff/xdsp_10_RA8876.ino index 2abeda94b..d138ae154 100644 --- a/sonoff/xdsp_10_RA8876.ino +++ b/sonoff/xdsp_10_RA8876.ino @@ -113,9 +113,16 @@ void RA8876_MQTT(uint8_t count,const char *cp) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } +void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + // check digitizer hit void FT5316Check() { uint16_t temp; +uint8_t rbutt=0,vbutt=0; ra8876_ctouch_counter++; if (2 == ra8876_ctouch_counter) { // every 100 ms should be enough @@ -152,23 +159,26 @@ if (2 == ra8876_ctouch_counter) { break; } */ + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %d,%d"),ra8876_pLoc.x,ra8876_pLoc.y); + //Serial.printf("loc x: %d , loc y: %d\n",pLoc.x,pLoc.y); // now must compare with defined buttons for (uint8_t count=0; countvpower&0x7f; if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { // did hit buttons[count]->press(true); if (buttons[count]->justPressed()) { - uint8_t bflags=buttons[count]->vpower&0x7f; if (!bflags) { // real button - if (!SendKey(KEY_BUTTON, count+1, POWER_TOGGLE)) { - ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON); + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + RA8876_RDW_BUTT(count,!pwr); } - buttons[count]->xdrawButton(bitRead(power,count)); } else { // virtual button const char *cp; @@ -186,6 +196,11 @@ if (2 == ra8876_ctouch_counter) { } } } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } } } } @@ -193,15 +208,26 @@ if (2 == ra8876_ctouch_counter) { // no hit for (uint8_t count=0; countvpower&0x7f; buttons[count]->press(false); if (buttons[count]->justReleased()) { - uint8_t bflags=buttons[count]->vpower&0x7f; - if (bflags>1) { - // push button - buttons[count]->vpower&=0x7f; - RA8876_MQTT(count,"PBT"); + if (bflags>0) { + if (bflags>1) { + // push button + buttons[count]->vpower&=0x7f; + RA8876_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + if (!bflags) { + // check if power button stage changed + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + RA8876_RDW_BUTT(count,pwr); + } + rbutt++; } } } From 7306bb3638a95752cb2f4004776896dc1c8ef5ea Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Fri, 6 Sep 2019 10:42:39 +0200 Subject: [PATCH 32/40] decode-config.py: adapt settings - add Time (time_format) - add TuyaMCU (tuya_fnid_map) - add cfg_timestamp/cfg_crc32 - remove SetOption65 (tuya_disable_dimmer) --- tools/decode-config.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index 67e21b3a6..f04854acd 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.3.0032' +VER = '2.3.0033' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -984,7 +984,22 @@ Setting_6_6_0_9.update ({ 'sbaudrate': (' Date: Fri, 6 Sep 2019 15:46:40 +0200 Subject: [PATCH 33/40] Change command Time 1/2/3 for legacy reason Change command Time 1/2/3 to select JSON time format ISO, ISO + Epoch or Epoch for legacy reason --- sonoff/_changelog.ino | 1 + sonoff/support.ino | 4 ++-- sonoff/support_command.ino | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 4de80cebe..359289b3d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,7 @@ * 6.6.0.10 20190905 * Redesign Tuya support by Shantur Rathore (#6353) * Add command Reset 99 to reset bootcount to zero (#684, #6351) + * Change command Time 1/2/3 to select JSON time format ISO, ISO + Epoch or Epoch for legacy reason * * 6.6.0.9 20190828 * Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294) diff --git a/sonoff/support.ino b/sonoff/support.ino index e6707510e..035a1d31d 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -876,13 +876,13 @@ char* ResponseGetTime(uint32_t format, char* time_str) { switch (format) { case 1: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); break; case 2: snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); break; default: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); } return time_str; } diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index a634ac48f..8497497ab 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -1271,8 +1271,8 @@ void CmndReset(void) void CmndTime(void) { // payload 0 = (re-)enable NTP -// payload 1 = Time format {"Time":"2019-09-04T14:31:29","Epoch":1567600289} -// payload 2 = Time format {"Time":"2019-09-04T14:31:29"} +// payload 1 = Time format {"Time":"2019-09-04T14:31:29"} +// payload 2 = Time format {"Time":"2019-09-04T14:31:29","Epoch":1567600289} // payload 3 = Time format {"Time":1567600289} // payload 4 = reserved // payload 1451602800 - disable NTP and set time to epoch @@ -1283,7 +1283,7 @@ void CmndTime(void) Settings.flag2.time_format = XdrvMailbox.payload -1; format = Settings.flag2.time_format; } else { - format = 0; // {"Time":"2019-09-04T14:31:29","Epoch":1567600289} + format = 1; // {"Time":"2019-09-04T14:31:29","Epoch":1567600289} RtcSetTime(XdrvMailbox.payload); } } From 53235a3382abbb3b34b60e26fcdd57c2535fef1d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 6 Sep 2019 18:02:31 +0200 Subject: [PATCH 34/40] Redesign Energy Total calculation * Redesign Energy Total calculation * Increase SDM120 modbus interval time to 200mS (#6282) --- sonoff/sonoff.h | 2 +- sonoff/xdrv_03_energy.ino | 111 ++++++++++++++++++++++---------------- sonoff/xnrg_09_sdm120.ino | 6 +-- 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 42f71e0b2..e773bf7a7 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -263,7 +263,7 @@ enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, - FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, + FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_300_MSECOND, FUNC_EVERY_SECOND, FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 7d40d762d..d22dae114 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -83,12 +83,12 @@ struct ENERGY { float total = 0; // 12345.12345 kWh tariff 1 + 2 float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak - unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) + unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) + unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily - unsigned long kWhtoday1; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily - uint8_t fifth_second = 0; + uint8_t tenth_second = 0; uint8_t command_code = 0; uint8_t data_valid = 0; @@ -129,64 +129,68 @@ void EnergyUpdateToday(void) Energy.kWhtoday_delta -= (delta * 1000); Energy.kWhtoday += delta; } - uint32_t energy_diff = Energy.kWhtoday - RtcSettings.energy_kWhtoday; - RtcSettings.energy_kWhtoday = Energy.kWhtoday; - Energy.daily = (float)Energy.kWhtoday / 100000; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000; + uint32_t energy_diff = Energy.kWhtoday_offset + Energy.kWhtoday - RtcSettings.energy_kWhtoday; + + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; + Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; + Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; if ((RtcTime.hour < Settings.param[P_ENERGY_TARIFF2]) || // Tarrif1 = Off-Peak (RtcTime.hour >= Settings.param[P_ENERGY_TARIFF1]) || (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || (RtcTime.day_of_week == 7))) ) { - Energy.kWhtoday1 += energy_diff; - RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; - Energy.total1 = (float)(RtcSettings.energy_usage.usage1_kWhtotal + Energy.kWhtoday1) / 100000; + RtcSettings.energy_usage.usage1_kWhtoday += energy_diff; + Energy.total1 = (float)(RtcSettings.energy_usage.usage1_kWhtotal + RtcSettings.energy_usage.usage1_kWhtoday) / 100000; } } void EnergyUpdateTotal(float value, bool kwh) { + char energy_total_chr[FLOATSZ]; + dtostrfd(value, 4, energy_total_chr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total %s %sWh"), energy_total_chr, (kwh) ? "k" : ""); + uint32_t multiplier = (kwh) ? 100000 : 100; // kWh or Wh to deca milli Wh if (0 == Energy.start_energy || (value < Energy.start_energy)) { Energy.start_energy = value; // Init after restart and handle roll-over if any -// RtcSettings.energy_kWhtotal = (unsigned long)(value * multiplier); -// Energy.kWhtoday = 0; -// RtcSettings.energy_kWhtoday = 0; } else if (value != Energy.start_energy) { - Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * multiplier); - Energy.start_energy = value; + Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); } EnergyUpdateToday(); } /*********************************************************************************************/ -void Energy200ms(void) +void Energy100ms(void) { Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; - Energy.fifth_second++; - if (5 == Energy.fifth_second) { - Energy.fifth_second = 0; + Energy.tenth_second++; + if (30 == Energy.tenth_second) { + Energy.tenth_second = 0; + } + + if ((Energy.tenth_second % 10) == 0) { XnrgCall(FUNC_ENERGY_EVERY_SECOND); if (RtcTime.valid) { if (LocalTime() == Midnight()) { - Settings.energy_kWhyesterday = Energy.kWhtoday; + Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal += Energy.kWhtoday; - RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; + RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; Energy.kWhtoday = 0; + Energy.kWhtoday_offset = 0; RtcSettings.energy_kWhtoday = 0; + Energy.start_energy = 0; - Settings.energy_usage.usage1_kWhtotal += Energy.kWhtoday1; - RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_usage.usage1_kWhtotal; - Energy.kWhtoday1 = 0; + RtcSettings.energy_usage.usage1_kWhtotal += RtcSettings.energy_usage.usage1_kWhtoday; + Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; RtcSettings.energy_usage.usage1_kWhtoday = 0; Energy.kWhtoday_delta = 0; @@ -205,19 +209,23 @@ void Energy200ms(void) } } - XnrgCall(FUNC_EVERY_200_MSECOND); + if (Energy.tenth_second &1) { + XnrgCall(FUNC_EVERY_200_MSECOND); + } + + if ((Energy.tenth_second % 3) == 0) { + XnrgCall(FUNC_EVERY_300_MSECOND); + } } void EnergySaveState(void) { Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; - Settings.energy_kWhtoday = Energy.kWhtoday; - RtcSettings.energy_kWhtoday = Energy.kWhtoday; + Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Settings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; - RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1; + Settings.energy_usage.usage1_kWhtoday = RtcSettings.energy_usage.usage1_kWhtoday; Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; } @@ -440,13 +448,14 @@ void CmndEnergyReset(void) if (p != XdrvMailbox.data) { switch (XdrvMailbox.index) { case 1: - Energy.kWhtoday = lnum *100; + Energy.kWhtoday_offset = lnum *100; + Energy.kWhtoday = 0; Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday; - Settings.energy_kWhtoday = Energy.kWhtoday; - RtcSettings.energy_kWhtoday = Energy.kWhtoday; - Energy.daily = (float)Energy.kWhtoday / 100000; - if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday) { + Energy.period = Energy.kWhtoday_offset; + Settings.energy_kWhtoday = Energy.kWhtoday_offset; + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; + Energy.daily = (float)Energy.kWhtoday_offset / 100000; + if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { Settings.energy_kWhtotal_time = LocalTime(); } break; @@ -456,14 +465,14 @@ void CmndEnergyReset(void) case 3: RtcSettings.energy_kWhtotal = lnum *100; Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000; - Settings.energy_kWhtotal_time = (!Energy.kWhtoday) ? LocalTime() : Midnight(); + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); break; } } - if (Energy.kWhtoday1 > Energy.kWhtoday) { - Energy.kWhtoday1 = Energy.kWhtoday; + if (RtcSettings.energy_usage.usage1_kWhtoday > (Energy.kWhtoday_offset + Energy.kWhtoday)) { + RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; } if (Settings.energy_usage.usage1_kWhtoday > Settings.energy_kWhtoday) { Settings.energy_usage.usage1_kWhtoday = Settings.energy_kWhtoday; @@ -704,12 +713,22 @@ void EnergySnsInit(void) XnrgCall(FUNC_INIT); if (energy_flg) { - Energy.kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0; - Energy.kWhtoday1 = (RtcSettingsValid()) ? RtcSettings.energy_usage.usage1_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_usage.usage1_kWhtoday : 0; + if (RtcSettingsValid()) { + Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; + } + else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { + Energy.kWhtoday_offset = Settings.energy_kWhtoday; + RtcSettings.energy_usage.usage1_kWhtoday = Settings.energy_usage.usage1_kWhtoday; + } + else { + Energy.kWhtoday_offset = 0; + RtcSettings.energy_usage.usage1_kWhtoday = 0; + } + Energy.kWhtoday = 0; Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday; + Energy.period = Energy.kWhtoday_offset; EnergyUpdateToday(); - ticker_energy.attach_ms(200, Energy200ms); + ticker_energy.attach_ms(100, Energy100ms); } } @@ -788,8 +807,8 @@ void EnergyShow(bool json) float energy = 0; char energy_period_chr[FLOATSZ]; if (show_energy_period) { - if (Energy.period) energy = (float)(Energy.kWhtoday - Energy.period) / 100; - Energy.period = Energy.kWhtoday; + if (Energy.period) energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; + Energy.period = RtcSettings.energy_kWhtoday; dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); } diff --git a/sonoff/xnrg_09_sdm120.ino b/sonoff/xnrg_09_sdm120.ino index af8a7e214..6ef7f71ae 100644 --- a/sonoff/xnrg_09_sdm120.ino +++ b/sonoff/xnrg_09_sdm120.ino @@ -78,7 +78,7 @@ struct SDM220 { /*********************************************************************************************/ -void SDM120Every200ms(void) +void SDM120Every300ms(void) { bool data_ready = Sdm120Modbus->ReceiveReady(); @@ -262,8 +262,8 @@ int Xnrg09(uint8_t function) case FUNC_INIT: Sdm120SnsInit(); break; - case FUNC_EVERY_200_MSECOND: - if (uptime > 4) { SDM120Every200ms(); } + case FUNC_EVERY_300_MSECOND: + if (uptime > 4) { SDM120Every300ms(); } break; #ifdef USE_SDM220 From 8b15fe8c0bf7480c95985d73af3286c6ba0f62af Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Fri, 6 Sep 2019 20:03:42 -0300 Subject: [PATCH 35/40] Update it-IT.h --- sonoff/language/it-IT.h | 58 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 8bbdb8b35..287206488 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -147,9 +147,9 @@ #define D_START "Start" #define D_STD_TIME "STD" #define D_STOP "Stop" -#define D_SUBNET_MASK "Maschera sottorete" +#define D_SUBNET_MASK "Maschera Subnet" #define D_SUBSCRIBE_TO "Sottoscrivi a" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_UNSUBSCRIBE_FROM "Cancella da" #define D_SUCCESSFUL "Riuscito" #define D_SUNRISE "Alba" #define D_SUNSET "Tramonto" @@ -161,16 +161,16 @@ #define D_TRANSMIT "Trasmesso" #define D_TRUE "Vero" #define D_TVOC "TVOC" -#define D_UPGRADE "aggiornamento" +#define D_UPGRADE "Aggiornamento" #define D_UPLOAD "Invio" #define D_UPTIME "Uptime" #define D_USER "Utente" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_1 "Basso" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Pericolo" #define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_7 "OoR" @@ -186,7 +186,7 @@ #define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" #define D_LEVEL_10 "level 1-0" #define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Log seriale disabilitato" +#define D_SERIAL_LOGGING_DISABLED "Syslog disabilitato" #define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" #define D_SET_BAUDRATE_TO "Baudrate impostato a" @@ -198,11 +198,11 @@ #define D_OSWATCH "osWatch" #define D_BLOCKED_LOOP "Ciclo Bloccato" #define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" -#define D_ACTIVE_FOR_3_MINUTES "attivo per 3 minuti" +#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti" #define D_FAILED_TO_START "partenza fallita" #define D_PATCH_ISSUE_2186 "Patch issue 2186" #define D_CONNECTING_TO_AP "Connessione ad AP" -#define D_IN_MODE "in modalità" +#define D_IN_MODE "In modalità" #define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" #define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" #define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" @@ -259,8 +259,8 @@ #define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_ADC "ADC" #define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" +#define D_SERIAL_IN "Seriale In" +#define D_SERIAL_OUT "Seriale Out" #define D_WIFI_PARAMETERS "Parametri Wifi" #define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" @@ -283,30 +283,30 @@ #define D_FULL_TOPIC "Full Topic" #define D_LOGGING_PARAMETERS "Parametri Logging" -#define D_SERIAL_LOG_LEVEL "Seriale livello di log" -#define D_WEB_LOG_LEVEL "Web livello di log" -#define D_SYS_LOG_LEVEL "Sys livello di log" +#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" +#define D_WEB_LOG_LEVEL "livello di log Web" +#define D_SYS_LOG_LEVEL "livello di log Sys" #define D_MORE_DEBUG "Debug aggiuntivo" #define D_SYSLOG_HOST "Syslog host" #define D_SYSLOG_PORT "Syslog porta" #define D_TELEMETRY_PERIOD "Periodo Telemetria" #define D_OTHER_PARAMETERS "Altri parametri" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" +#define D_TEMPLATE "Modello" +#define D_ACTIVATE "Attivare" #define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" #define D_MQTT_ENABLE "Abilita MQTT" -#define D_FRIENDLY_NAME "Nome confidenziale" +#define D_FRIENDLY_NAME "Nome amichevole" #define D_BELKIN_WEMO "Belkin WeMo" #define D_HUE_BRIDGE "Hue Bridge" #define D_SINGLE_DEVICE "dispositivo singolo" #define D_MULTI_DEVICE "dispositivo multiplo" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" +#define D_CONFIGURE_TEMPLATE "Configurare Modello" +#define D_TEMPLATE_PARAMETERS "Parametri Modello" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Baseto nel" +#define D_TEMPLATE_FLAGS "Opzioni" #define D_SAVE_CONFIGURATION "Salva configurazione" #define D_CONFIGURATION_SAVED "Configurazione salvata" @@ -464,12 +464,12 @@ #define D_PARTICALS_BEYOND "Particelle" // xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" +#define D_AX_AXIS "Accel. Asse-X" +#define D_AY_AXIS "Accel. Asse-Y" +#define D_AZ_AXIS "Accel. Asse-Z" +#define D_GX_AXIS "Gyro Asse-X" +#define D_GY_AXIS "Gyro Asse-Y" +#define D_GZ_AXIS "Gyro Asse-Z" // xsns_34_hx711.ino #define D_HX_CAL_REMOVE "Rimuovere peso" From 0c8ac27b54cc129a281873ab4dadf2758b1b1265 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Fri, 6 Sep 2019 20:30:49 -0300 Subject: [PATCH 36/40] Update pt-BR.h --- sonoff/language/pt-BR.h | 130 ++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index c62c9fe32..9099b21a0 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -65,8 +65,8 @@ #define D_BY "por" // Write by me #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" -#define D_CO2 "Dióxido de carbono" +#define D_CHANNEL "Canal" +#define D_CO2 "CO2" #define D_CODE "Código" // Button code #define D_COLDLIGHT "Luz fria" #define D_COMMAND "Comando" @@ -93,14 +93,14 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Arquivo" -#define D_FLOW_RATE "Flow rate" +#define D_FLOW_RATE "Quociente de vazão" #define D_FREE_MEMORY "Memória livre" #define D_FREQUENCY "Frequência" #define D_GAS "Gás" #define D_GATEWAY "Gateway" #define D_GROUP "Grupo" -#define D_HOST "Anfitrião" -#define D_HOSTNAME "Nome do anfitrião" +#define D_HOST "Host" +#define D_HOSTNAME "Nome do Host" #define D_HUMIDITY "Umidade" #define D_ILLUMINANCE "Luminância" #define D_IMMEDIATE "Imediato" // Button immediate @@ -167,10 +167,10 @@ #define D_USER "Usuário" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Perigro" #define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_7 "OoR" @@ -178,7 +178,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Weight" +#define D_WEIGHT "Peso" #define D_WARMLIGHT "Luz quente" #define D_WEB_SERVER "Servidor WEB" @@ -186,7 +186,7 @@ #define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" #define D_LEVEL_10 "nível 1-0" #define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro em série desabilitado" +#define D_SERIAL_LOGGING_DISABLED "Registro do Syslog desabilitado" #define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" #define D_SET_BAUDRATE_TO "Ajuste da velocidade para" @@ -292,7 +292,7 @@ #define D_TELEMETRY_PERIOD "Período de telemetria" #define D_OTHER_PARAMETERS "Outros parâmetros" -#define D_TEMPLATE "Template" +#define D_TEMPLATE "Modelo" #define D_ACTIVATE "Activate" #define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" #define D_MQTT_ENABLE "MQTT habilitado" @@ -302,11 +302,11 @@ #define D_SINGLE_DEVICE "Dispositivo único" #define D_MULTI_DEVICE "Múltiplos dispositivos" -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" #define D_SAVE_CONFIGURATION "Gravar configuração" #define D_CONFIGURATION_SAVED "Configuração gravada" @@ -347,10 +347,10 @@ #define D_UPLOAD_ERR_7 "Envio cancelado" #define D_UPLOAD_ERR_8 "Arquivo inválido" #define D_UPLOAD_ERR_9 "Arquivo muito grande" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" +#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" @@ -472,27 +472,27 @@ #define D_GZ_AXIS "Gyro Z-Axis" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Peso de referência de carga" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Redefinir escala" +#define D_CONFIGURE_HX711 "Configurar escala" +#define D_HX711_PARAMETERS "Parâmetros de escala" +#define D_ITEM_WEIGHT "Peso do Item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" #define D_TX20_NORTH "N" -#define D_TX20_EAST "E" +#define D_TX20_EAST "L" #define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" +#define D_TX20_WEST "O" //xsns_43_hre.ino #define D_LOG_HRE "HRE: " @@ -657,37 +657,37 @@ #define D_LOG_WIFI "WIF: " // Wifi //SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" +#define D_PHASE_ANGLE "Ângulo de Fase" +#define D_IMPORT_ACTIVE "Importar Ativo" +#define D_EXPORT_ACTIVE "Exportar Ativo" +#define D_IMPORT_REACTIVE "Importar Reativo" +#define D_EXPORT_REACTIVE "Exportar Reativo" +#define D_TOTAL_REACTIVE "Reativo total" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" +#define D_PV1_VOLTAGE "PV1 Voltagem" +#define D_PV1_CURRENT "PV1 Corrente" +#define D_PV1_POWER "PV1 Energia" +#define D_PV2_VOLTAGE "PV2 Voltagem" +#define D_PV2_CURRENT "PV2 Corrente" +#define D_PV2_POWER "PV2 Energia" +#define D_SOLAR_POWER "Energia Solar" +#define D_INVERTER_POWER "Potência do Inversor" #define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Erro Grid Perdida" +#define D_SOLAX_ERROR_2 "Falha na Tensão da rede" +#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid" +#define D_SOLAX_ERROR_4 "Pv Falha de Tensão" +#define D_SOLAX_ERROR_5 "Falha de Isolamento" +#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no Ventilador" +#define D_SOLAX_ERROR_8 "Outra falha do dispositivo" #endif // _LANGUAGE_PT_BR_H_ From 5eb09495c2aee380adb3f017fc6006a3229d85d0 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sat, 7 Sep 2019 11:24:57 -0300 Subject: [PATCH 37/40] Update it-IT.h --- sonoff/language/it-IT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 287206488..d76460815 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -186,7 +186,7 @@ #define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" #define D_LEVEL_10 "level 1-0" #define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Syslog disabilitato" +#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato" #define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" #define D_SET_BAUDRATE_TO "Baudrate impostato a" From 299a14fed4c1095eacd1f41b35abd05ea5cd43c4 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sat, 7 Sep 2019 11:25:53 -0300 Subject: [PATCH 38/40] Update pt-BR.h --- sonoff/language/pt-BR.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 9099b21a0..15ec61b9c 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -186,7 +186,7 @@ #define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" #define D_LEVEL_10 "nível 1-0" #define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro do Syslog desabilitado" +#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado" #define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" #define D_SET_BAUDRATE_TO "Ajuste da velocidade para" From fc2be924783319fe4d58a59b647e61956911a73f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 7 Sep 2019 16:31:39 +0200 Subject: [PATCH 39/40] Move SDM120 modbus updates out of ticker interrupt Move SDM120 modbus updates out of ticker interrupt (#6282) --- sonoff/xdrv_03_energy.ino | 26 ++++++++++---------------- sonoff/xnrg_09_sdm120.ino | 6 +++--- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index d22dae114..ef3c98145 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -88,7 +88,7 @@ struct ENERGY { unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily - uint8_t tenth_second = 0; + uint8_t fifth_second = 0; uint8_t command_code = 0; uint8_t data_valid = 0; @@ -165,16 +165,13 @@ void EnergyUpdateTotal(float value, bool kwh) /*********************************************************************************************/ -void Energy100ms(void) +void Energy200ms(void) { Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; - Energy.tenth_second++; - if (30 == Energy.tenth_second) { - Energy.tenth_second = 0; - } - - if ((Energy.tenth_second % 10) == 0) { + Energy.fifth_second++; + if (5 == Energy.fifth_second) { + Energy.fifth_second = 0; XnrgCall(FUNC_ENERGY_EVERY_SECOND); @@ -209,13 +206,7 @@ void Energy100ms(void) } } - if (Energy.tenth_second &1) { - XnrgCall(FUNC_EVERY_200_MSECOND); - } - - if ((Energy.tenth_second % 3) == 0) { - XnrgCall(FUNC_EVERY_300_MSECOND); - } + XnrgCall(FUNC_EVERY_200_MSECOND); } void EnergySaveState(void) @@ -728,7 +719,7 @@ void EnergySnsInit(void) Energy.kWhtoday_delta = 0; Energy.period = Energy.kWhtoday_offset; EnergyUpdateToday(); - ticker_energy.attach_ms(100, Energy100ms); + ticker_energy.attach_ms(200, Energy200ms); } } @@ -907,6 +898,9 @@ bool Xdrv03(uint8_t function) case FUNC_LOOP: XnrgCall(FUNC_LOOP); break; + case FUNC_EVERY_250_MSECOND: + XnrgCall(FUNC_EVERY_250_MSECOND); + break; #ifdef USE_ENERGY_MARGIN_DETECTION case FUNC_SET_POWER: Energy.power_steady_counter = 2; diff --git a/sonoff/xnrg_09_sdm120.ino b/sonoff/xnrg_09_sdm120.ino index 6ef7f71ae..368c64021 100644 --- a/sonoff/xnrg_09_sdm120.ino +++ b/sonoff/xnrg_09_sdm120.ino @@ -78,7 +78,7 @@ struct SDM220 { /*********************************************************************************************/ -void SDM120Every300ms(void) +void SDM120Every250ms(void) { bool data_ready = Sdm120Modbus->ReceiveReady(); @@ -262,8 +262,8 @@ int Xnrg09(uint8_t function) case FUNC_INIT: Sdm120SnsInit(); break; - case FUNC_EVERY_300_MSECOND: - if (uptime > 4) { SDM120Every300ms(); } + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM120Every250ms(); } break; #ifdef USE_SDM220 From 2e9f06f8bf6fc481a40373fe5c0163882db767da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 7 Sep 2019 18:32:11 +0200 Subject: [PATCH 40/40] Bump version to 6.6.0.11 Change Settings crc calculation allowing short term backward compatibility --- sonoff/_changelog.ino | 3 +++ sonoff/settings.ino | 43 ++++++++++++++++++++++-------------- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 17 +++++++------- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 359289b3d..aefb1b821 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 6.6.0.11 20190907 + * Change Settings crc calculation allowing short term backward compatibility + * * 6.6.0.10 20190905 * Redesign Tuya support by Shantur Rathore (#6353) * Add command Reset 99 to reset bootcount to zero (#684, #6351) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 97f41e167..9534c0ab6 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -274,8 +274,7 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) uint32_t settings_location = SETTINGS_LOCATION; -//uint32_t settings_crc32 = 0; -uint16_t settings_crc = 0; +uint32_t settings_crc32 = 0; uint8_t *settings_buffer = nullptr; /********************************************************************************************/ @@ -319,27 +318,29 @@ bool SettingsBufferAlloc(void) return true; } -uint16_t GetSettingsCrc(void) +uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) { uint16_t crc = 0; - uint8_t *bytes = (uint8_t*)&Settings; - // Fix miscalculation if previous Settings was 3584 and current Settings is 4096 as of 0x06060007 - uint32_t size = (Settings.version < 0x06060007) ? 3584 : sizeof(SYSCFG); for (uint32_t i = 0; i < size; i++) { if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip crc } return crc; } -uint32_t GetSettingsCrc32(void) +uint16_t GetSettingsCrc(void) +{ + // Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A + uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); + return GetCfgCrc16((uint8_t*)&Settings, size); +} + +uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) { // https://create.stephan-brumme.com/crc32/#bitwise uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&Settings; - uint32_t length = sizeof(SYSCFG) -4; // Skip crc - while (length--) { + while (size--) { crc ^= *bytes++; for (uint32_t j = 0; j < 8; j++) { crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); @@ -348,6 +349,11 @@ uint32_t GetSettingsCrc32(void) return ~crc; } +uint32_t GetSettingsCrc32(void) +{ + return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32 +} + void SettingsSaveAll(void) { if (Settings.flag.save_state) { @@ -380,7 +386,7 @@ void SettingsSave(uint8_t rotate) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ #ifndef FIRMWARE_MINIMAL - if ((GetSettingsCrc() != settings_crc) || rotate) { + if ((GetSettingsCrc32() != settings_crc32) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) stop_flash_rotate = 1; } @@ -395,6 +401,7 @@ void SettingsSave(uint8_t rotate) settings_location = SETTINGS_LOCATION; } } + Settings.save_flag++; if (UtcTime() > START_VALID_TIME) { Settings.cfg_timestamp = UtcTime(); @@ -402,8 +409,8 @@ void SettingsSave(uint8_t rotate) Settings.cfg_timestamp++; } Settings.cfg_size = sizeof(SYSCFG); -// Settings.cfg_crc32 = GetSettingsCrc32(); - Settings.cfg_crc = GetSettingsCrc(); + Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade + Settings.cfg_crc32 = GetSettingsCrc32(); ESP.flashEraseSector(settings_location); ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); @@ -417,8 +424,7 @@ void SettingsSave(uint8_t rotate) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - settings_crc = Settings.cfg_crc; -// settings_crc32 = Settings.cfg_crc32; + settings_crc32 = Settings.cfg_crc32; } #endif // FIRMWARE_MINIMAL RtcSettingsSave(); @@ -443,7 +449,10 @@ void SettingsLoad(void) bool valid = false; if (Settings.version > 0x06000000) { - bool almost_valid = (Settings.cfg_crc == GetSettingsCrc()); + bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); + if (Settings.version < 0x0606000B) { + almost_valid = (Settings.cfg_crc == GetSettingsCrc()); + } // Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder valid = (cfg_holder == Settings.cfg_holder); @@ -472,7 +481,7 @@ void SettingsLoad(void) if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h SettingsDefault(); } - settings_crc = GetSettingsCrc(); + settings_crc32 = GetSettingsCrc32(); #endif // FIRMWARE_MINIMAL RtcSettingsLoad(); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 962434a63..b7eae8a8f 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x0606000A; +const uint32_t VERSION = 0x0606000B; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 003d9d765..606e40616 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1687,8 +1687,8 @@ void HandleBackupConfiguration(void) WSSend(200, CT_STREAM, ""); - uint16_t cfg_crc = Settings.cfg_crc; - Settings.cfg_crc = GetSettingsCrc(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918) + uint32_t cfg_crc32 = Settings.cfg_crc32; + Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918) memcpy(settings_buffer, &Settings, sizeof(Settings)); if (Web.config_xor_on_set) { @@ -1708,7 +1708,7 @@ void HandleBackupConfiguration(void) SettingsBufferFree(); - Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed + Settings.cfg_crc32 = cfg_crc32; // Restore crc in case savedata = 0 to make sure settings will be noted as changed } /*-------------------------------------------------------------------------------------------*/ @@ -2093,12 +2093,13 @@ void HandleUploadLoop(void) unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8]; if (buffer_version > 0x06000000) { uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2]; - uint16_t buffer_crc = settings_buffer[15] << 8 | settings_buffer[14]; - uint16_t crc = 0; - for (uint32_t i = 0; i < buffer_size; i++) { - if ((i < 14) || (i > 15)) { crc += settings_buffer[i]*(i+1); } // Skip crc + if (buffer_version > 0x0606000A) { + uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092]; + valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32); + } else { + uint16_t buffer_crc16 = settings_buffer[15] << 8 | settings_buffer[14]; + valid_settings = (GetCfgCrc16(settings_buffer, buffer_size) == buffer_crc16); } - valid_settings = (buffer_crc == crc); } else { valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN); }