From 5f759b03c24883069761dfc1403e49e9ab48ec48 Mon Sep 17 00:00:00 2001 From: Staars Date: Sat, 21 Mar 2020 10:17:21 +0100 Subject: [PATCH 01/56] update xsns_62_MI_HM10.ino --- tasmota/xsns_62_MI_HM10.ino | 751 +++++++++++++++++++++++++++--------- 1 file changed, 562 insertions(+), 189 deletions(-) diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index 17cc094ad..83252c4f6 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -20,7 +20,9 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- - + 0.9.2.0 20200317 added - MiBeacon-support, add Flora, MJ_HT_V1 and CGD1, add dew point, + add AUTO(-scan), RULES-message + --- 0.9.1.0 20200209 added - LYWSD02-support, including setting the time --- 0.9.0.0 20200130 started - initial development by Christian Baars (support LYWSD03 only) @@ -40,8 +42,7 @@ TasmotaSerial *HM10Serial; #define HM10_MAX_TASK_NUMBER 12 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms -#define HM10_MAX_RX_BUF 512 -char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; +#define HM10_MAX_RX_BUF 160 struct { uint8_t current_task_delay; // number of 100ms-cycles @@ -53,13 +54,14 @@ struct { uint32_t time; uint8_t timebuf[4]; }; + uint16_t autoScanInterval; struct { + uint32_t awaiting:8; uint32_t init:1; uint32_t pending_task:1; uint32_t connected:1; uint32_t subscribed:1; - uint32_t awaitingHT:1; - uint32_t awaitingB:1; + uint32_t autoScan:1; // TODO: more to come } mode; struct { @@ -68,15 +70,52 @@ struct { } state; } HM10; -#pragma pack(1) +#pragma pack(1) // byte-aligned structures to read the sensor data struct { uint16_t temp; uint8_t hum; } LYWSD0x_HT; + +struct { + uint8_t spare; + uint16_t temp; + uint16_t hum; +} CGD1_HT; + +struct { + uint16_t temp; + uint8_t spare; + uint32_t lux; + uint8_t moist; + uint16_t fert; +} Flora_TLMF; // temeprature, lux, moisture, fertility + +struct mi_beacon_t{ + uint16_t frame; + uint16_t productID; + uint8_t counter; + uint8_t Mac[6]; + uint8_t spare; + uint8_t type; + uint8_t ten; + uint8_t size; + union { + struct{ //0d + uint16_t temp; + uint16_t hum; + }HT; + uint8_t bat; //0a + uint16_t temp; //04 + uint16_t hum; //06 + uint32_t lux; //07 + uint8_t moist; //08 + uint16_t fert; //09 + }; +}; #pragma pack(0) struct mi_sensor_t{ - uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4 + uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 uint8_t serial[6]; uint8_t showedUp; float temp; //Flora, MJ_HT_V1, LYWSD0x @@ -84,13 +123,13 @@ struct mi_sensor_t{ struct { float moisture; float fertility; - uint16_t lux; + uint32_t lux; }; // Flora struct { float hum; - uint8_t bat; }; // MJ_HT_V1, LYWSD0x }; + uint8_t bat; }; std::vector MIBLEsensors; @@ -103,24 +142,30 @@ std::vector MIBLEsensors; const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; -const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time"; +const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto"; #define FLORA 1 #define MJ_HT_V1 2 #define LYWSD02 3 #define LYWSD03MMC 4 +#define CGG1 5 +#define CGD1 6 -uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, // Flora - 0x58,0x2D,0x34, // MJ_HT_V1 - 0xE7,0x2E,0x00, // LYWSD02 - 0xA4,0xC1,0x38, // LYWSD03 - }; +const uint16_t kHM10SlaveID[6]={ 0x0098, // Flora + 0x01aa, // MJ_HT_V1 + 0x045b, // LYWSD02 + 0x055b, // LYWSD03 + 0x0347, // CGG1 + 0x0576 // CGD1 + }; const char kHM10SlaveType1[] PROGMEM = "Flora"; const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; -const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; +const char kHM10SlaveType5[] PROGMEM = "CGG1"; +const char kHM10SlaveType6[] PROGMEM = "CGD1"; +const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4,kHM10SlaveType5,kHM10SlaveType6}; /*********************************************************************************************\ * enumerations @@ -131,9 +176,19 @@ enum HM10_Commands { // commands useable in console or rules CMND_HM10_AT, // send AT-command for debugging and special configuration CMND_HM10_PERIOD, // set period like TELE-period in seconds between read-cycles CMND_HM10_BAUD, // serial speed of ESP8266 (<-> HM10), does not change baud rate of HM10 - CMND_HM10_TIME // set LYWSD02-Time from ESP8266-time + CMND_HM10_TIME, // set LYWSD02-Time from ESP8266-time + CMND_HM10_AUTO // do discovery scans permanently to receive MiBeacons in seconds between read-cycles }; +enum HM10_awaitData: uint8_t { + none = 0, + tempHumLY = 1, + TLMF = 2, + bat = 3, + tempHumCGD1 = 4, + discScan = 5 + }; + /*********************************************************************************************\ * Task codes defines \*********************************************************************************************/ @@ -143,7 +198,7 @@ enum HM10_Commands { // commands useable in console or rules #define TASK_HM10_IMME1 2 // change imme to 1 #define TASK_HM10_RENEW 3 // device factory setting #define TASK_HM10_RESET 4 // device reset -#define TASK_HM10_DISC 5 // device discovery scan +#define TASK_HM10_DISC 5 // device discovery scan: AT+DISA? #define TASK_HM10_CONN 6 // connect to given MAC #define TASK_HM10_VERSION 7 // query FW version #define TASK_HM10_NAME 8 // query device name @@ -151,14 +206,23 @@ enum HM10_Commands { // commands useable in console or rules #define TASK_HM10_DISCONN 10 // disconnect #define TASK_HM10_SUB_L3 11 // subscribe to service handle 37 #define TASK_HM10_READ_HT 12 // read from handle 36 -> Hum & Temp -#define TASK_HM10_FINDALLCHARS 13 // read all available characteristics -#define TASK_HM10_UN_L3 14 // subscribe service handle 37 -#define TASK_HM10_DELAY_SUB 15 // start reading from subscription delayed +#define TASK_HM10_SCAN9 13 // longest discovery scan possible +#define TASK_HM10_UN_L3 14 // unsubscribe service handle 37 +#define TASK_HM10_DELAY_SUB_LY 15 // start reading from subscription delayed #define TASK_HM10_READ_BT_L3 16 // read from handle 3A -> Battery #define TASK_HM10_SUB_L2 17 // subscribe to service handle 3C -#define TASK_HM10_UN_L2 18 // subscribe service handle 3C +#define TASK_HM10_UN_L2 18 // unsubscribe service handle 3C #define TASK_HM10_READ_BT_L2 19 // read from handle 43 -> Battery #define TASK_HM10_TIME_L2 20 // set time of LYWSD02 to system time +#define TASK_HM10_SHOW0 21 // set verbositiy to minimum +#define TASK_HM10_READ_BF_FL 22 // read battery and firmware from flower care +#define TASK_HM10_CALL_TLMF_FL 23 // write 0xa01f to handle 0x33 to init sensor readings +#define TASK_HM10_READ_TLMF_FL 24 // read temp,lux,moist and fert from flower care +#define TASK_HM10_SUB_HT_CGD1 25 // subscribe to service handle 4b +#define TASK_HM10_UN_HT_CGD1 26 // unsubscribe service handle 4b +#define TASK_HM10_READ_B_CGD1 27 // read service handle 11 +#define TASK_HM10_DELAY_SUB_CGD1 28 // start reading from subscription delayed +#define TASK_HM10_STATUS_EVENT 29 // process status for RULES #define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait @@ -178,6 +242,14 @@ void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ HM10_TASK_LIST[slot][0] = task; } +void HM10_ReverseMAC(uint8_t _mac[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _mac[i]; + } + memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); +} + /*********************************************************************************************\ * chained tasks \*********************************************************************************************/ @@ -187,12 +259,15 @@ void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disco HM10_Launchtask(TASK_HM10_IMME1,2,1); // set imme to 1 HM10_Launchtask(TASK_HM10_RESET,3,1); // reset Device HM10_Launchtask(TASK_HM10_VERSION,4,10); // read SW Version - HM10_Launchtask(TASK_HM10_DISC,5,50); // discovery + HM10_Launchtask(TASK_HM10_SCAN9,5,2); // scan time 9 seconds + HM10_Launchtask(TASK_HM10_DISC,6,2); // discovery + HM10_Launchtask(TASK_HM10_STATUS_EVENT,7,2); // status } void HM10_Discovery_Scan(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); // disconnect - HM10_Launchtask(TASK_HM10_DISC,1,1); // discovery + HM10_Launchtask(TASK_HM10_DISC,1,5); // discovery + HM10_Launchtask(TASK_HM10_STATUS_EVENT,2,2); // status } void HM10_Read_LYWSD03(void) { @@ -221,66 +296,84 @@ void HM10_Time_LYWSD02(void) { HM10_Launchtask(TASK_HM10_DISCONN,4,5); // disconnect } +void HM10_Read_Flora(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,0); // disconnect + HM10_Launchtask(TASK_HM10_CONN,1,1); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,2,5); // get OK+CONN + HM10_Launchtask(TASK_HM10_READ_BF_FL,3,20); // read battery + HM10_Launchtask(TASK_HM10_CALL_TLMF_FL,4,30); // read TLMF + HM10_Launchtask(TASK_HM10_DISCONN,5,10); // disconnect + } + +void HM10_Read_CGD1(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN + HM10_Launchtask(TASK_HM10_SUB_HT_CGD1,2,20); // subscribe + HM10_Launchtask(TASK_HM10_UN_HT_CGD1,3,10); // unsubscribe + HM10_Launchtask(TASK_HM10_READ_B_CGD1,4,5); // read Battery + HM10_Launchtask(TASK_HM10_DISCONN,5,5); // disconnect + } + /** * @brief Return the slot number of a known sensor or return create new sensor slot * * @param _serial BLE address of the sensor - * @param _type Type number of the sensor, 0xff for Auto-type + * @param _type Type number of the sensor * @return uint32_t Known or new slot in the sensors-vector */ -uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kHM10SlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); - } +uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ + + DEBUG_SENSOR_LOG(PSTR("%s: will test ID-type: %x"),D_CMND_HM10, _type); + bool _success = false; + for (uint32_t i=0;i<6;i++){ // i < sizeof(kHM10SlaveID) gives compiler warning + if(_type == kHM10SlaveID[i]){ + DEBUG_SENSOR_LOG(PSTR("HM10: ID is type %u"), i); + _type = i+1; + _success = true; + } + else { + DEBUG_SENSOR_LOG(PSTR("%s: ID-type is not: %x"),D_CMND_HM10,kHM10SlaveID[i]); } } - if(_type==0xff) return _type; // error - - DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); + if(!_success) return 0xff; + + DEBUG_SENSOR_LOG(PSTR("%s: vector size %u"),D_CMND_HM10, MIBLEsensors.size()); for(uint32_t i=0; ihardwareSerial()) { ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); + DEBUG_SENSOR_LOG(PSTR("%s: claim HW"),D_CMND_HM10); } HM10_Reset(); HM10.mode.pending_task = 1; @@ -305,68 +398,147 @@ void HM10SerialInit(void) { return; } -/** - * @brief convert Mac-String to byte array - * - * @param string Hex-string, must contain 12 chars (no error checking) - * @param _mac Must be a uint8_t[6], filled with zeros - */ - -void HM10MACStringToBytes(const char* string, uint8_t _mac[]) { - uint32_t index = 0; - while (index < 12) { - char c = string[index]; - uint32_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _mac[(index/2)] += value << (((index + 1) % 2) * 4); - // DEBUG_SENSOR_LOG(PSTR("HM10: Char: %c, Value: %x, Index/2: %u, valueadded: %x, MAC-index: %x"), c, value,(index/2),value << (((index + 1) % 2) * 4), _mac[index/2]); - index++; - } - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); -} - - /*********************************************************************************************\ * parse the response \*********************************************************************************************/ -void HM10ParseResponse(char *buf) { +void HM10parseMiBeacon(char * _buf, uint32_t _slot){ + float _tempFloat; + mi_beacon_t _beacon; + if (MIBLEsensors.at(_slot).type==2){ + memcpy((uint8_t*)&_beacon+1,(uint8_t*)_buf, sizeof(_beacon)); // shift by one byte for the MJ_HT_V1 + memcpy((uint8_t*)&_beacon.Mac,(uint8_t*)&_beacon.Mac+1,6); // but shift back the MAC + } + else{ + memcpy((void*)&_beacon,(void*)_buf, sizeof(_beacon)); + } + HM10_ReverseMAC(_beacon.Mac); + if(memcmp(_beacon.Mac,MIBLEsensors.at(_slot).serial,sizeof(_beacon.Mac))!=0){ + if (MIBLEsensors.at(_slot).showedUp>3) return; // probably false alarm from a damaged packet + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: remove garbage sensor"),D_CMND_HM10); + DEBUG_SENSOR_LOG(PSTR("%s i: %x %x %x %x %x %x"),D_CMND_HM10, MIBLEsensors.at(_slot).serial[5], MIBLEsensors.at(_slot).serial[4],MIBLEsensors.at(_slot).serial[3],MIBLEsensors.at(_slot).serial[2],MIBLEsensors.at(_slot).serial[1],MIBLEsensors.at(_slot).serial[0]); + DEBUG_SENSOR_LOG(PSTR("%s n: %x %x %x %x %x %x"),D_CMND_HM10, _beacon.Mac[5], _beacon.Mac[4], _beacon.Mac[3],_beacon.Mac[2],_beacon.Mac[1],_beacon.Mac[0]); + MIBLEsensors.erase(MIBLEsensors.begin()+_slot); + return; + } + if (MIBLEsensors.at(_slot).showedUp<4) MIBLEsensors.at(_slot).showedUp++; + + DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); + DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); + + if(MIBLEsensors.at(_slot).type==4 || MIBLEsensors.at(_slot).type==6){ + DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors.at(_slot).type); + return; + } + DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kHM10SlaveType[MIBLEsensors.at(_slot).type-1],_slot); + switch(_beacon.type){ + case 0x04: + _tempFloat=(float)(_beacon.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); + break; + case 0x06: + _tempFloat=(float)(_beacon.hum)/10.0f; + if(_tempFloat<101){ + MIBLEsensors.at(_slot).hum=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum); + break; + case 0x07: + MIBLEsensors.at(_slot).lux=_beacon.lux & 0x00ffffff; + DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); + break; + case 0x08: + _tempFloat =(float)_beacon.moist; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).moisture=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); + break; + case 0x09: + _tempFloat=(float)(_beacon.fert); + if(_tempFloat<65535){ // ??? + MIBLEsensors.at(_slot).fertility=_tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); + break; + case 0x0a: + if(_beacon.bat<101){ + MIBLEsensors.at(_slot).bat = _beacon.bat; + DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat); + break; + case 0x0d: + _tempFloat=(float)(_beacon.HT.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated")); + } + _tempFloat=(float)(_beacon.HT.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); + break; + } +} + +void HM10ParseResponse(char *buf, uint16_t bufsize) { if (!strncmp(buf,"OK",2)) { - DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); + DEBUG_SENSOR_LOG(PSTR("%s: got OK"),D_CMND_HM10); } if (!strncmp(buf,"HMSoft",6)) { //8 const char* _fw = "000"; memcpy((void *)_fw,(void *)(buf+8),3); HM10.firmware = atoi(_fw); - DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); + DEBUG_SENSOR_LOG(PSTR("%s: Firmware: %d"),D_CMND_HM10, HM10.firmware); return; } - char * _pos = strstr(buf, "IS0:"); + char * _pos = strstr(buf, "ISA:"); if(_pos) { - const char* _mac = "000000000000"; - memcpy((void *)_mac,(void *)(_pos+4),12); - DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); uint8_t _newMacArray[6] = {0}; - HM10MACStringToBytes(_mac, _newMacArray); - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); - MIBLEgetSensorSlot(_newMacArray, 0xff); + memcpy((void *)_newMacArray,(void *)(_pos+4),6); + HM10_ReverseMAC(_newMacArray); + DEBUG_SENSOR_LOG(PSTR("%s: MAC-array: %02x%02x%02x%02x%02x%02x"),D_CMND_HM10,_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); + uint16_t _type=0xffff; + + for (uint32_t idx =10;idxavailable()) { // delay(0); if(iwrite("AT+ROLE1"); break; case TASK_HM10_IMME1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set imme to 1"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+IMME1"); break; case TASK_HM10_DISC: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); - HM10.current_task_delay = 35; // set task delay + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: start discovery"),D_CMND_HM10); + HM10.current_task_delay = 100; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; - HM10Serial->write("AT+DISC?"); + HM10.mode.awaiting = discScan; + HM10Serial->write("AT+DISA?"); break; case TASK_HM10_VERSION: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read version"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+VERR?"); break; case TASK_HM10_NAME: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read name"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+NAME?"); break; case TASK_HM10_CONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); + char _con[20]; + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: connect %s"),D_CMND_HM10, _con); HM10.current_task_delay = 2; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; - char _con[20]; - sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); HM10Serial->write(_con); - HM10.mode.awaitingB = false; + HM10.mode.awaiting = none; HM10.mode.connected = true; break; case TASK_HM10_DISCONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: disconnect"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT"); break; case TASK_HM10_RESET: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: Reset Device"),D_CMND_HM10); HM10Serial->write("AT+RESET"); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; break; case TASK_HM10_SUB_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); HM10.current_task_delay = 25; // set task delay - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB_LY,i); runningTaskLoop = false; HM10Serial->write("AT+NOTIFY_ON0037"); break; case TASK_HM10_UN_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; - HM10.mode.awaitingHT = false; + HM10.mode.awaiting = none; HM10Serial->write("AT+NOTIFYOFF0037"); break; case TASK_HM10_SUB_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe"),D_CMND_HM10); HM10.current_task_delay = 25; // set task delay - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB_LY,i); runningTaskLoop = false; HM10Serial->write("AT+NOTIFY_ON003C"); break; case TASK_HM10_UN_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; - HM10.mode.awaitingHT = false; + HM10.mode.awaiting = none; HM10Serial->write("AT+NOTIFYOFF003C"); break; case TASK_HM10_TIME_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set time"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: set time"),D_CMND_HM10); HM10.current_task_delay = 5; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; @@ -550,49 +795,114 @@ void HM10_TaskEvery100ms(){ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); break; case TASK_HM10_READ_HT: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0036"),D_CMND_HM10); HM10.current_task_delay = 0; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+READDATA0036?"); - HM10.mode.awaitingHT = true; + HM10.mode.awaiting = tempHumLY; break; case TASK_HM10_READ_BT_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 003A"),D_CMND_HM10); HM10.current_task_delay = 2; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+READDATA003A?"); - HM10.mode.awaitingB = true; + HM10.mode.awaiting = bat; break; case TASK_HM10_READ_BT_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0043"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0043"),D_CMND_HM10); HM10.current_task_delay = 2; // set task delay HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); runningTaskLoop = false; HM10Serial->write("AT+READDATA0043?"); - HM10.mode.awaitingB = true; + HM10.mode.awaiting = bat; + break; + case TASK_HM10_READ_BF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0038"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0038?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_CALL_TLMF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: write to handle 0033"),D_CMND_HM10); + HM10.current_task_delay = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_READ_TLMF_FL,i); + runningTaskLoop = false; + HM10Serial->write("AT+SEND_DATAWR0033"); + HM10Serial->write(0xa0); + HM10Serial->write(0x1f); + HM10.mode.awaiting = none; + break; + case TASK_HM10_READ_TLMF_FL: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0035"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0035?"); + HM10.mode.awaiting = TLMF; + break; + case TASK_HM10_READ_B_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0011"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0011?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_SUB_HT_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe 4b"),D_CMND_HM10); + HM10.current_task_delay = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB_CGD1,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + HM10Serial->write("AT+NOTIFY_ON004b"); + break; + case TASK_HM10_UN_HT_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: un-subscribe 4b"),D_CMND_HM10); + HM10.current_task_delay = 5; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + HM10Serial->write("AT+NOTIFYOFF004b"); + break; + case TASK_HM10_SCAN9: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: scan time to 9"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+SCAN9"); break; - // case TASK_HM10_FINDALLCHARS: - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s find all chars"),D_CMND_HM10); - // HM10.current_task_delay = 5; // set task delay - // HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - // runningTaskLoop = false; - // HM10Serial->write("AT+FINDALLCHARS?"); - // break; case TASK_HM10_FEEDBACK: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: get response"),D_CMND_HM10); HM10SerialHandleFeedback(); HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset runningTaskLoop = false; break; - case TASK_HM10_DELAY_SUB: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); + case TASK_HM10_DELAY_SUB_LY: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: start reading"),D_CMND_HM10); HM10SerialHandleFeedback(); HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset - HM10.mode.awaitingHT = true; + HM10.mode.awaiting = tempHumLY; + runningTaskLoop = false; + break; + case TASK_HM10_DELAY_SUB_CGD1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: start reading"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset + HM10.mode.awaiting = tempHumCGD1; + runningTaskLoop = false; + break; + case TASK_HM10_STATUS_EVENT: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: show status"),D_CMND_HM10); + HM10StatusInfo(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; // set task delay + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; // no feedback for reset runningTaskLoop = false; break; case TASK_HM10_DONE: // this entry was already handled @@ -619,39 +929,74 @@ void HM10_TaskEvery100ms(){ } } +void HM10StatusInfo(){ + char stemp[20]; + snprintf_P(stemp, sizeof(stemp),PSTR("{%s:{\"found\": %u}}"),D_CMND_HM10, MIBLEsensors.size()); + AddLog_P2(LOG_LEVEL_INFO, stemp); + RulesProcessEvent(stemp); +} + /** * @brief Main loop of the driver, "high level"-loop * */ void HM10EverySecond(){ - if(HM10.firmware == 0) return; - if(HM10.mode.pending_task == 1) return; - if (MIBLEsensors.size()==0) return; - static uint32_t _counter = 0; static uint32_t _nextSensorSlot = 0; + static uint32_t _lastDiscovery = 0; + + if(HM10.firmware == 0) return; + if(HM10.mode.pending_task == 1) return; + if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return; + + if((HM10.period-_counter)>15 && HM10.mode.autoScan) { + if(_counter-_lastDiscovery>HM10.autoScanInterval){ + HM10_Discovery_Scan(); + HM10.mode.pending_task = 1; + _counter+=12; + _lastDiscovery = _counter; + return; + } + } + if(_counter==0) { HM10.state.sensor = _nextSensorSlot; _nextSensorSlot++; - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD03(); - } - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD02) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD02(); + HM10.mode.pending_task = 1; + switch(MIBLEsensors.at(HM10.state.sensor).type){ + case LYWSD03MMC: + HM10_Read_LYWSD03(); + break; + case LYWSD02: + HM10_Read_LYWSD02(); + break; + case FLORA: + HM10_Read_Flora(); + break; + case CGD1: + HM10_Read_CGD1(); + break; + default: + HM10.mode.pending_task = 0; } if (HM10.state.sensor==MIBLEsensors.size()-1) { _nextSensorSlot= 0; _counter++; } - DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); + DEBUG_SENSOR_LOG(PSTR("%s: active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); } else _counter++; - if (_counter>HM10.period) _counter = 0; + if (_counter>HM10.period) { + _counter = 0; + _lastDiscovery = 0; + } } +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + bool HM10Cmd(void) { char command[CMDSZ]; bool serviced = true; @@ -662,22 +1007,36 @@ bool HM10Cmd(void) { switch (command_code) { case CMND_HM10_PERIOD: if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; } + HM10.period = XdrvMailbox.payload; } else { - if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period; + XdrvMailbox.payload = HM10.period; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_AUTO: + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload>0) { + HM10.mode.autoScan = 1; + HM10.autoScanInterval = XdrvMailbox.payload; + } + else { + HM10.mode.autoScan = 0; + HM10.autoScanInterval = 0; + } + } + else { + XdrvMailbox.payload = HM10.autoScanInterval; } Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); break; case CMND_HM10_BAUD: if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_BAUD) { HM10.serialSpeed = XdrvMailbox.payload; HM10Serial->begin(HM10.serialSpeed); - } } else { - if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed; + XdrvMailbox.payload = HM10.serialSpeed; } Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); break; @@ -702,13 +1061,13 @@ bool HM10Cmd(void) { else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); break; case CMND_HM10_DISC_SCAN: - if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); } + HM10_Discovery_Scan(); Response_P(S_JSON_HM10_COMMAND, command, ""); break; default: - // else for Unknown command - serviced = false; - break; + // else for Unknown command + serviced = false; + break; } } else { return false; @@ -733,21 +1092,25 @@ void HM10Show(bool json) for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { char slave[33]; sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[33]; // all sensors have temperature + char temperature[FLOATSZ]; // all sensors have temperature dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); ResponseAppend_P(PSTR(",\"%s\":{"),slave); if(MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no temperature ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); } + else { + ResponseAppend_P(PSTR("}")); + continue; + } if (MIBLEsensors.at(i).type==FLORA){ - char lux[33]; - char moisture[33]; - char fertility[33]; + char lux[FLOATSZ]; + char moisture[FLOATSZ]; + char fertility[FLOATSZ]; dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no temperature + if(MIBLEsensors.at(i).lux!=0x0ffffff){ // this is the error code -> no temperature ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); } if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no moisture @@ -758,15 +1121,20 @@ void HM10Show(bool json) } } if (MIBLEsensors.at(i).type>FLORA){ - char humidity[33]; + char humidity[FLOATSZ]; dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); } - if(MIBLEsensors.at(i).bat!=0xff){ // this is the error code -> no battery - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + if(MIBLEsensors.at(i).hum!=-1.0f && MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no humidity nor temp + char dewpoint[FLOATSZ]; + dtostrfd(CalcTempHumToDew(MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum), Settings.flag2.temperature_resolution, dewpoint); + ResponseAppend_P(PSTR(",\"" D_JSON_DEWPOINT "\":%s"), dewpoint); } } + if(MIBLEsensors.at(i).bat!=0x00){ // this is the error code -> no battery + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } ResponseAppend_P(PSTR("}")); } #ifdef USE_WEBSERVER @@ -776,32 +1144,37 @@ void HM10Show(bool json) WSContentSend_PD(HTTP_HM10_HL); WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); if(MIBLEsensors.at(i).temp!=-1000.0f){ - char temperature[33]; + char temperature[FLOATSZ]; dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); } if (MIBLEsensors.at(i).type==FLORA){ - if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no valid value + if(MIBLEsensors.at(i).lux!=0x00ffffff){ // this is the error code -> no valid value WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); } if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no valid value WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); } if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no valid value - char fertility[33]; + char fertility[FLOATSZ]; dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); } } if (MIBLEsensors.at(i).type>FLORA){ // everything "above" Flora if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity - char humidity[33]; + char humidity[FLOATSZ]; dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); } - if(MIBLEsensors.at(i).bat!=0xff){ - WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + if(MIBLEsensors.at(i).hum!=-1.0f && MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no humidity nor temp + char dewpoint[FLOATSZ]; + dtostrfd(CalcTempHumToDew(MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum), Settings.flag2.temperature_resolution, dewpoint); + WSContentSend_PD(HTTP_SNS_DEW, kHM10SlaveType[MIBLEsensors.at(i).type-1], dewpoint, TempUnit()); } + } + if(MIBLEsensors.at(i).bat!=0x00){ + WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); } } #endif // USE_WEBSERVER @@ -847,4 +1220,4 @@ bool Xsns62(uint8_t function) } return result; } -#endif //USE_HM10 \ No newline at end of file +#endif //USE_HM10 From 211520b1c8a8211879221541934644af71751713 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Mar 2020 11:22:22 +0100 Subject: [PATCH 02/56] Bump version 8.2.0 --- README.md | 2 +- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 8 ++++++-- tasmota/tasmota_version.h | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2a32990ff..53f977ae2 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v8.1.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v8.2.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 05f63f01e..811941f43 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.11 +### Version 8.2.0 Elliot - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers to tasmota.bin - Change DHT driver (#7468, #7717) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 1c11c313a..02c344b58 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,11 @@ ## Unreleased (development) +## Released + +### 8.2.0 20200321 + +- Release + ### 8.1.0.11 20200313 - Change Zigbee simplification of devices probing, saving Flash and memory @@ -119,8 +125,6 @@ - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev - Add Zigbee attribute decoder for Xiaomi Aqara Cube -## Released - ### 8.1.0 20191225 - Release diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 636018ddc..0a3b9aa5e 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x0801000B; +const uint32_t VERSION = 0x08020000; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 0ec6f886893fa0ce133b1aa33fb9f0cfce276ec7 Mon Sep 17 00:00:00 2001 From: blakadder Date: Sat, 21 Mar 2020 14:57:30 +0100 Subject: [PATCH 03/56] Update MODULES.md module 54 changed to correct version, some minor edits --- MODULES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MODULES.md b/MODULES.md index b47769998..e16dec401 100644 --- a/MODULES.md +++ b/MODULES.md @@ -23,7 +23,7 @@ Module | Description 17 WiOn | WiOn Wifi Smart Socket 18 Generic | Any ESP8266/ESP8285 device like WeMos and NodeMCU 19 Sonoff Dev | Sonoff Dev Wifi Development Board -20 H801 | H801 Wifi RGBWW Led Controller +20 H801 | H801 Wifi 5 Channel LED Controller 21 Sonoff SC | Sonoff SC Wifi Environmental Monitor 22 Sonoff BN-SZ | Sonoff BN-SZ01 Wifi Ceiling Led (Retired) 23 Sonoff 4CH Pro | Sonoff 4CH Pro 4-gang Wifi Smart Switch @@ -57,7 +57,7 @@ Module | Description 51 OBI Socket | OBI Wifi Smart Socket 52 Teckin | Teckin SP22 Wifi Smart Switch with Energy Monitoring 53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring -54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led +54 TuyaMCU | Devices with an MCU using Tuya communication protocol for control 55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring 56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led 57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring @@ -65,7 +65,7 @@ Module | Description 59 Teckin US | Teckin SP20 and ZooZee SA102 Wifi Smart Switch with Energy Monitoring 60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays 61 OBI Socket 2 | OBI 2 Wifi Smart Socket -62 YTF IR Bridge | YTF Infra Red Wifi Bridge +62 YTF IR Bridge | YTF Universal IR Bridge 63 Digoo DG-SP202 | Digoo DG-SP202 Dual Wifi Smart Switch with Energy Monitoring 64 KA10 | Smanergy KA10 Wifi Smart Wall Switch with Energy Monitoring 65 Luminea ZX2820 | Luminea ZX2820 Wifi Smart Switch with Energy Monitoring From b6fc31ebb0d3dbf835d5aeb9bb5f1309f5727cab Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Mar 2020 15:46:28 +0100 Subject: [PATCH 04/56] Bump version 8.2.0.1 - Bump version 8.2.0.1 - Change HM-10 sensor type detection and add features (#7962) --- RELEASENOTES.md | 74 ++------------------------------------- tasmota/CHANGELOG.md | 4 +++ tasmota/tasmota_version.h | 2 +- 3 files changed, 7 insertions(+), 73 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 811941f43..eb9da8a74 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,76 +52,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.2.0 Elliot +### Version 8.2.0.1 -- Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers to tasmota.bin -- Change DHT driver (#7468, #7717) -- Change Lights: simplified gamma correction and 10 bits internal computation -- Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items -- Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` -- Change MQTT message size with additional 200 characters -- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" -- Change IRremoteESP8266 library updated to v2.7.4 -- Fix ``PowerDelta`` zero power detection (#7515) -- Fix ``White`` added to light status (#7142) -- Fix ``WakeUp `` ignores provided value (#7473) -- Fix ``RGBWWTable`` ignored (#7572) -- Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) -- Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging -- Fix Improved fade linearity with gamma correction -- Fix PWM flickering at low levels (#7415) -- Fix LCD line and column positioning (#7387) -- Fix Display handling of hexadecimal escape characters (#7387) -- Fix exception 9 restart on log message in Ticker interrupt service routines NTP, Wemos and Hue emulation (#7496) -- Fix Hass sensor discovery by Federico Leoni (#7582, #7548) -- Fix MaxPower functionality (#7647) -- Fix relation between Wifi RSSI and signal strength -- Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) -- Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 -- Add command ``SetOption84 0/1`` to send AWS IoT device shadow updates (alternative to retained) -- Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) -- Add command ``SetOption86 0/1`` for PWM dimmer to turn brightness LED's off 5 seconds after last change -- Add command ``SetOption87 0/1`` for PWM dimmer to turn red LED on when powered off -- Add command ``SetOption88 0/1`` for PWM dimmer to let buttons control remote devices -- Add command ``SetOption89 0/1`` for Zigbee distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) -- Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) -- Add commands ``SwitchMode 8`` ToggleMulti, ``SwitchMode 9`` FollowMulti and ``SwitchMode 10`` FollowMultiInverted (#7522) -- Add commands ``SwitchMode 11`` PushHoldMulti and ``SwitchMode 12`` PushHoldInverted (#7603) -- Add commands ``SwitchMode 13`` PushOn and ``SwitchMode 14`` PushOnInverted (#7912) -- Add command ``Buzzer -1`` for infinite mode and command ``Buzzer -2`` for following led mode (#7623) -- Add command ``HumOffset -10.0 .. 10.0`` to set global humidity sensor offset (#7934) -- Add support for ``AdcParam`` parameters to control ADC0 Current Transformer Apparent Power formula by Jodi Dillon (#7100) -- Add optional parameter ```` to command ``Scheme , `` to control initial start color -- Add web page sliders when ``SetOption37 128`` is active allowing control of white(s) -- Add SerialConfig to ``Status 1`` -- Add BootCount Reset Time as BCResetTime to ``Status 1`` -- Add WifiPower to ``Status 5`` -- Add most SetOptions as defines to my_user_config.h -- Add optional Wifi AccessPoint passphrase define WIFI_AP_PASSPHRASE in my_user_config.h (#7690) -- Add SoftwareSerial to CSE7766 driver allowing different GPIOs (#7563) -- Add rule trigger on one level deeper using syntax with two ``#`` like ``on zbreceived#vibration_sensor#aqaracubeside=0 do ...`` -- Add Zigbee attribute decoder for Xiaomi Aqara Cube -- Add ``ZbZNPReceived``and ``ZbZCLReceived`` being published to MQTT when ``SetOption66 1`` -- Add Zigbee enhanced commands decoding, added ``ZbPing`` -- Add Zigbee features and improvements -- Add Zigbee support for Hue emulation by Stefan Hadinger -- Add HAss Discovery support for Button and Switch triggers by Federico Leoni (#7901) -- Add Dew Point to Temperature and Humidity sensors -- Add optional support for Prometheus using file xsns_91_prometheus.ino (#7216) -- Add support for gzipped binaries -- Add support for Romanian language translations by Augustin Marti -- Add support for sensors DS18x20 and DHT family on Shelly 1 and Shelly 1PM using Shelly Add-On adapter (#7469) -- Add support to BMP driver to enter reset state (sleep enable) when deep sleep is used in Tasmota -- Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev -- Add support for NRF24L01 as BLE-bridge for Mijia Bluetooth sensors by Christian Baars (#7394) -- Add support for MI-BLE sensors using HM-10 Bluetooth 4.0 module by Christian Staars (#7683) -- Add support for FiF LE-01MR energy meter by saper-2 (#7584) -- Add support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) -- Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) -- Add support for La Crosse TX23 Anemometer by Norbert Richter (#3146, #7765) -- Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) -- Add support for UDP Group control without MQTT by Paul Diem (#7790) -- Add support for Jarolift rollers by Keeloq algorithm -- Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) -- Add support for HDC1080 Temperature and Humidity sensor by Luis Teixeira (#7888) -- Add support for ElectriQ iQ-wifiMOODL RGBW light by Ian King (#7947) +- Change HM-10 sensor type detection and add features (#7962) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 02c344b58..66f27a53e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.2.0.1 20200321 + +- Change HM-10 sensor type detection and add features (#7962) + ## Released ### 8.2.0 20200321 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 0a3b9aa5e..3bc994c67 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08020000; +const uint32_t VERSION = 0x08020001; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 5c0d78ac425b1fcac4a13359c14d33c7eba00e19 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 21 Mar 2020 15:57:59 +0100 Subject: [PATCH 05/56] Generate gzip binaries --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 6b9459388..9e0c28e9a 100755 --- a/platformio.ini +++ b/platformio.ini @@ -85,6 +85,7 @@ extra_scripts = ${scripts_defaults.extra_scripts} [scripts_defaults] extra_scripts = pio/strip-floats.py pio/name-firmware.py + pio/gzip-firmware.py [esp82xx_defaults] build_flags = -D NDEBUG From 2c8dd288e7e0cad622749b3999bd9ec4a906fc09 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 22 Mar 2020 16:11:01 +0100 Subject: [PATCH 06/56] Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_23_zigbee_1_headers.ino | 36 +++++++++++ tasmota/xdrv_23_zigbee_2_devices.ino | 95 +++++++++++++++++++++++++++- tasmota/xdrv_23_zigbee_9_impl.ino | 58 ++++++++++++++++- 5 files changed, 186 insertions(+), 5 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 66f27a53e..9851355a0 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.2.0.1 20200321 - Change HM-10 sensor type detection and add features (#7962) +- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` ## Released diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 12f3164c6..47afc7307 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -514,6 +514,7 @@ #define D_JSON_ZIGBEE_STATUS_MSG "StatusMessage" #define D_CMND_ZIGBEE_LIGHT "Light" #define D_JSON_ZIGBEE_LIGHT "Light" +#define D_CMND_ZIGBEE_RESTORE "Restore" // Commands xdrv_25_A4988_Stepper.ino #define D_CMND_MOTOR "MOTOR" diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 50e028dc1..051858697 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -43,6 +43,42 @@ JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { return *(JsonVariant*)nullptr; } +// get the result as a string (const char*) and nullptr if there is no field or the string is empty +const char * getCaseInsensitiveConstCharNull(const JsonObject &json, const char *needle) { + const JsonVariant &val = getCaseInsensitive(json, needle); + if (&val) { + const char *val_cs = val.as(); + if (strlen(val_cs)) { + return val_cs; + } + } + return nullptr; +} + +// Get an JSON attribute, with case insensitive key search starting with *needle +JsonVariant &startsWithCaseInsensitive(const JsonObject &json, const char *needle) { + // key can be in PROGMEM + if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { + return *(JsonVariant*)nullptr; + } + + String needle_s(needle); + needle_s.toLowerCase(); + + for (auto kv : json) { + String key_s(kv.key); + key_s.toLowerCase(); + JsonVariant &value = kv.value; + + if (key_s.startsWith(needle_s)) { + return value; + } + } + // if not found + return *(JsonVariant*)nullptr; +} + + uint32_t parseHex(const char **data, size_t max_len = 8) { uint32_t ret = 0; for (uint32_t i = 0; i < max_len; i++) { diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 0cbe9a507..7443b5457 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -105,9 +105,7 @@ public: // Add an endpoint to a device void addEndpoint(uint16_t shortaddr, uint8_t endpoint); - - // Add cluster - void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster); + void clearEndpoints(uint16_t shortaddr); void setManufId(uint16_t shortaddr, const char * str); void setModelId(uint16_t shortaddr, const char * str); @@ -121,6 +119,7 @@ public: // Dump json String dumpLightState(uint16_t shortaddr) const; String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; + int32_t deviceRestore(const JsonObject &json); // Hue support void setHueBulbtype(uint16_t shortaddr, int8_t bulbtype); @@ -450,6 +449,20 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { } } +// +// Clear all endpoints +// +void Z_Devices::clearEndpoints(uint16_t shortaddr) { + if (!shortaddr) { return; } + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + + for (uint32_t i = 0; i < endpoints_max; i++) { + device.endpoints[i] = 0; + // no dirty here because it doesn't make sense to store it, does it? + } +} + // // Add an endpoint to a shortaddr // @@ -994,6 +1007,9 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { if (device.modelId) { dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; } + if (-1 != device.bulbtype) { + dev[F(D_JSON_ZIGBEE_LIGHT)] = device.bulbtype; // sign extend, 0xFF changed as -1 + } if (device.manufacturerId) { dev[F("Manufacturer")] = device.manufacturerId; } @@ -1013,4 +1029,77 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { return payload; } +// Restore a single device configuration based on json export +// Input: json element as expported by `ZbStatus2`` +// Mandatory attribue: `Device` +// +// Returns: +// 0 : Ok +// <0 : Error +// +// Ex: {"Device":"0x5ADF","Name":"IKEA_Light","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]} +int32_t Z_Devices::deviceRestore(const JsonObject &json) { + + // params + uint16_t device = 0x0000; // 0x0000 is coordinator so considered invalid + uint64_t ieeeaddr = 0x0000000000000000LL; // 0 means unknown + const char * modelid = nullptr; + const char * manufid = nullptr; + const char * friendlyname = nullptr; + int8_t bulbtype = 0xFF; + size_t endpoints_len = 0; + + // read mandatory "Device" + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = strToUInt(val_device); + } else { + return -1; // missing "Device" attribute + } + + // read "IEEEAddr" 64 bits in format "0x0000000000000000" + const JsonVariant &val_ieeeaddr = getCaseInsensitive(json, PSTR("IEEEAddr")); + if (nullptr != &val_ieeeaddr) { + ieeeaddr = strtoull(val_ieeeaddr.as(), nullptr, 0); + } + + // read "Name" + friendlyname = getCaseInsensitiveConstCharNull(json, PSTR("Name")); + + // read "ModelId" + modelid = getCaseInsensitiveConstCharNull(json, PSTR("ModelId")); + + // read "Manufacturer" + manufid = getCaseInsensitiveConstCharNull(json, PSTR("Manufacturer")); + + // read "Light" + const JsonVariant &val_bulbtype = getCaseInsensitive(json, PSTR(D_JSON_ZIGBEE_LIGHT)); + if (nullptr != &val_bulbtype) { bulbtype = strToUInt(val_bulbtype);; } + + // update internal device information + updateDevice(device, ieeeaddr); + if (modelid) { setModelId(device, modelid); } + if (manufid) { setManufId(device, manufid); } + if (friendlyname) { setFriendlyName(device, friendlyname); } + if (&val_bulbtype) { setHueBulbtype(device, bulbtype); } + + // read "Endpoints" + const JsonVariant &val_endpoints = getCaseInsensitive(json, PSTR("Endpoints")); + if ((nullptr != &val_endpoints) && (val_endpoints.is())) { + const JsonArray &arr_ep = val_endpoints.as(); + endpoints_len = arr_ep.size(); + clearEndpoints(device); // clear even if array is empty + if (endpoints_len) { + for (auto ep_elt : arr_ep) { + uint8_t ep = strToUInt(ep_elt); + if (ep) { + addEndpoint(device, ep); + } + } + } + } + + return 0; +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index e90782a8c..674f8d655 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -35,7 +35,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" - D_CMND_ZIGBEE_LIGHT + D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE ; void (* const ZigbeeCommand[])(void) PROGMEM = { @@ -44,7 +44,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, &CmndZbPing, &CmndZbModelId, - &CmndZbLight, + &CmndZbLight, CmndZbRestore, }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -790,6 +790,60 @@ void CmndZbSave(void) { ResponseCmndDone(); } + +// Restore a device configuration previously exported via `ZbStatus2`` +// Format: +// Either the entire `ZbStatus3` export, or an array or just the device configuration. +// If array, if can contain multiple devices +// ZbRestore {"ZbStatus3":[{"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]}]} +// ZbRestore [{"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]}] +// ZbRestore {"Device":"0x5ADF","Name":"Petite_Lampe","IEEEAddr":"0x90FD9FFFFE03B051","ModelId":"TRADFRI bulb E27 WS opal 980lm","Manufacturer":"IKEA of Sweden","Endpoints":["0x01","0xF2"]} +void CmndZbRestore(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + DynamicJsonBuffer jsonBuf; + const JsonVariant json_parsed = jsonBuf.parse((const char*)XdrvMailbox.data); // const to force a copy of parameter + const JsonVariant * json = &json_parsed; // root of restore, to be changed if needed + bool success = false; + + // check if parsing succeeded + if (json_parsed.is()) { + success = json_parsed.as().success(); + } else if (json_parsed.is()) { + success = json_parsed.as().success(); + } + if (!success) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } + + // Check is root contains `ZbStatus` key, if so change the root + const JsonVariant * zbstatus = &startsWithCaseInsensitive(*json, PSTR("ZbStatus")); + if (nullptr != zbstatus) { + json = zbstatus; + } + + // check if the root is an array + if (json->is()) { + const JsonArray& arr = json->as(); + for (auto elt : arr) { + // call restore on each item + int32_t res = zigbee_devices.deviceRestore(elt); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } + } + } else if (json->is()) { + int32_t res = zigbee_devices.deviceRestore(*json); + if (res < 0) { + ResponseCmndChar_P(PSTR("Restore failed")); + return; + } + // call restore on a single object + } else { + ResponseCmndChar_P(PSTR("Missing parameters")); + return; + } + ResponseCmndDone(); +} + // Send an attribute read command to a device, specifying cluster and list of attributes void CmndZbRead(void) { // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} From 752fad8b19ec487229e4b67847a1dc453ed1c165 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Mar 2020 16:18:48 +0100 Subject: [PATCH 07/56] Disable reset pins from core Disable reset pins from core. Works with core below 2.5.0 and 2.6.3 + e64cb619f (or current STAGE). Should stop relay toggling at restart. --- tasmota/core_esp8266_wiring_digital.c | 2 ++ tasmota/support_legacy_cores.ino | 21 +++++++++++++++++++++ tasmota/tasmota_post.h | 1 + 3 files changed, 24 insertions(+) diff --git a/tasmota/core_esp8266_wiring_digital.c b/tasmota/core_esp8266_wiring_digital.c index f8d521748..4b9ab252b 100644 --- a/tasmota/core_esp8266_wiring_digital.c +++ b/tasmota/core_esp8266_wiring_digital.c @@ -196,6 +196,7 @@ void initPins(void) { U0IE = 0; U1IE = 0; +/* for (int i = 0; i <= 5; ++i) { pinMode(i, INPUT); } @@ -203,6 +204,7 @@ void initPins(void) { for (int i = 12; i <= 16; ++i) { pinMode(i, INPUT); } +*/ ETS_GPIO_INTR_ATTACH(interrupt_handler, &interrupt_reg); ETS_GPIO_INTR_ENABLE(); diff --git a/tasmota/support_legacy_cores.ino b/tasmota/support_legacy_cores.ino index f8c5b3060..0d429c75f 100644 --- a/tasmota/support_legacy_cores.ino +++ b/tasmota/support_legacy_cores.ino @@ -155,3 +155,24 @@ void* memmove_P(void *dest, const void *src, size_t n) } #endif // ARDUINO_ESP8266_RELEASE < 2_6_0 + + + +/*********************************************************************************************\ + * Core overrides +\*********************************************************************************************/ + +// Add below line to tasmota_post.h +// extern "C" void resetPins(); +void resetPins() +{ +/* + for (int i = 0; i <= 5; ++i) { + pinMode(i, INPUT); + } + // pins 6-11 are used for the SPI flash interface + for (int i = 12; i <= 16; ++i) { + pinMode(i, INPUT); + } +*/ +} diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index b9bc6a833..1bba02172 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -41,6 +41,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1); char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0'); extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end); +extern "C" void resetPins(); /*********************************************************************************************\ * Default global defines From 5471de6f1c96cc82209fa9316e98d0a0c091ee00 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Mar 2020 17:42:32 +0100 Subject: [PATCH 08/56] Change GPIO initialization solving possible Relay toggle on (OTA) restart Change GPIO initialization solving possible Relay toggle on (OTA) restart --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 1 + tasmota/support_tasmota.ino | 23 +++++++++++++++++++++++ tasmota/support_wifi.ino | 1 + 4 files changed, 27 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index eb9da8a74..6d46d8cda 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,3 +55,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.2.0.1 - Change HM-10 sensor type detection and add features (#7962) +- Change GPIO initialization solving possible Relay toggle on (OTA) restart +- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 9851355a0..bea282bd9 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.2.0.1 20200321 - Change HM-10 sensor type detection and add features (#7962) +- Change GPIO initialization solving possible Relay toggle on (OTA) restart - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` ## Released diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index d8ca2668c..1caaa2779 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1297,6 +1297,18 @@ void SerialInput(void) /********************************************************************************************/ +void ResetPwm(void) +{ + for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only + if (pin[GPIO_PWM1 +i] < 99) { + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); +// analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + } + } +} + +/********************************************************************************************/ + void GpioInit(void) { uint32_t mpin; @@ -1506,6 +1518,17 @@ void GpioInit(void) RotaryInit(); #endif + // Set any non-used GPIO to INPUT + for (uint32_t i = 0; i < sizeof(my_module.io); i++) { + mpin = ValidPin(i, my_module.io[i]); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("INI: gpio pin %d, mpin %d"), i, mpin); + if (((i < 6) || (i > 11)) && (0 == mpin)) { // Skip SPI flash interface + if (!((1 == i) || (3 == i))) { // Skip serial + pinMode(i, INPUT); + } + } + } + SetLedPower(Settings.ledstate &8); SetLedLink(Settings.ledstate &8); diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index f4e88a49d..efc0f9a26 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -694,6 +694,7 @@ void WifiShutdown(bool option = false) void EspRestart(void) { + ResetPwm(); WifiShutdown(true); CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 From bb73f6c412c5271703acb00384f9cee38f97715a Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sun, 22 Mar 2020 14:06:30 -0300 Subject: [PATCH 09/56] Update BUILDS.md --- BUILDS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILDS.md b/BUILDS.md index 0134d5fd7..04711b1c6 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -71,7 +71,7 @@ | | | | | | | | | | USE_ADC_VCC | x | x | - | - | - | - | - | | USE_COUNTER | - | - | x | x | x | x | x | -| USE_DS18x20 | - | - | x | x | x | - | x | +| USE_DS18x20 | - | - | x | x | x | x | x | | USE_DHT | - | - | x | x | x | x | x | | USE_MAX31855 | - | - | - | - | x | - | - | | USE_MAX31865 | - | - | - | - | - | - | - | From 55aad3dd372dc6284f9f360133bdd029a5cade51 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 22 Mar 2020 18:16:05 +0100 Subject: [PATCH 10/56] Use Arduino.git#e64cb619 for Platformio override. -> Use all latest development commit features --- platformio_override_sample.ini | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index fd5c86fdc..18766c735 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -79,9 +79,9 @@ extra_scripts = ${scripts_defaults.extra_scripts} ;platform_packages = ${core_2_6_3.platform_packages} ;build_flags = ${core_2_6_3.build_flags} -platform = ${tasmota_core_stage.platform} -platform_packages = ${tasmota_core_stage.platform_packages} -build_flags = ${tasmota_core_stage.build_flags} +platform = ${tasmota_feature_stage.platform} +platform_packages = ${tasmota_feature_stage.platform_packages} +build_flags = ${tasmota_feature_stage.build_flags} ;platform = ${core_stage.platform} ;platform_packages = ${core_stage.platform_packages} @@ -177,10 +177,10 @@ build_flags = ${esp82xx_defaults.build_flags} ; -fexceptions ; -lstdc++-exc -[tasmota_core_stage] -; *** Esp8266 core for Arduino version stable beta +[tasmota_feature_stage] +; *** Esp8266 core for Arduino version Tasmota feature stage platform = espressif8266@2.3.3 -platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#372a3ec297dfe8501bed1ec4552244695b5e8ced +platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#e64cb619f79a3c888dd56b957d8f48ce74f35735 build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC ; NONOSDK221 From 4749222d95168dd7b1b4e3e3bd52adcad04d69b2 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 22 Mar 2020 19:14:11 +0100 Subject: [PATCH 11/56] Fix Zigbee sending wrong Sat value with Hue emulation --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_3_hue.ino | 5 +++++ tasmota/xdrv_23_zigbee_9_impl.ino | 1 + 3 files changed, 7 insertions(+) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index bea282bd9..e0ebc4d4a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change HM-10 sensor type detection and add features (#7962) - Change GPIO initialization solving possible Relay toggle on (OTA) restart - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Fix Zigbee sending wrong Sat value with Hue emulation ## Released diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index baab88d8f..c19216842 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -130,6 +130,7 @@ void ZigbeeHuePower(uint16_t shortaddr, uint8_t power) { // Dimmer void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { + if (dimmer > 0xFE) { dimmer = 0xFE; } char param[8]; snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer); zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0008, 0x04, param); @@ -138,6 +139,7 @@ void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { // CT void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { + if (ct > 0xFEFF) { ct = 0xFEFF; } AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeHueCT 0x%04X - %d"), shortaddr, ct); char param[12]; snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8); @@ -149,6 +151,8 @@ void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { // XY void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { char param[16]; + if (x > 0xFEFF) { x = 0xFEFF; } + if (y > 0xFEFF) { y = 0xFEFF; } snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8); uint8_t colormode = 1; // "xy" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x07, param); @@ -159,6 +163,7 @@ void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { char param[16]; uint8_t hue8 = changeUIntScale(hue, 0, 360, 0, 254); + if (sat > 0xFE) { sat = 0xFE; } snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), hue8, sat); uint8_t colormode = 0; // "hs" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param); diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 674f8d655..f61979ea1 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -756,6 +756,7 @@ void CmndZbLight(void) { if (p) { int8_t bulbtype = strtol(p, nullptr, 10); + if (bulbtype > 5) { bulbtype = 5; } zigbee_devices.setHueBulbtype(shortaddr, bulbtype); } String dump = zigbee_devices.dumpLightState(shortaddr); From 12ec99ed070dcaa97f3e8e26e02ccde6a973e1ff Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 22 Mar 2020 21:35:44 +0100 Subject: [PATCH 12/56] web pagination, MJ_HT_V1 polling, some tweaks --- tasmota/xsns_62_MI_HM10.ino | 157 +++++++++++++++++++++++++++++------- 1 file changed, 127 insertions(+), 30 deletions(-) diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index 83252c4f6..7b72527b7 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -20,6 +20,8 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.3.0 20200322 added - multi page web view, command HM10PAGE, polling for MJ_HT_V1 + --- 0.9.2.0 20200317 added - MiBeacon-support, add Flora, MJ_HT_V1 and CGD1, add dew point, add AUTO(-scan), RULES-message --- @@ -42,11 +44,12 @@ TasmotaSerial *HM10Serial; #define HM10_MAX_TASK_NUMBER 12 uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; // first value: kind of task - second value: delay in x * 100ms -#define HM10_MAX_RX_BUF 160 +#define HM10_MAX_RX_BUF 64 struct { uint8_t current_task_delay; // number of 100ms-cycles uint8_t last_command; + uint16_t perPage = 4; uint16_t firmware; uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start uint32_t serialSpeed; @@ -71,24 +74,24 @@ struct { } HM10; #pragma pack(1) // byte-aligned structures to read the sensor data -struct { - uint16_t temp; - uint8_t hum; -} LYWSD0x_HT; -struct { - uint8_t spare; - uint16_t temp; - uint16_t hum; -} CGD1_HT; + struct { + uint16_t temp; + uint8_t hum; + } LYWSD0x_HT; + struct { + uint8_t spare; + uint16_t temp; + uint16_t hum; + } CGD1_HT; + struct { + uint16_t temp; + uint8_t spare; + uint32_t lux; + uint8_t moist; + uint16_t fert; + } Flora_TLMF; // temperature, lux, moisture, fertility -struct { - uint16_t temp; - uint8_t spare; - uint32_t lux; - uint8_t moist; - uint16_t fert; -} Flora_TLMF; // temeprature, lux, moisture, fertility struct mi_beacon_t{ uint16_t frame; @@ -118,7 +121,7 @@ struct mi_sensor_t{ uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 uint8_t serial[6]; uint8_t showedUp; - float temp; //Flora, MJ_HT_V1, LYWSD0x + float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx union { struct { float moisture; @@ -129,7 +132,7 @@ struct mi_sensor_t{ float hum; }; // MJ_HT_V1, LYWSD0x }; - uint8_t bat; + uint8_t bat; // all sensors }; std::vector MIBLEsensors; @@ -142,7 +145,7 @@ std::vector MIBLEsensors; const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; -const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto"; +const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto|Page"; #define FLORA 1 #define MJ_HT_V1 2 @@ -177,7 +180,8 @@ enum HM10_Commands { // commands useable in console or rules CMND_HM10_PERIOD, // set period like TELE-period in seconds between read-cycles CMND_HM10_BAUD, // serial speed of ESP8266 (<-> HM10), does not change baud rate of HM10 CMND_HM10_TIME, // set LYWSD02-Time from ESP8266-time - CMND_HM10_AUTO // do discovery scans permanently to receive MiBeacons in seconds between read-cycles + CMND_HM10_AUTO, // do discovery scans permanently to receive MiBeacons in seconds between read-cycles + CMND_HM10_PAGE // sensor entries per web page, which will be shown alternated }; enum HM10_awaitData: uint8_t { @@ -186,7 +190,8 @@ enum HM10_awaitData: uint8_t { TLMF = 2, bat = 3, tempHumCGD1 = 4, - discScan = 5 + discScan = 5, + tempHumMJ = 6 }; /*********************************************************************************************\ @@ -222,7 +227,10 @@ enum HM10_awaitData: uint8_t { #define TASK_HM10_UN_HT_CGD1 26 // unsubscribe service handle 4b #define TASK_HM10_READ_B_CGD1 27 // read service handle 11 #define TASK_HM10_DELAY_SUB_CGD1 28 // start reading from subscription delayed -#define TASK_HM10_STATUS_EVENT 29 // process status for RULES +#define TASK_HM10_READ_B_MJ 29 // read service handle 18 +#define TASK_HM10_SUB_HT_MJ 30 // subscribe to service handle 0f + +#define TASK_HM10_STATUS_EVENT 32 // process status for RULES #define TASK_HM10_DONE 99 // used, if there was a task in the slot or just to wait @@ -314,6 +322,14 @@ void HM10_Read_CGD1(void) { HM10_Launchtask(TASK_HM10_DISCONN,5,5); // disconnect } +void HM10_Read_MJ_HT_V1(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); // connect + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); // get OK+CONN + HM10_Launchtask(TASK_HM10_READ_B_MJ,2,20); // battery + HM10_Launchtask(TASK_HM10_SUB_HT_MJ,3,10); // temp hum + HM10_Launchtask(TASK_HM10_DISCONN,4,5); // disconnect + } + /** * @brief Return the slot number of a known sensor or return create new sensor slot * @@ -536,6 +552,7 @@ void HM10ParseResponse(char *buf, uint16_t bufsize) { void HM10readHT_LY(char *_buf){ DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b && _buf[2]==0x2b) return; // "OK+" if(_buf[0] != 0 && _buf[1] != 0){ memcpy(&LYWSD0x_HT,(void *)_buf,3); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 100: %u, H: %u"),D_CMND_HM10,LYWSD0x_HT.temp,LYWSD0x_HT.hum); @@ -559,7 +576,8 @@ void HM10readHT_LY(char *_buf){ } void HM10readHT_CGD1(char *_buf){ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b && _buf[2]==0x2b) return; // "OK+" if(_buf[0] == 0){ if(_buf[1]==0 && _buf[2]==0 && _buf[3]==0 && _buf[4]==0) return; memcpy(&CGD1_HT,(void *)_buf,5); @@ -583,8 +601,35 @@ void HM10readHT_CGD1(char *_buf){ } } +void HM10readHT_MJ_HT_V1(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]!=0x54 && _buf[1]!=0x3d) return; //"T=" + // T=22.7 H=42.2 (response as ASCII) + // 0123456789012 + uint32_t _temp = (atoi(_buf+2) * 10) + atoi(_buf+5); + uint32_t _hum = (atoi(_buf+9) * 10) + atoi(_buf+12); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, H * 10: %u"),D_CMND_HM10,_temp,_hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)_temp/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp=_tempFloat; + HM10.mode.awaiting = none; + HM10.current_task_delay = 0; + MIBLEsensors.at(_slot).showedUp=255; // this sensor is real + } + _tempFloat=(float)_hum/10.0f; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated")); + } +} + void HM10readTLMF(char *_buf){ DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b && _buf[2]==0x2b) return; // "OK+" if(_buf[0] != 0 || _buf[1] != 0){ // this will lose 0.0 degree, but it is not possible to measure a successful reading memcpy(&Flora_TLMF,(void *)_buf,10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: T * 10: %u, L: %u, M: %u, F: %u"),D_CMND_HM10,Flora_TLMF.temp,Flora_TLMF.lux,Flora_TLMF.moist,Flora_TLMF.fert); @@ -612,6 +657,7 @@ void HM10readTLMF(char *_buf){ bool HM10readBat(char *_buf){ DEBUG_SENSOR_LOG(PSTR("%s: raw data: %x%x%x%x%x%x%x"),D_CMND_HM10,_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0]==0x4f && _buf[1]==0x4b && _buf[2]==0x2b) return false; // "OK+" if(_buf[0] != 0){ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: Battery: %u"),D_CMND_HM10,_buf[0]); uint32_t _slot = HM10.state.sensor; @@ -662,12 +708,15 @@ bool HM10SerialHandleFeedback(){ // every 50 milliseconds break; case TLMF: if (HM10.mode.connected) HM10readTLMF(ret); - break; + break; case discScan: if(success) { HM10ParseResponse(ret,i); } break; + case tempHumMJ: + if (HM10.mode.connected) HM10readHT_MJ_HT_V1(ret); + break; case none: if(success) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: response: %s"),D_CMND_HM10, (char *)ret); @@ -875,6 +924,23 @@ void HM10_TaskEvery100ms(){ runningTaskLoop = false; HM10Serial->write("AT+SCAN9"); break; + case TASK_HM10_READ_B_MJ: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: read handle 0x18"),D_CMND_HM10); + HM10.current_task_delay = 2; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0018?"); + HM10.mode.awaiting = bat; + break; + case TASK_HM10_SUB_HT_MJ: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: subscribe to 0x0f"),D_CMND_HM10); + HM10.current_task_delay = 10; // set task delay + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaiting = none; + HM10Serial->write("AT+NOTIFY_ON000F"); + HM10.mode.awaiting = tempHumMJ; + break; case TASK_HM10_FEEDBACK: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: get response"),D_CMND_HM10); HM10SerialHandleFeedback(); @@ -965,14 +1031,17 @@ void HM10EverySecond(){ _nextSensorSlot++; HM10.mode.pending_task = 1; switch(MIBLEsensors.at(HM10.state.sensor).type){ - case LYWSD03MMC: - HM10_Read_LYWSD03(); + case FLORA: + HM10_Read_Flora(); + break; + case MJ_HT_V1: + HM10_Read_MJ_HT_V1(); break; case LYWSD02: HM10_Read_LYWSD02(); break; - case FLORA: - HM10_Read_Flora(); + case LYWSD03MMC: + HM10_Read_LYWSD03(); break; case CGD1: HM10_Read_CGD1(); @@ -1051,6 +1120,13 @@ bool HM10Cmd(void) { } Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); break; + case CMND_HM10_PAGE: + if (XdrvMailbox.data_len > 0) { + HM10.perPage = XdrvMailbox.payload; + } + else XdrvMailbox.payload = HM10.perPage; + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; case CMND_HM10_AT: HM10Serial->write("AT"); // without an argument this will disconnect if (strlen(XdrvMailbox.data)!=0) { @@ -1081,6 +1157,7 @@ bool HM10Cmd(void) { \*********************************************************************************************/ const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; +const char HTTP_HM10_PAGE[] PROGMEM = "{s}{m}%u%s / %u{e}"; const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; @@ -1139,8 +1216,21 @@ void HM10Show(bool json) } #ifdef USE_WEBSERVER } else { + static uint16_t _page = 0; + static uint16_t _counter = 0; + uint32_t i = _page * HM10.perPage; + uint32_t j = i + HM10.perPage; + if (j+1>MIBLEsensors.size()){ + j = MIBLEsensors.size(); + } + char stemp[5] ={0}; + if (MIBLEsensors.size()-(_page*HM10.perPage)>1 && HM10.perPage!=1) { + sprintf_P(stemp,"-%u",j); + } + WSContentSend_PD(HTTP_HM10, HM10.firmware); - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if (MIBLEsensors.size()>0) WSContentSend_PD(HTTP_HM10_PAGE, i+1,stemp,MIBLEsensors.size()); + for (i; i3) { + _page++; + _counter=0; + } + if(MIBLEsensors.size()%HM10.perPage==0 && _page==MIBLEsensors.size()/HM10.perPage) _page=0; + if(_page>MIBLEsensors.size()/HM10.perPage) _page=0; #endif // USE_WEBSERVER } } From 8ea179aed5b1dc4666d4164db0bfcba658c7cab4 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 22 Mar 2020 22:00:45 +0100 Subject: [PATCH 13/56] catch hm10page 0, hm10period 1 now triggers one read cycle --- tasmota/xsns_62_MI_HM10.ino | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index 7b72527b7..16ac499ae 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -1007,11 +1007,17 @@ void HM10StatusInfo(){ * */ -void HM10EverySecond(){ +void HM10EverySecond(bool restart){ static uint32_t _counter = 0; static uint32_t _nextSensorSlot = 0; static uint32_t _lastDiscovery = 0; + if(restart){ + _counter = 0; + _lastDiscovery = 0; + return; + } + if(HM10.firmware == 0) return; if(HM10.mode.pending_task == 1) return; if(MIBLEsensors.size()==0 && !HM10.mode.autoScan) return; @@ -1076,7 +1082,13 @@ bool HM10Cmd(void) { switch (command_code) { case CMND_HM10_PERIOD: if (XdrvMailbox.data_len > 0) { - HM10.period = XdrvMailbox.payload; + if (XdrvMailbox.payload==1) { + HM10EverySecond(true); + XdrvMailbox.payload = HM10.period; + } + else { + HM10.period = XdrvMailbox.payload; + } } else { XdrvMailbox.payload = HM10.period; @@ -1122,6 +1134,7 @@ bool HM10Cmd(void) { break; case CMND_HM10_PAGE: if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload == 0) XdrvMailbox.payload = HM10.perPage; // ignore 0 HM10.perPage = XdrvMailbox.payload; } else XdrvMailbox.payload = HM10.perPage; @@ -1300,7 +1313,7 @@ bool Xsns62(uint8_t function) } break; case FUNC_EVERY_SECOND: - HM10EverySecond(); + HM10EverySecond(false); break; case FUNC_COMMAND: result = HM10Cmd(); From f9d6ab1825d24e90177641bf90c5b5f9c527af0c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 23 Mar 2020 08:25:01 +0100 Subject: [PATCH 14/56] Better test for bulbtype --- tasmota/xdrv_23_zigbee_2_devices.ino | 2 +- tasmota/xdrv_23_zigbee_9_impl.ino | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 7443b5457..7b02e33ff 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -1007,7 +1007,7 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { if (device.modelId) { dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; } - if (-1 != device.bulbtype) { + if (device.bulbtype >= 0) { dev[F(D_JSON_ZIGBEE_LIGHT)] = device.bulbtype; // sign extend, 0xFF changed as -1 } if (device.manufacturerId) { diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index f61979ea1..12c9ff98f 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -756,7 +756,8 @@ void CmndZbLight(void) { if (p) { int8_t bulbtype = strtol(p, nullptr, 10); - if (bulbtype > 5) { bulbtype = 5; } + if (bulbtype > 5) { bulbtype = 5; } + if (bulbtype < -1) { bulbtype = -1; } zigbee_devices.setHueBulbtype(shortaddr, bulbtype); } String dump = zigbee_devices.dumpLightState(shortaddr); From 22eaa5795322c325a38ec22d6f77ba5b11e05645 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 23 Mar 2020 11:55:20 +0100 Subject: [PATCH 15/56] Remove gzip script... is already done in Platformio.ini --- platformio_override_sample.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 18766c735..deeafc3ee 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -54,7 +54,6 @@ build_flags = ${core_active.build_flags} upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} - pio/gzip-firmware.py pio/obj-dump.py ; *** Upload file to OTA server using SCP From 0a573bd0d68c4ef975f1802c13e29a849df9125c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Mar 2020 15:19:08 +0100 Subject: [PATCH 16/56] Update changelog and releasenotes --- RELEASENOTES.md | 5 +++-- tasmota/CHANGELOG.md | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6d46d8cda..1804b32c5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -21,7 +21,7 @@ While fallback or downgrading is common practice it was never supported due to S ## Supported Core versions -This release will be supported from ESP8266/Arduino library Core version **2.6.3 + 372a3ec** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. +This release will be supported from ESP8266/Arduino library Core version **2.6.3 + e64cb61** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. Although it might still compile on previous Core versions all support will be removed in the near future. @@ -35,7 +35,7 @@ For initial configuration this release supports Webserver based **WifiManager** ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.6.3 + 372a3ec**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.6.3 + e64cb61**. - **tasmota.bin** = The Tasmota version with most drivers. **RECOMMENDED RELEASE BINARY** - **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages. @@ -56,4 +56,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change HM-10 sensor type detection and add features (#7962) - Change GPIO initialization solving possible Relay toggle on (OTA) restart +- Fix Zigbee sending wrong Sat value with Hue emulation - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e0ebc4d4a..12f581ce8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,14 +4,14 @@ - Change HM-10 sensor type detection and add features (#7962) - Change GPIO initialization solving possible Relay toggle on (OTA) restart -- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Fix Zigbee sending wrong Sat value with Hue emulation +- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` ## Released ### 8.2.0 20200321 -- Release +- Release Elliot ### 8.1.0.11 20200313 @@ -134,7 +134,7 @@ ### 8.1.0 20191225 -- Release +- Release Doris ### 8.0.0.3 20191224 @@ -160,7 +160,7 @@ ### 7.2.0 20191221 -- Release +- Release Constance - Change basic version string to lite (#7291) - Fix Arduino IDE compile error (#7277) - Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281) @@ -243,7 +243,7 @@ ### 7.1.0 20191129 -- Release +- Release Doris ### 7.0.0.6 20191122 @@ -312,7 +312,7 @@ ### 6.7.1 20191026 -- Release +- Release Allison - Fix on energy monitoring devices using PowerDelta Exception0 with epc1:0x4000dce5 = Divide by zero (#6750) - Fix Script array bug (#6751) From 4a89c56182e31d349e6d5d18d10f624b121221af Mon Sep 17 00:00:00 2001 From: Staars Date: Mon, 23 Mar 2020 17:42:29 +0100 Subject: [PATCH 17/56] refactoring, more compact UI --- tasmota/xsns_62_MI_HM10.ino | 79 +++++++++++++++---------------------- 1 file changed, 32 insertions(+), 47 deletions(-) diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index 16ac499ae..581a32096 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -20,7 +20,8 @@ -------------------------------------------------------------------------------------------- Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- - 0.9.3.0 20200322 added - multi page web view, command HM10PAGE, polling for MJ_HT_V1 + 0.9.3.0 20200322 added - multi page web view, command HM10PAGE, polling for MJ_HT_V1, + more stable readings, internal refactoring --- 0.9.2.0 20200317 added - MiBeacon-support, add Flora, MJ_HT_V1 and CGD1, add dew point, add AUTO(-scan), RULES-message @@ -370,17 +371,17 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ memcpy(_newSensor.serial,_serial, sizeof(_serial)); _newSensor.type = _type; _newSensor.showedUp = 1; - _newSensor.temp =-1000.0f; + _newSensor.temp =NAN; _newSensor.bat=0x00; switch (_type) { case 1: - _newSensor.moisture =-1000.0f; - _newSensor.fertility =-1000.0f; + _newSensor.moisture =NAN; + _newSensor.fertility =NAN; _newSensor.lux = 0x00ffffff; break; case 2: case 3: case 4: case 5: case 6: - _newSensor.hum=-1.0f; + _newSensor.hum=NAN; break; default: break; @@ -1169,8 +1170,7 @@ bool HM10Cmd(void) { * Presentation \*********************************************************************************************/ -const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; -const char HTTP_HM10_PAGE[] PROGMEM = "{s}{m}%u%s / %u{e}"; +const char HTTP_HM10[] PROGMEM = "{s}HM10 V%u{m}%u%s / %u{e}"; const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; @@ -1182,18 +1182,17 @@ void HM10Show(bool json) for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { char slave[33]; sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[FLOATSZ]; // all sensors have temperature - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - ResponseAppend_P(PSTR(",\"%s\":{"),slave); - if(MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no temperature - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - else { - ResponseAppend_P(PSTR("}")); - continue; - } if (MIBLEsensors.at(i).type==FLORA){ + if(!isnan(MIBLEsensors.at(i).temp)){ // this is the error code -> no temperature + char temperature[FLOATSZ]; // all sensors have temperature + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + else { + ResponseAppend_P(PSTR("}")); + continue; + } char lux[FLOATSZ]; char moisture[FLOATSZ]; char fertility[FLOATSZ]; @@ -1203,23 +1202,16 @@ void HM10Show(bool json) if(MIBLEsensors.at(i).lux!=0x0ffffff){ // this is the error code -> no temperature ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no moisture + if(!isnan(MIBLEsensors.at(i).moisture)){ // this is the error code -> no moisture ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no fertility + if(!isnan(MIBLEsensors.at(i).fertility)){ // this is the error code -> no fertility ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); } } if (MIBLEsensors.at(i).type>FLORA){ - char humidity[FLOATSZ]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - } - if(MIBLEsensors.at(i).hum!=-1.0f && MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no humidity nor temp - char dewpoint[FLOATSZ]; - dtostrfd(CalcTempHumToDew(MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum), Settings.flag2.temperature_resolution, dewpoint); - ResponseAppend_P(PSTR(",\"" D_JSON_DEWPOINT "\":%s"), dewpoint); + if(!isnan(MIBLEsensors.at(i).hum) && !isnan(MIBLEsensors.at(i).temp)){ // this is the error code -> no humidity nor temp + ResponseAppendTHD(MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum); } } if(MIBLEsensors.at(i).bat!=0x00){ // this is the error code -> no battery @@ -1231,7 +1223,7 @@ void HM10Show(bool json) } else { static uint16_t _page = 0; static uint16_t _counter = 0; - uint32_t i = _page * HM10.perPage; + int32_t i = _page * HM10.perPage; uint32_t j = i + HM10.perPage; if (j+1>MIBLEsensors.size()){ j = MIBLEsensors.size(); @@ -1240,40 +1232,33 @@ void HM10Show(bool json) if (MIBLEsensors.size()-(_page*HM10.perPage)>1 && HM10.perPage!=1) { sprintf_P(stemp,"-%u",j); } + if (MIBLEsensors.size()==0) i=-1; // only for the GUI - WSContentSend_PD(HTTP_HM10, HM10.firmware); - if (MIBLEsensors.size()>0) WSContentSend_PD(HTTP_HM10_PAGE, i+1,stemp,MIBLEsensors.size()); + WSContentSend_PD(HTTP_HM10, HM10.firmware, i+1,stemp,MIBLEsensors.size()); for (i; i no valid value WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no valid value + if(!isnan(MIBLEsensors.at(i).moisture)){ // this is the error code -> no valid value WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no valid value + if(!isnan(MIBLEsensors.at(i).fertility)){ // this is the error code -> no valid value char fertility[FLOATSZ]; dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); } } if (MIBLEsensors.at(i).type>FLORA){ // everything "above" Flora - if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity - char humidity[FLOATSZ]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); - } - if(MIBLEsensors.at(i).hum!=-1.0f && MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no humidity nor temp - char dewpoint[FLOATSZ]; - dtostrfd(CalcTempHumToDew(MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum), Settings.flag2.temperature_resolution, dewpoint); - WSContentSend_PD(HTTP_SNS_DEW, kHM10SlaveType[MIBLEsensors.at(i).type-1], dewpoint, TempUnit()); + if(!isnan(MIBLEsensors.at(i).hum) && !isnan(MIBLEsensors.at(i).temp)){ + WSContentSend_THD(kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).temp, MIBLEsensors.at(i).hum); } } if(MIBLEsensors.at(i).bat!=0x00){ From ac4d4ac57114700e25cd54f103f777b2c6ca19b8 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 23 Mar 2020 22:46:26 +0100 Subject: [PATCH 18/56] Code optimization, cleaning and more error codes --- tasmota/support_static_buffer.ino | 4 +- tasmota/xdrv_23_zigbee_0_constants.ino | 106 +++------- tasmota/xdrv_23_zigbee_2_devices.ino | 93 ++++----- tasmota/xdrv_23_zigbee_6_commands.ino | 7 + tasmota/xdrv_23_zigbee_7_statemachine.ino | 88 ++++++++- tasmota/xdrv_23_zigbee_8_parsers.ino | 226 ++++++++++++--------- tasmota/xdrv_23_zigbee_9_impl.ino | 227 +++++++++++----------- 7 files changed, 406 insertions(+), 345 deletions(-) diff --git a/tasmota/support_static_buffer.ino b/tasmota/support_static_buffer.ino index bec831cc9..ea21b2805 100644 --- a/tasmota/support_static_buffer.ino +++ b/tasmota/support_static_buffer.ino @@ -112,7 +112,7 @@ public: } size_t addBuffer(const uint8_t *buf2, size_t len2) { - if (len() + len2 <= size()) { + if ((buf2) && (len() + len2 <= size())) { for (uint32_t i = 0; i < len2; i++) { _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); } @@ -121,7 +121,7 @@ public: } size_t addBuffer(const char *buf2, size_t len2) { - if (len() + len2 <= size()) { + if ((buf2) && (len() + len2 <= size())) { for (uint32_t i = 0; i < len2; i++) { _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); } diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index d97a26f9f..1a23c98dd 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -393,88 +393,36 @@ typedef struct Z_StatusLine { const char * status_msg; } Z_StatusLine; -ZF(SUCCESS) -ZF(FAILURE) -ZF(NOT_AUTHORIZED) -ZF(RESERVED_FIELD_NOT_ZERO) -ZF(MALFORMED_COMMAND) -ZF(UNSUP_CLUSTER_COMMAND) -ZF(UNSUP_GENERAL_COMMAND) -ZF(UNSUP_MANUF_CLUSTER_COMMAND) -ZF(UNSUP_MANUF_GENERAL_COMMAND) -ZF(INVALID_FIELD) -ZF(UNSUPPORTED_ATTRIBUTE) -ZF(INVALID_VALUE) -ZF(READ_ONLY) -ZF(INSUFFICIENT_SPACE) -ZF(DUPLICATE_EXISTS) -ZF(NOT_FOUND) -ZF(UNREPORTABLE_ATTRIBUTE) -ZF(INVALID_DATA_TYPE) -ZF(INVALID_SELECTOR) -ZF(WRITE_ONLY) -ZF(INCONSISTENT_STARTUP_STATE) -ZF(DEFINED_OUT_OF_BAND) -ZF(INCONSISTENT) -ZF(ACTION_DENIED) -ZF(TIMEOUT) -ZF(ABORT) -ZF(INVALID_IMAGE) -ZF(WAIT_FOR_DATA) -ZF(NO_IMAGE_AVAILABLE) -ZF(REQUIRE_MORE_IMAGE) -ZF(NOTIFICATION_PENDING) -ZF(HARDWARE_FAILURE) -ZF(SOFTWARE_FAILURE) -ZF(CALIBRATION_ERROR) -ZF(UNSUPPORTED_CLUSTER) +// Undocumented Zigbee ZCL code here: https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Zigbee-Error-Codes-in-the-Log +String getZigbeeStatusMessage(uint8_t status) { + static const char StatusMsg[] PROGMEM = "SUCCESS|FAILURE|NOT_AUTHORIZED|RESERVED_FIELD_NOT_ZERO|MALFORMED_COMMAND|UNSUP_CLUSTER_COMMAND|UNSUP_GENERAL_COMMAND" + "|UNSUP_MANUF_CLUSTER_COMMAND|UNSUP_MANUF_GENERAL_COMMAND|INVALID_FIELD|UNSUPPORTED_ATTRIBUTE|INVALID_VALE|READ_ONLY" + "|INSUFFICIENT_SPACE|DUPLICATE_EXISTS|NOT_FOUND|UNREPORTABLE_ATTRIBUTE|INVALID_DATA_TYPE|INVALID_SELECTOR|WRITE_ONLY" + "|INCONSISTENT_STARTUP_STATE|DEFINED_OUT_OF_BAND|INCONSISTENT|ACTION_DENIED|TIMEOUT|ABORT|INVALID_IMAGE|WAIT_FOR_DATA" + "|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER" + "|CHANNEL_ACCESS_FAILURE|NO_ACK|NO_APP_ACK|NO_ROUTE" + ; + static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x7E, 0x7F, 0x80, 0x81, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, + 0xE1, 0xE9, 0xA7, 0xD0}; -const Z_StatusLine Z_Status[] PROGMEM = { - 0x00, Z(SUCCESS), - 0x01, Z(FAILURE), - 0x7E, Z(NOT_AUTHORIZED), - 0x7F, Z(RESERVED_FIELD_NOT_ZERO), - 0x80, Z(MALFORMED_COMMAND), - 0x81, Z(UNSUP_CLUSTER_COMMAND), - 0x82, Z(UNSUP_GENERAL_COMMAND), - 0x83, Z(UNSUP_MANUF_CLUSTER_COMMAND), - 0x84, Z(UNSUP_MANUF_GENERAL_COMMAND), - 0x85, Z(INVALID_FIELD), - 0x86, Z(UNSUPPORTED_ATTRIBUTE), - 0x87, Z(INVALID_VALUE), - 0x88, Z(READ_ONLY), - 0x89, Z(INSUFFICIENT_SPACE), - 0x8A, Z(DUPLICATE_EXISTS), - 0x8B, Z(NOT_FOUND), - 0x8C, Z(UNREPORTABLE_ATTRIBUTE), - 0x8D, Z(INVALID_DATA_TYPE), - 0x8E, Z(INVALID_SELECTOR), - 0x8F, Z(WRITE_ONLY), - 0x90, Z(INCONSISTENT_STARTUP_STATE), - 0x91, Z(DEFINED_OUT_OF_BAND), - 0x92, Z(INCONSISTENT), - 0x93, Z(ACTION_DENIED), - 0x94, Z(TIMEOUT), - 0x95, Z(ABORT), - 0x96, Z(INVALID_IMAGE), - 0x97, Z(WAIT_FOR_DATA), - 0x98, Z(NO_IMAGE_AVAILABLE), - 0x99, Z(REQUIRE_MORE_IMAGE), - 0x9A, Z(NOTIFICATION_PENDING), - 0xC0, Z(HARDWARE_FAILURE), - 0xC1, Z(SOFTWARE_FAILURE), - 0xC2, Z(CALIBRATION_ERROR), - 0xC3, Z(UNSUPPORTED_CLUSTER), -}; - -const __FlashStringHelper* getZigbeeStatusMessage(uint8_t status) { - for (uint32_t i = 0; i < sizeof(Z_Status) / sizeof(Z_Status[0]); i++) { - const Z_StatusLine *statl = &Z_Status[i]; - if (statl->status == status) { - return (const __FlashStringHelper*) statl->status_msg; + char msg[32]; + int32_t idx = -1; + for (uint32_t i = 0; i < sizeof(StatusIdx); i++) { + if (status == pgm_read_byte(&StatusIdx[i])) { + idx = i; + break; } } - return F(""); + if (idx >= 0) { + GetTextIndexed(msg, sizeof(msg), idx, StatusMsg); + } else { + *msg = 0x00; // empty string + } + return String(msg); } #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 7b02e33ff..e4c6f6df0 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -26,7 +26,9 @@ #endif const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; // wait for x seconds -typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); +/*********************************************************************************************\ + * Structures for device configuration +\*********************************************************************************************/ const size_t endpoints_max = 8; // we limit to 8 endpoints @@ -53,6 +55,12 @@ typedef struct Z_Device { uint16_t x, y; // last color [x,y] } Z_Device; +/*********************************************************************************************\ + * Structures for deferred callbacks +\*********************************************************************************************/ + +typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value); + // Category for Deferred actions, this allows to selectively remove active deferred or update them typedef enum Z_Def_Category { Z_CAT_NONE = 0, // no category, it will happen anyways @@ -76,6 +84,10 @@ typedef struct Z_Deferred { Z_DeviceTimer func; // function to call when timer occurs } Z_Deferred; +/*********************************************************************************************\ + * Singleton for device configuration +\*********************************************************************************************/ + // All devices are stored in a Vector // Invariants: // - shortaddr is unique if not null @@ -190,13 +202,22 @@ private: // Create a new entry in the devices list - must be called if it is sure it does not already exist Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); void freeDeviceEntry(Z_Device *device); + + void setStringAttribute(char*& attr, const char * str); }; +/*********************************************************************************************\ + * Singleton variable +\*********************************************************************************************/ Z_Devices zigbee_devices = Z_Devices(); // Local coordinator information uint64_t localIEEEAddr = 0; +/*********************************************************************************************\ + * Implementation +\*********************************************************************************************/ + // https://thispointer.com/c-how-to-find-an-element-in-vector-and-get-its-index/ template < typename T> bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { @@ -493,73 +514,55 @@ uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const { return device.endpoints[0]; // returns 0x00 if no endpoint } -void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } // don't crash if not found +void Z_Devices::setStringAttribute(char*& attr, const char * str) { size_t str_len = str ? strlen(str) : 0; // len, handle both null ptr and zero length string - if ((!device.manufacturerId) && (0 == str_len)) { return; } // if both empty, don't do anything - if (device.manufacturerId) { + if ((nullptr == attr) && (0 == str_len)) { return; } // if both empty, don't do anything + if (attr) { // we already have a value - if (strcmp(device.manufacturerId, str) != 0) { + if (strcmp(attr, str) != 0) { // new value - free(device.manufacturerId); // free previous value - device.manufacturerId = nullptr; + free(attr); // free previous value + attr = nullptr; } else { return; // same value, don't change anything } } if (str_len) { - device.manufacturerId = (char*) malloc(str_len + 1); - strlcpy(device.manufacturerId, str, str_len + 1); + attr = (char*) malloc(str_len + 1); + strlcpy(attr, str, str_len + 1); } dirty(); } +// +// Sets the ManufId for a device. +// No action taken if the device does not exist. +// Inputs: +// - shortaddr: 16-bits short address of the device. No action taken if the device is unknown +// - str: string pointer, if nullptr it is considered as empty string +// Impact: +// - Any actual change in ManufId (i.e. setting a different value) triggers a `dirty()` and saving to Flash +// +void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + + setStringAttribute(device.manufacturerId, str); +} + void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found - size_t str_len = str ? strlen(str) : 0; // len, handle both null ptr and zero length string - if ((!device.modelId) && (0 == str_len)) { return; } // if both empty, don't do anything - if (device.modelId) { - // we already have a value - if (strcmp(device.modelId, str) != 0) { - // new value - free(device.modelId); // free previous value - device.modelId = nullptr; - } else { - return; // same value, don't change anything - } - } - if (str_len) { - device.modelId = (char*) malloc(str_len + 1); - strlcpy(device.modelId, str, str_len + 1); - } - dirty(); + setStringAttribute(device.modelId, str); } void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found - size_t str_len = str ? strlen(str) : 0; // len, handle both null ptr and zero length string - if ((!device.friendlyName) && (0 == str_len)) { return; } // if both empty, don't do anything - if (device.friendlyName) { - // we already have a value - if (strcmp(device.friendlyName, str) != 0) { - // new value - free(device.friendlyName); // free previous value - device.friendlyName = nullptr; - } else { - return; // same value, don't change anything - } - } - if (str_len) { - device.friendlyName = (char*) malloc(str_len + 1); - strlcpy(device.friendlyName, str, str_len + 1); - } - dirty(); + setStringAttribute(device.friendlyName, str); } const char * Z_Devices::getFriendlyName(uint16_t shortaddr) const { diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 8d756c95d..4788ddf67 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -19,6 +19,10 @@ #ifdef USE_ZIGBEE +/*********************************************************************************************\ + * ZCL Command Structures +\*********************************************************************************************/ + typedef struct Z_CommandConverter { const char * tasmota_cmd; uint16_t cluster; @@ -130,6 +134,9 @@ const Z_CommandConverter Z_Commands[] PROGMEM = { { Z(GetSceneMembership),0x0005, 0x06, 0x82,Z(xxyyzzzz) }, // specific }; +/*********************************************************************************************\ + * ZCL Read Light status based on cluster number +\*********************************************************************************************/ #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian // Below are the attributes we wand to read from each cluster diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 2073fb9eb..1c4f782b4 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -20,7 +20,7 @@ #ifdef USE_ZIGBEE // Status code used for ZigbeeStatus MQTT message -// Ex: {"ZigbeeStatus":{"Status": 3,"Message":"Configured, starting coordinator"}} +// Ex: {"ZbStatus":{"Status": 3,"Message":"Configured, starting coordinator"}} const uint8_t ZIGBEE_STATUS_OK = 0; // Zigbee started and working const uint8_t ZIGBEE_STATUS_BOOT = 1; // CC2530 booting const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; // Resetting CC2530 configuration @@ -33,7 +33,6 @@ const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address -//const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; // Request of device address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version @@ -50,9 +49,6 @@ typedef union Zigbee_Instruction { } i; const void *p; // pointer } Zigbee_Instruction; -// -// Zigbee_Instruction z1 = { .i = {1,2,3}}; -// Zigbee_Instruction z3 = { .p = nullptr }; typedef struct Zigbee_Instruction_Type { uint8_t instr; @@ -488,7 +484,6 @@ void ZigbeeStateMachine_Run(void) { if (zigbee.state_waiting) { // state machine is waiting for external event or timeout // checking if timeout expired if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { // if next_timeout == 0 then wait forever - //AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout occured pc=%d"), zigbee.pc); if (!zigbee.state_no_timeout) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout, goto label %d"), zigbee.on_timeout_goto); ZigbeeGotoLabel(zigbee.on_timeout_goto); @@ -505,7 +500,6 @@ void ZigbeeStateMachine_Run(void) { zigbee.recv_until = false; zigbee.state_no_timeout = false; // reset the no_timeout for next instruction -// AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeStateMachine_Run PC = %d, Mem1 = %d"), zigbee.pc, ESP.getFreeHeap()); if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); zigbee.pc = -1; @@ -516,7 +510,6 @@ void ZigbeeStateMachine_Run(void) { } // load current instruction details - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Executing instruction pc=%d"), zigbee.pc); const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; cur_instr = pgm_read_byte(&cur_instr_line->i.i); cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); @@ -553,7 +546,6 @@ void ZigbeeStateMachine_Run(void) { case ZGB_INSTR_WAIT_FOREVER: zigbee.next_timeout = 0; zigbee.state_waiting = true; - //zigbee.state_no_timeout = true; // do not generate a timeout error when waiting is done break; case ZGB_INSTR_STOP: zigbee.state_machine = false; @@ -617,4 +609,82 @@ void ZigbeeStateMachine_Run(void) { } } +// +// Process a bytes buffer and call any callback that matches the received message +// +int32_t ZigbeeProcessInput(class SBuffer &buf) { + if (!zigbee.state_machine) { return -1; } // if state machine is stopped, send 'ignore' message + + // apply the receive filter, acts as 'startsWith()' + bool recv_filter_match = true; + bool recv_prefix_match = false; // do the first 2 bytes match the response + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (zigbee.recv_filter_len >= 2) { + recv_prefix_match = false; + if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && + (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { + recv_prefix_match = true; + } + } + + for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { + if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { + recv_filter_match = false; + break; + } + } + } + + // if there is a recv_callback, call it now + int32_t res = -1; // default to ok + // res = 0 - proceed to next state + // res > 0 - proceed to the specified state + // res = -1 - silently ignore the message + // res <= -2 - move to error state + // pre-compute the suggested value + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (!recv_prefix_match) { + res = -1; // ignore + } else { // recv_prefix_match + if (recv_filter_match) { + res = 0; // ok + } else { + if (zigbee.recv_until) { + res = -1; // ignore until full match + } else { + res = -2; // error, because message is expected but wrong value + } + } + } + } else { // we don't have any filter, ignore message by default + res = -1; + } + + if (recv_prefix_match) { + if (zigbee.recv_func) { + res = (*zigbee.recv_func)(res, buf); + } + } + if (-1 == res) { + // if frame was ignored up to now + if (zigbee.recv_unexpected) { + res = (*zigbee.recv_unexpected)(res, buf); + } + } + + // change state accordingly + if (0 == res) { + // if ok, continue execution + zigbee.state_waiting = false; + } else if (res > 0) { + ZigbeeGotoLabel(res); // if >0 then go to specified label + } else if (-1 == res) { + // -1 means ignore message + // just do nothing + } else { + // any other negative value means error + ZigbeeGotoLabel(zigbee.on_error_goto); + } +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index e9c4b6368..b10c4be05 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -19,6 +19,13 @@ #ifdef USE_ZIGBEE +/*********************************************************************************************\ + * Parsers for incoming ZNP messages +\*********************************************************************************************/ + +// +// Handle a "Receive Device Info" incoming message +// int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { // Ex= 6700.00.6263151D004B1200.0000.07.09.02.83869991 // IEEE Adr (8 bytes) = 0x00124B001D156362 @@ -76,12 +83,12 @@ int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { } } -const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; - int32_t Z_Reboot(int32_t res, class SBuffer &buf) { // print information about the reboot of device // 4180.02.02.00.02.06.03 // + static const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; + uint8_t reason = buf.get8(2); uint8_t transport_rev = buf.get8(3); uint8_t product_id = buf.get8(4); @@ -140,6 +147,9 @@ int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { } } +// +// Helper function, checks if the incoming buffer matches the 2-bytes prefix, i.e. message type in PMEM +// bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && (pgm_read_byte(&match[1]) == buf.get8(1)) ) { @@ -149,6 +159,9 @@ bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { } } +// +// Handle Permit Join response +// int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { // we received a PermitJoin status change uint8_t duration = buf.get8(2); @@ -176,22 +189,6 @@ int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { return -1; } -// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address -void Z_SendIEEEAddrReq(uint16_t shortaddr) { - uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; - - ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); -} - -// Send ACTIVE_EP_REQ to collect active endpoints for this address -void Z_SendActiveEpReq(uint16_t shortaddr) { - uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); -} - const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { // Received ZDO_NODE_DESC_RSP @@ -226,6 +223,9 @@ int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { return -1; } +// +// Porcess Receive Active Endpoint +// int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { // Received ZDO_ACTIVE_EP_RSP Z_ShortAddress srcAddr = buf.get16(2); @@ -254,37 +254,14 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { return -1; } -void Z_SendAFInfoRequest(uint16_t shortaddr) { - uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01 - uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); - - SBuffer buf(100); - buf.add8(Z_SREQ | Z_AF); // 24 - buf.add8(AF_DATA_REQUEST); // 01 - buf.add16(shortaddr); - buf.add8(endpoint); // dest endpoint - buf.add8(0x01); // source endpoint - buf.add16(0x0000); - buf.add8(transacid); - buf.add8(0x30); // 30 options - buf.add8(0x1E); // 1E radius - - buf.add8(3 + 2*sizeof(uint16_t)); // Len = 0x07 - buf.add8(0x00); // Frame Control Field - buf.add8(transacid); // Transaction Sequence Number - buf.add8(ZCL_READ_ATTRIBUTES); // 00 Command - buf.add16(0x0004); // 0400 ManufacturerName - buf.add16(0x0005); // 0500 ModelIdentifier - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -} - +// +// Handle IEEEAddr incoming message +// int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { uint8_t status = buf.get8(2); Z_IEEEAddress ieeeAddr = buf.get64(3); Z_ShortAddress nwkAddr = buf.get16(11); - // uint8_t startIndex = buf.get8(13); + // uint8_t startIndex = buf.get8(13); // not used // uint8_t numAssocDev = buf.get8(14); if (0 == status) { // SUCCESS @@ -308,34 +285,6 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { } return -1; } - -int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { - Z_ShortAddress nwkAddr = buf.get16(2); - uint8_t status = buf.get8(4); - char status_message[32]; - - strncpy_P(status_message, (const char*) getZigbeeStatusMessage(status), sizeof(status_message)); - status_message[sizeof(status_message)-1] = 0; // truncate if needed, strlcpy is safer but strlcpy_P does not exist - - const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); - if (friendlyName) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" - ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"" - ",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), nwkAddr, friendlyName, status, status_message); - } else { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" - ",\"" D_JSON_ZIGBEE_STATUS "\":%d" - ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), nwkAddr, status, status_message); - } - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - return -1; -} - // // Report any AF_DATA_CONFIRM message // Ex: {"ZbConfirm":{"Endpoint":1,"Status":0,"StatusMessage":"SUCCESS"}} @@ -343,17 +292,13 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) { uint8_t status = buf.get8(2); uint8_t endpoint = buf.get8(3); - //uint8_t transId = buf.get8(4); - char status_message[32]; + //uint8_t transId = buf.get8(4); // unused if (status) { // only report errors - strncpy_P(status_message, (const char*) getZigbeeStatusMessage(status), sizeof(status_message)); - status_message[sizeof(status_message)-1] = 0; // truncate if needed, strlcpy is safer but strlcpy_P does not exist - Response_P(PSTR("{\"" D_JSON_ZIGBEE_CONFIRM "\":{\"" D_CMND_ZIGBEE_ENDPOINT "\":%d" ",\"" D_JSON_ZIGBEE_STATUS "\":%d" ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" - "}}"), endpoint, status, status_message); + "}}"), endpoint, status, getZigbeeStatusMessage(status).c_str()); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); XdrvRulesProcess(); } @@ -361,6 +306,10 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) { return -1; } +// +// Handle Receive End Device Announce incoming message +// Send back Active Ep Req message +// int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { Z_ShortAddress srcAddr = buf.get16(2); Z_ShortAddress nwkAddr = buf.get16(4); @@ -386,7 +335,10 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { return -1; } +// +// Handle Receive TC Dev Ind incoming message // 45CA +// int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { Z_ShortAddress srcAddr = buf.get16(2); Z_IEEEAddress ieeeAddr = buf.get64(4); @@ -404,15 +356,82 @@ int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); XdrvRulesProcess(); - //Z_SendActiveEpReq(srcAddr); return -1; } +// +// Handle Bind Rsp incoming message +// +int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, friendlyName, status, getZigbeeStatusMessage(status).c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, status, getZigbeeStatusMessage(status).c_str()); + } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} + +/*********************************************************************************************\ + * Send specific ZNP messages +\*********************************************************************************************/ + +// +// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address +// +void Z_SendIEEEAddrReq(uint16_t shortaddr) { + uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + + ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); +} + +// +// Send ACTIVE_EP_REQ to collect active endpoints for this address +// +void Z_SendActiveEpReq(uint16_t shortaddr) { + uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); +} + +// +// Send AF Info Request +// +void Z_SendAFInfoRequest(uint16_t shortaddr) { + uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + if (0x00 == endpoint) { endpoint = 0x01; } // if we don't know the endpoint, try 0x01 + uint8_t transacid = zigbee_devices.getNextSeqNumber(shortaddr); + + uint8_t AFInfoReq[] = { Z_SREQ | Z_AF, AF_DATA_REQUEST, Z_B0(shortaddr), Z_B1(shortaddr), endpoint, + 0x01, 0x00, 0x00, transacid, 0x30, 0x1E, 3 + 2*sizeof(uint16_t), + 0x00, transacid, ZCL_READ_ATTRIBUTES, 0x04, 0x00, 0x05, 0x00 + }; + ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq)); +} + + +/*********************************************************************************************\ + * Callbacks +\*********************************************************************************************/ + + // Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds. // Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false -const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s - void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, const JsonObject *json) { + static const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s // Read OCCUPANCY value if any const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); if (nullptr != &val_endpoint) { @@ -436,6 +455,10 @@ int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t groupaddr, uint16_t clu return 1; } +/*********************************************************************************************\ + * Global dispatcher for incoming messages +\*********************************************************************************************/ + int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { uint16_t groupid = buf.get16(2); uint16_t clusterid = buf.get16(4); @@ -506,22 +529,24 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { return -1; } +// Structure for the Dispatcher callbacks table typedef struct Z_Dispatcher { const uint8_t* match; ZB_RecvMsgFunc func; } Z_Dispatcher; -// Filters for ZCL frames -ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480 -ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 -ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1 -ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA -ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB -ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 -ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 -ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 -ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 +// Ffilters based on ZNP frames +ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480 +ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 +ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1 +ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA +ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB +ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 +ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 +ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 +ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 +// Dispatcher callbacks table const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_AF_DATA_CONFIRM, &Z_DataConfirm }, { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, @@ -534,6 +559,10 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, }; +/*********************************************************************************************\ + * Default resolver +\*********************************************************************************************/ + int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { // Default message handler for new messages if (zigbee.init_phase) { @@ -549,12 +578,22 @@ int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { } } +/*********************************************************************************************\ + * Functions called by State Machine +\*********************************************************************************************/ + +// +// Callback for loading Zigbee configuration from Flash, called by the state machine +// int32_t Z_Load_Devices(uint8_t value) { // try to hidrate from known devices loadZigbeeDevices(); return 0; // continue } +// +// Send messages to query the state of each Hue emulated light +// int32_t Z_Query_Bulbs(uint8_t value) { // Scan all devices and send deferred requests to know the state of bulbs uint32_t wait_ms = 1000; // start with 1.0 s delay @@ -588,6 +627,9 @@ int32_t Z_Query_Bulbs(uint8_t value) { return 0; // continue } +// +// Zigbee initialization is complete, let the party begin +// int32_t Z_State_Ready(uint8_t value) { zigbee.init_phase = false; // initialization phase complete return 0; // continue diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 12c9ff98f..49f89c9c7 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -47,85 +47,10 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbLight, CmndZbRestore, }; -int32_t ZigbeeProcessInput(class SBuffer &buf) { - if (!zigbee.state_machine) { return -1; } // if state machine is stopped, send 'ignore' message - - // apply the receive filter, acts as 'startsWith()' - bool recv_filter_match = true; - bool recv_prefix_match = false; // do the first 2 bytes match the response - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (zigbee.recv_filter_len >= 2) { - recv_prefix_match = false; - if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && - (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { - recv_prefix_match = true; - } - } - - for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { - if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { - recv_filter_match = false; - break; - } - } - - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: recv_prefix_match = %d, recv_filter_match = %d"), recv_prefix_match, recv_filter_match); - } - - // if there is a recv_callback, call it now - int32_t res = -1; // default to ok - // res = 0 - proceed to next state - // res > 0 - proceed to the specified state - // res = -1 - silently ignore the message - // res <= -2 - move to error state - // pre-compute the suggested value - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (!recv_prefix_match) { - res = -1; // ignore - } else { // recv_prefix_match - if (recv_filter_match) { - res = 0; // ok - } else { - if (zigbee.recv_until) { - res = -1; // ignore until full match - } else { - res = -2; // error, because message is expected but wrong value - } - } - } - } else { // we don't have any filter, ignore message by default - res = -1; - } - - if (recv_prefix_match) { - if (zigbee.recv_func) { - res = (*zigbee.recv_func)(res, buf); - } - } - if (-1 == res) { - // if frame was ignored up to now - if (zigbee.recv_unexpected) { - res = (*zigbee.recv_unexpected)(res, buf); - } - } - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); - - // change state accordingly - if (0 == res) { - // if ok, continue execution - zigbee.state_waiting = false; - } else if (res > 0) { - ZigbeeGotoLabel(res); // if >0 then go to specified label - } else if (-1 == res) { - // -1 means ignore message - // just do nothing - } else { - // any other negative value means error - ZigbeeGotoLabel(zigbee.on_error_goto); - } -} - -void ZigbeeInput(void) +// +// Called at event loop, checks for incoming data from the CC2530 +// +void ZigbeeInputLoop(void) { static uint32_t zigbee_polling_window = 0; static uint8_t fcs = ZIGBEE_SOF; @@ -217,6 +142,7 @@ void ZigbeeInput(void) /********************************************************************************************/ +// Initialize internal structures void ZigbeeInit(void) { // AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInit Mem1 = %d"), ESP.getFreeHeap()); @@ -260,10 +186,10 @@ uint32_t strToUInt(const JsonVariant &val) { return 0; // couldn't parse anything } +// Do a factory reset of the CC2530 const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x01 /* STARTOPT_CLEAR_CONFIG */}; //"2605030101"; // Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 len, 0x01 STARTOPT_CLEAR_CONFIG -// Do a factory reset of the CC2530 void CmndZbReset(void) { if (ZigbeeSerial) { switch (XdrvMailbox.payload) { @@ -279,6 +205,10 @@ void CmndZbReset(void) { } } +// +// Same code for `ZbZNPSend` and `ZbZNPReceive` +// building the complete message (intro, length) +// void CmndZbZNPSendOrReceive(bool send) { if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { @@ -298,8 +228,10 @@ void CmndZbZNPSendOrReceive(bool send) codes += 2; } if (send) { + // Command was `ZbZNPSend` ZigbeeZNPSend(buf.getBuffer(), buf.len()); } else { + // Command was `ZbZNPReceive` ZigbeeProcessInput(buf); } } @@ -347,6 +279,21 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { ToHex_P(msg, len, hex_char, sizeof(hex_char))); } +// +// Internal function, send the low-level frame +// Input: +// - shortaddr: 16-bits short address, or 0x0000 if group address +// - groupaddr: 16-bits group address, or 0x0000 if unicast using shortaddr +// - clusterIf: 16-bits cluster number +// - endpoint: 8-bits target endpoint (source is always 0x01), unused for group addresses. Should not be 0x00 except when sending to group address. +// - cmdId: 8-bits ZCL command number +// - clusterSpecific: boolean, is the message general cluster or cluster specific, used to create the FC byte of ZCL +// - msg: pointer to byte array, payload of ZCL message (len is following), ignored if nullptr +// - len: length of the 'msg' payload +// - needResponse: boolean, true = we ask the target to respond, false = the target should not respond +// - transacId: 8-bits, transation id of message (should be incremented at each message), used both for Zigbee message number and ZCL message number +// Returns: None +// void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { SBuffer buf(32+len); @@ -379,7 +326,22 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI ZigbeeZNPSend(buf.getBuffer(), buf.len()); } -// Send a command specified as an HEX string for the workload +/********************************************************************************************/ +// +// High-level function +// Send a command specified as an HEX string for the workload. +// The target endpoint is computed if zero, i.e. sent to the first known endpoint of the device. +// If cluster-specific, a timer may be set calling `zigbeeSetCommandTimer()`, for ex to coalesce attributes or Aqara presence sensor +// +// Inputs: +// - shortaddr: 16-bits short address, or 0x0000 if group address +// - groupaddr: 16-bits group address, or 0x0000 if unicast using shortaddr +// - endpoint: 8-bits target endpoint (source is always 0x01), if 0x00, it will be guessed from ZbStatus information (basically the first endpoint of the device) +// - clusterSpecific: boolean, is the message general cluster or cluster specific, used to create the FC byte of ZCL +// - clusterIf: 16-bits cluster number +// - param: pointer to HEX string for payload, should not be nullptr +// Returns: None +// void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t cluster, uint8_t cmd, const char *param) { size_t size = param ? strlen(param) : 0; @@ -395,15 +357,15 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, if ((0 == endpoint) && (shortaddr)) { // endpoint is not specified, let's try to find it from shortAddr, unless it's a group address endpoint = zigbee_devices.findFirstEndpoint(shortaddr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: shortaddr 0x%04X, groupaddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), shortaddr, groupaddr, cluster, endpoint, cmd, param); - if ((0 == endpoint) && (shortaddr)) { + if ((0 == endpoint) && (shortaddr)) { // endpoint null is ok for group address AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); return; - } // endpoint null is ok for group address + } // everything is good, we can send the command ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr)); @@ -413,21 +375,24 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, } } +// +// Command `ZbSend` +// void CmndZbSend(void) { - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":1} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"3"} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"0xFF"} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":null} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":false} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":true} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"true"} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"ShutterClose":null} } - // ZigbeeSend { "devicse":"0x1234", "endpoint":"0x03", "send":{"Power":1} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"1,2"} } - // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"0x1122,0xFFEE"} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":1} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"3"} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"0xFF"} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":null} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":false} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":true} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"true"} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"ShutterClose":null} } + // ZbSend { "devicse":"0x1234", "endpoint":"0x03", "send":{"Power":1} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"1,2"} } + // ZbSend { "device":"0x1234", "endpoint":"0x03", "send":{"Color":"0x1122,0xFFEE"} } if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + const JsonObject &json = jsonBuf.parseObject((const char*) XdrvMailbox.data); if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } // params @@ -463,16 +428,16 @@ void CmndZbSend(void) { // If String, it's a low level command if (val_cmd.is()) { // we have a high-level command - JsonObject &cmd_obj = val_cmd.as(); + const JsonObject &cmd_obj = val_cmd.as(); int32_t cmd_size = cmd_obj.size(); if (cmd_size > 1) { Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); return; } else if (1 == cmd_size) { // We have exactly 1 command, parse it - JsonObject::iterator it = cmd_obj.begin(); // just get the first key/value + JsonObject::const_iterator it = cmd_obj.begin(); // just get the first key/value String key = it->key; - JsonVariant& value = it->value; + const JsonVariant& value = it->value; uint32_t x = 0, y = 0, z = 0; uint16_t cmd_var; @@ -526,7 +491,7 @@ void CmndZbSend(void) { } else { // we have zero command, pass through until last error for missing command } - } else if (val_cmd.is()) { + } else if (val_cmd.is()) { // low-level command cmd_str = val_cmd.as(); // Now parse the string to extract cluster, command, and payload @@ -564,16 +529,18 @@ void CmndZbSend(void) { Response_P(PSTR("Missing zigbee 'Send'")); return; } - } +// +// Command `ZbBind` +// void CmndZbBind(void) { - // ZbBind { "device":"0x1234", "endpoint":1, "cluster":6 } + // ZbBind {"Device":"", "Endpoint":, "Cluster":, "ToDevice":"", "ToEndpoint":, "ToGroup": } // local endpoint is always 1, IEEE addresses are calculated if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + const JsonObject &json = jsonBuf.parseObject((const char*) XdrvMailbox.data); if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } // params @@ -658,6 +625,9 @@ void CmndZbProbe(void) { CmndZbProbeOrPing(true); } +// +// Common code for `ZbProbe` and `ZbPing` +// void CmndZbProbeOrPing(boolean probe) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); @@ -677,12 +647,15 @@ void CmndZbPing(void) { CmndZbProbeOrPing(false); } +// +// Command `ZbName` // Specify, read or erase a Friendly Name +// void CmndZbName(void) { // Syntax is: - // ZigbeeName , - assign a friendly name - // ZigbeeName - display the current friendly name - // ZigbeeName , - remove friendly name + // ZbName , - assign a friendly name + // ZbName - display the current friendly name + // ZbName , - remove friendly name // // Where can be: short_addr, long_addr, device_index, friendly_name @@ -706,12 +679,15 @@ void CmndZbName(void) { } } +// +// Command `ZbName` // Specify, read or erase a ModelId, only for debug purposes +// void CmndZbModelId(void) { // Syntax is: - // ZigbeeName , - assign a friendly name - // ZigbeeName - display the current friendly name - // ZigbeeName , - remove friendly name + // ZbName , - assign a friendly name + // ZbName - display the current friendly name + // ZbName , - remove friendly name // // Where can be: short_addr, long_addr, device_index, friendly_name @@ -735,6 +711,8 @@ void CmndZbModelId(void) { } } +// +// Command `ZbLight` // Specify, read or erase a Light type for Hue/Alexa integration void CmndZbLight(void) { // Syntax is: @@ -768,7 +746,10 @@ void CmndZbLight(void) { ResponseCmndDone(); } +// +// Command `ZbForget` // Remove an old Zigbee device from the list of known devices, use ZigbeeStatus to know all registered devices +// void CmndZbForget(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); @@ -783,12 +764,13 @@ void CmndZbForget(void) { } } +// +// Command `ZbSave` // Save Zigbee information to flash +// void CmndZbSave(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } - saveZigbeeDevices(); - ResponseCmndDone(); } @@ -803,7 +785,7 @@ void CmndZbSave(void) { void CmndZbRestore(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } DynamicJsonBuffer jsonBuf; - const JsonVariant json_parsed = jsonBuf.parse((const char*)XdrvMailbox.data); // const to force a copy of parameter + const JsonVariant json_parsed = jsonBuf.parse((const char*) XdrvMailbox.data); // const to force a copy of parameter const JsonVariant * json = &json_parsed; // root of restore, to be changed if needed bool success = false; @@ -846,14 +828,17 @@ void CmndZbRestore(void) { ResponseCmndDone(); } +// +// Command `ZbRead` // Send an attribute read command to a device, specifying cluster and list of attributes +// void CmndZbRead(void) { - // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} - // ZigbeeRead {"Device":"0xF289","Cluster":"0x0000","Endpoint":"0x0003","Attr":"0x0005"} - // ZigbeeRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":[5,6,7,4]} + // ZbRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":5} + // ZbRead {"Device":"0xF289","Cluster":"0x0000","Endpoint":"0x0003","Attr":"0x0005"} + // ZbRead {"Device":"0xF289","Cluster":0,"Endpoint":3,"Attr":[5,6,7,4]} if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + JsonObject &json = jsonBuf.parseObject((const char*) XdrvMailbox.data); if (!json.success()) { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); return; } // params @@ -884,7 +869,7 @@ void CmndZbRead(void) { if (nullptr != &val_attr) { uint16_t val = strToUInt(val_attr); if (val_attr.is()) { - JsonArray& attr_arr = val_attr; + const JsonArray& attr_arr = val_attr.as(); attrs_len = attr_arr.size() * 2; attrs = new uint8_t[attrs_len]; @@ -920,7 +905,10 @@ void CmndZbRead(void) { if (attrs) { delete[] attrs; } } +// +// Command `ZbPermitJoin` // Allow or Deny pairing of new Zigbee devices +// void CmndZbPermitJoin(void) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } uint32_t payload = XdrvMailbox.payload; @@ -946,6 +934,9 @@ void CmndZbPermitJoin(void) { ResponseCmndDone(); } +// +// Command `ZbStatus` +// void CmndZbStatus(void) { if (ZigbeeSerial) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } @@ -976,7 +967,7 @@ bool Xdrv23(uint8_t function) } break; case FUNC_LOOP: - if (ZigbeeSerial) { ZigbeeInput(); } + if (ZigbeeSerial) { ZigbeeInputLoop(); } if (zigbee.state_machine) { ZigbeeStateMachine_Run(); } From aede481b6129534be4636d6d13ad976274b7fb7a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Mar 2020 11:29:46 +0100 Subject: [PATCH 19/56] Move not used GPIO init up in chain --- tasmota/support_tasmota.ino | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 1caaa2779..3c4239359 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1433,6 +1433,18 @@ void GpioInit(void) soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); #endif // USE_SPI + // Set any non-used GPIO to INPUT - Related to resetPins() in support_legacy_cores.ino + // Doing it here solves relay toggles at restart. + for (uint32_t i = 0; i < sizeof(my_module.io); i++) { + mpin = ValidPin(i, my_module.io[i]); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("INI: gpio pin %d, mpin %d"), i, mpin); + if (((i < 6) || (i > 11)) && (0 == mpin)) { // Skip SPI flash interface + if (!((1 == i) || (3 == i))) { // Skip serial + pinMode(i, INPUT); + } + } + } + #ifdef USE_I2C i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); if (i2c_flg) { @@ -1518,17 +1530,6 @@ void GpioInit(void) RotaryInit(); #endif - // Set any non-used GPIO to INPUT - for (uint32_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidPin(i, my_module.io[i]); -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("INI: gpio pin %d, mpin %d"), i, mpin); - if (((i < 6) || (i > 11)) && (0 == mpin)) { // Skip SPI flash interface - if (!((1 == i) || (3 == i))) { // Skip serial - pinMode(i, INPUT); - } - } - } - SetLedPower(Settings.ledstate &8); SetLedLink(Settings.ledstate &8); From 2165a783741c0aed165542a599709b2a5d1d0141 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Mar 2020 14:03:51 +0100 Subject: [PATCH 20/56] Use latest Platformio chain 2.4.0 --- platformio_override_sample.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index deeafc3ee..f8ff1af64 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -134,7 +134,7 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_6_3] ; *** Esp8266 core for Arduino version 2.6.3 -platform = espressif8266@2.3.3 +platform = espressif8266@2.4.0 platform_packages = build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC @@ -178,7 +178,7 @@ build_flags = ${esp82xx_defaults.build_flags} [tasmota_feature_stage] ; *** Esp8266 core for Arduino version Tasmota feature stage -platform = espressif8266@2.3.3 +platform = espressif8266@2.4.0 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#e64cb619f79a3c888dd56b957d8f48ce74f35735 build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC @@ -222,7 +222,7 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = espressif8266@2.3.3 +platform = espressif8266@2.4.0 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC From 308b145514012d9b100ce6ed4b87bc37c9fb85ae Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 25 Mar 2020 14:05:31 +0100 Subject: [PATCH 21/56] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 9e0c28e9a..2c78a4583 100755 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,7 @@ build_flags = ${tasmota_core_stage.build_flags} [tasmota_core_stage] ; *** Esp8266 core for Arduino version stable beta -platform = espressif8266@2.3.3 +platform = espressif8266@2.4.0 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#372a3ec297dfe8501bed1ec4552244695b5e8ced build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC From bec81f50895af870369648d22c9e3a3393b13a35 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 25 Mar 2020 20:36:57 +0100 Subject: [PATCH 22/56] Zigbee fix incorrect Hue value --- tasmota/xdrv_20_hue.ino | 8 ++++---- tasmota/xdrv_23_zigbee_3_hue.ino | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 95aef13e4..c816eed02 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -298,7 +298,7 @@ void HueLightStatus1(uint8_t device, String *response) prev_x_str[0] = prev_y_str[0] = 0; } - hue = changeUIntScale(hue, 0, 359, 0, 65535); + hue = changeUIntScale(hue, 0, 360, 0, 65535); if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { hue = prev_hue; } else { // if hue was changed outside of Alexa, reset xy @@ -598,7 +598,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { uint8_t rr,gg,bb; LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); // calculate back prev_hue + prev_hue = changeUIntScale(hue, 0, 360, 0, 65535); // calculate back prev_hue prev_sat = (sat > 254 ? 254 : sat); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, "XY RGB (%d %d %d) HS (%d %d)", rr,gg,bb,hue,sat); if (resp) { response += ","; } @@ -619,8 +619,8 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { device_id, "hue", hue); response += buf; if (LST_RGB <= Light.subtype) { - // change range from 0..65535 to 0..359 - hue = changeUIntScale(hue, 0, 65535, 0, 359); + // change range from 0..65535 to 0..360 + hue = changeUIntScale(hue, 0, 65535, 0, 360); g_gotct = false; change = true; } diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index c19216842..d1bc5b731 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -32,10 +32,10 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri zigbee_devices.getHueState(shortaddr, &power, &colormode, &bri, &sat, &ct, &hue, &x, &y); - if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 - if (bri < 1) bri = 1; - if (sat > 254) sat = 254; // Philips Hue only accepts 254 as max hue - uint8_t hue8 = changeUIntScale(hue, 0, 360, 0, 254); // default hue is 0..254, we don't use extended hue + if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 + if (bri < 1) bri = 1; + if (sat > 254) sat = 254; // Philips Hue only accepts 254 as max hue + uint16_t hue16 = changeUIntScale(hue, 0, 360, 0, 65535); const size_t buf_size = 256; char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack @@ -56,7 +56,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri float y_f = y / 65536.0f; snprintf_P(buf, buf_size, PSTR("%s\"xy\":[%s,%s],"), buf, String(x, 5).c_str(), String(y, 5).c_str()); } - snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue, sat); + snprintf_P(buf, buf_size, PSTR("%s\"hue\":%d,\"sat\":%d,"), buf, hue16, sat); } if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { // white temp snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); @@ -164,7 +164,7 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { char param[16]; uint8_t hue8 = changeUIntScale(hue, 0, 360, 0, 254); if (sat > 0xFE) { sat = 0xFE; } - snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), hue8, sat); + snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat); uint8_t colormode = 0; // "hs" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param); zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr); @@ -250,8 +250,8 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { device_id, "hue", hue); response += buf; if (LST_RGB <= bulbtype) { - // change range from 0..65535 to 0..359 - hue = changeUIntScale(hue, 0, 65535, 0, 359); + // change range from 0..65535 to 0..360 + hue = changeUIntScale(hue, 0, 65535, 0, 360); huesat_changed = true; } resp = true; From d4a9ed41c9f18da6e6d3ecc833dcc3ba9402b4e1 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 26 Mar 2020 19:34:59 +0100 Subject: [PATCH 23/56] Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_2_devices.ino | 43 ++++++++++++++------ tasmota/xdrv_23_zigbee_3_hue.ino | 28 ++++++++----- tasmota/xdrv_23_zigbee_5_converters.ino | 18 ++++----- tasmota/xdrv_23_zigbee_6_commands.ino | 15 +++++++ tasmota/xdrv_23_zigbee_8_parsers.ino | 54 ++++++++++++++----------- 6 files changed, 102 insertions(+), 57 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 12f581ce8..0977c85c7 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Change GPIO initialization solving possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa ## Released diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index e4c6f6df0..d8cb1d5bc 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -46,7 +46,7 @@ typedef struct Z_Device { uint8_t seqNumber; // Light information for Hue integration integration, last known values int8_t bulbtype; // number of channel for the bulb: 0-5, or 0xFF if no Hue integration - uint8_t power; // power state (boolean) + uint8_t power; // power state (boolean), MSB (0x80) stands for reachable uint8_t colormode; // 0x00: Hue/Sat, 0x01: XY, 0x02: CT uint8_t dimmer; // last Dimmer value: 0-254 uint8_t sat; // last Sat: 0..254 @@ -66,12 +66,15 @@ typedef enum Z_Def_Category { Z_CAT_NONE = 0, // no category, it will happen anyways Z_CAT_READ_ATTR, // Attribute reporting, either READ_ATTRIBUTE or REPORT_ATTRIBUTE, we coalesce all attributes reported if we can Z_CAT_VIRTUAL_ATTR, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor + Z_CAT_REACHABILITY, // timer set to measure reachability of device, i.e. if we don't get an answer after 1s, it is marked as unreachable (for Alexa) Z_CAT_READ_0006, // Read 0x0006 cluster Z_CAT_READ_0008, // Read 0x0008 cluster Z_CAT_READ_0102, // Read 0x0300 cluster Z_CAT_READ_0300, // Read 0x0300 cluster } Z_Def_Category; +const uint32_t Z_CAT_REACHABILITY_TIMEOUT = 1000; // 1000 ms or 1s + typedef struct Z_Deferred { // below are per device timers, used for example to query the new state of the device uint32_t timer; // millis() when to fire the timer, 0 if no timer @@ -124,6 +127,7 @@ public: void setFriendlyName(uint16_t shortaddr, const char * str); const char * getFriendlyName(uint16_t shortaddr) const; const char * getModelId(uint16_t shortaddr) const; + void setReachable(uint16_t shortaddr, bool reachable); // get next sequence number for (increment at each all) uint8_t getNextSeqNumber(uint16_t shortaddr); @@ -137,15 +141,17 @@ public: void setHueBulbtype(uint16_t shortaddr, int8_t bulbtype); int8_t getHueBulbtype(uint16_t shortaddr) const ; void updateHueState(uint16_t shortaddr, - const uint8_t *power, const uint8_t *colormode, + const bool *power, const uint8_t *colormode, const uint8_t *dimmer, const uint8_t *sat, const uint16_t *ct, const uint16_t *hue, - const uint16_t *x, const uint16_t *y); + const uint16_t *x, const uint16_t *y, + const bool *reachable); bool getHueState(uint16_t shortaddr, - uint8_t *power, uint8_t *colormode, + bool *power, uint8_t *colormode, uint8_t *dimmer, uint8_t *sat, uint16_t *ct, uint16_t *hue, - uint16_t *x, uint16_t *y) const ; + uint16_t *x, uint16_t *y, + bool *reachable) const ; // Timers void resetTimersForDevice(uint16_t shortaddr, uint16_t groupaddr, uint8_t category); @@ -262,7 +268,7 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { 0, // seqNumber // Hue support -1, // no Hue support - 0, // power + 0x80, // power off + reachable 0, // colormode 0, // dimmer 0, // sat @@ -583,6 +589,12 @@ const char * Z_Devices::getModelId(uint16_t shortaddr) const { return nullptr; } +void Z_Devices::setReachable(uint16_t shortaddr, bool reachable) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + bitWrite(device.power, 7, reachable); +} + // get the next sequance number for the device, or use the global seq number if device is unknown uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { int32_t short_found = findShortAddr(shortaddr); @@ -616,12 +628,13 @@ int8_t Z_Devices::getHueBulbtype(uint16_t shortaddr) const { // Hue support void Z_Devices::updateHueState(uint16_t shortaddr, - const uint8_t *power, const uint8_t *colormode, + const bool *power, const uint8_t *colormode, const uint8_t *dimmer, const uint8_t *sat, const uint16_t *ct, const uint16_t *hue, - const uint16_t *x, const uint16_t *y) { + const uint16_t *x, const uint16_t *y, + const bool *reachable) { Z_Device &device = getShortAddr(shortaddr); - if (power) { device.power = *power; } + if (power) { bitWrite(device.power, 0, *power); } if (colormode){ device.colormode = *colormode; } if (dimmer) { device.dimmer = *dimmer; } if (sat) { device.sat = *sat; } @@ -629,18 +642,20 @@ void Z_Devices::updateHueState(uint16_t shortaddr, if (hue) { device.hue = *hue; } if (x) { device.x = *x; } if (y) { device.y = *y; } + if (reachable){ bitWrite(device.power, 7, *reachable); } } // return true if ok bool Z_Devices::getHueState(uint16_t shortaddr, - uint8_t *power, uint8_t *colormode, + bool *power, uint8_t *colormode, uint8_t *dimmer, uint8_t *sat, uint16_t *ct, uint16_t *hue, - uint16_t *x, uint16_t *y) const { + uint16_t *x, uint16_t *y, + bool *reachable) const { int32_t found = findShortAddr(shortaddr); if (found >= 0) { const Z_Device &device = *(_devices[found]); - if (power) { *power = device.power; } + if (power) { *power = bitRead(device.power, 0); } if (colormode){ *colormode = device.colormode; } if (dimmer) { *dimmer = device.dimmer; } if (sat) { *sat = device.sat; } @@ -648,6 +663,7 @@ bool Z_Devices::getHueState(uint16_t shortaddr, if (hue) { *hue = device.hue; } if (x) { *x = device.x; } if (y) { *y = device.y; } + if (reachable){ *reachable = bitRead(device.power, 7); } return true; } else { return false; @@ -951,7 +967,8 @@ String Z_Devices::dumpLightState(uint16_t shortaddr) const { dev[F(D_JSON_ZIGBEE_LIGHT)] = device.bulbtype; // sign extend, 0xFF changed as -1 if (0 <= device.bulbtype) { // bulbtype is defined - dev[F("Power")] = device.power; + dev[F("Power")] = bitRead(device.power, 0); + dev[F("Reachable")] = bitRead(device.power, 7); if (1 <= device.bulbtype) { dev[F("Dimmer")] = device.dimmer; } diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index d1bc5b731..ffbec109c 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -24,13 +24,19 @@ // idx: index in the list of zigbee_devices void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, String *response) { - uint8_t power, colormode, bri, sat; + static const char HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE[] PROGMEM = + "%s\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":%s}"; + + bool power, reachable; + uint8_t colormode, bri, sat; uint16_t ct, hue; uint16_t x, y; String light_status = ""; uint32_t echo_gen = findEchoGeneration(); // 1 for 1st gen =+ Echo Dot 2nd gen, 2 for 2nd gen and above - zigbee_devices.getHueState(shortaddr, &power, &colormode, &bri, &sat, &ct, &hue, &x, &y); + zigbee_devices.getHueState(shortaddr, &power, &colormode, &bri, &sat, &ct, &hue, &x, &y, &reachable); if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254 if (bri < 1) bri = 1; @@ -40,7 +46,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri const size_t buf_size = 256; char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (power & 1) ? "true" : "false"); + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), power ? "true" : "false"); // Brightness for all devices with PWM if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { // force dimmer for 1st gen Echo snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); @@ -61,7 +67,7 @@ void HueLightStatus1Zigbee(uint16_t shortaddr, uint8_t local_light_subtype, Stri if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { // white temp snprintf_P(buf, buf_size, PSTR("%s\"ct\":%d,"), buf, ct > 0 ? ct : 284); } - snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX, buf); + snprintf_P(buf, buf_size, HUE_LIGHTS_STATUS_JSON1_SUFFIX_ZIGBEE, buf, reachable ? "true" : "false"); *response += buf; free(buf); @@ -123,9 +129,9 @@ void ZigbeeHueGroups(String * lights) { // Send commands // Power On/Off -void ZigbeeHuePower(uint16_t shortaddr, uint8_t power) { - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power, ""); - zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); +void ZigbeeHuePower(uint16_t shortaddr, bool power) { + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power ? 1 : 0, ""); + zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } // Dimmer @@ -134,7 +140,7 @@ void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { char param[8]; snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer); zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0008, 0x04, param); - zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr); + zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } // CT @@ -145,7 +151,7 @@ void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8); uint8_t colormode = 2; // "ct" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x0A, param); - zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr); + zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr, nullptr); } // XY @@ -156,7 +162,7 @@ void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8); uint8_t colormode = 1; // "xy" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x07, param); - zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y); + zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y, nullptr); } // HueSat @@ -167,7 +173,7 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat); uint8_t colormode = 0; // "hs" zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param); - zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr); + zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr, nullptr); } void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index dfe544cbd..edd5ab682 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1215,38 +1215,38 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { // see if we need to update the Hue bulb status if ((cluster == 0x0006) && ((attribute == 0x0000) || (attribute == 0x8000))) { - uint8_t power = value; + bool power = value; zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } else if ((cluster == 0x0008) && (attribute == 0x0000)) { uint8_t dimmer = value; zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } else if ((cluster == 0x0300) && (attribute == 0x0000)) { uint16_t hue8 = value; uint16_t hue = changeUIntScale(hue8, 0, 254, 0, 360); // change range from 0..254 to 0..360 zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr, - nullptr, &hue, nullptr, nullptr); + nullptr, &hue, nullptr, nullptr, nullptr); } else if ((cluster == 0x0300) && (attribute == 0x0001)) { uint8_t sat = value; zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, &sat, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } else if ((cluster == 0x0300) && (attribute == 0x0003)) { uint16_t x = value; zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, &x, nullptr); + nullptr, nullptr, &x, nullptr, nullptr); } else if ((cluster == 0x0300) && (attribute == 0x0004)) { uint16_t y = value; zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, &y); + nullptr, nullptr, nullptr, &y, nullptr), nullptr; } else if ((cluster == 0x0300) && (attribute == 0x0007)) { uint16_t ct = value; zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, nullptr, nullptr, - &ct, nullptr, nullptr, nullptr); + &ct, nullptr, nullptr, nullptr, nullptr); } else if ((cluster == 0x0300) && (attribute == 0x0008)) { uint8_t colormode = value; zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } // Iterate on filter diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 4788ddf67..818f8afbe 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -173,6 +173,14 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus } } + +// This callback is registered after a an attribute read command was made to a light, and fires if we don't get any response after 1000 ms +int32_t Z_Unreachable(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { + if (shortaddr) { + zigbee_devices.setReachable(shortaddr, false); // mark device as reachable + } +} + // set a timer to read back the value in the future void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint) { uint32_t wait_ms = 0; @@ -192,6 +200,9 @@ void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus } if (wait_ms) { zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group + zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); + } } } @@ -300,6 +311,10 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin } if ((endpoint) || (groupaddr)) { // send only if we know the endpoint zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback); + if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group + zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); + } + } } } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index b10c4be05..5e05d6c82 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -308,6 +308,7 @@ int32_t Z_DataConfirm(int32_t res, const class SBuffer &buf) { // // Handle Receive End Device Announce incoming message +// This message is also received when a previously paired device is powered up // Send back Active Ep Req message // int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { @@ -328,6 +329,9 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { (capabilities & 0x08) ? "true" : "false", (capabilities & 0x40) ? "true" : "false" ); + // query the state of the bulb (for Alexa) + uint32_t wait_ms = 2000; // wait for 2s + Z_Query_Bulb(nwkAddr, wait_ms); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); XdrvRulesProcess(); @@ -513,6 +517,10 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; + // since we just receveived data from the device, it is reachable + zigbee_devices.resetTimersForDevice(srcaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there + zigbee_devices.setReachable(srcaddr, true); // mark device as reachable + if (defer_attributes) { // Prepare for publish if (zigbee_devices.jsonIsConflict(srcaddr, json)) { @@ -591,38 +599,36 @@ int32_t Z_Load_Devices(uint8_t value) { return 0; // continue } +// +// Query the state of a bulb (light) if its type allows it +// +void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) { + const uint32_t inter_message_ms = 100; // wait 100ms between messages + + if (0 <= zigbee_devices.getHueBulbtype(shortaddr)) { + uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); + + if (endpoint) { // send only if we know the endpoint + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0006, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0008, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); + wait_ms += inter_message_ms; + zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); + } + } +} + // // Send messages to query the state of each Hue emulated light // int32_t Z_Query_Bulbs(uint8_t value) { // Scan all devices and send deferred requests to know the state of bulbs uint32_t wait_ms = 1000; // start with 1.0 s delay - const uint32_t inter_message_ms = 100; // wait 100ms between messages for (uint32_t i = 0; i < zigbee_devices.devicesSize(); i++) { const Z_Device &device = zigbee_devices.devicesAt(i); - - if (0 <= device.bulbtype) { - uint16_t cluster; - uint8_t endpoint = zigbee_devices.findFirstEndpoint(device.shortaddr); - - cluster = 0x0006; - if (endpoint) { // send only if we know the endpoint - zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - } - - cluster = 0x0008; - if (endpoint) { // send only if we know the endpoint - zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - } - - cluster = 0x0300; - if (endpoint) { // send only if we know the endpoint - zigbee_devices.setTimer(device.shortaddr, 0 /* groupaddr */, wait_ms, cluster, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); - wait_ms += inter_message_ms; - } - } + Z_Query_Bulb(device.shortaddr, wait_ms); } return 0; // continue } From 6c1f5576d04ccdce58bb897955d7b56c453f2f6c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 26 Mar 2020 20:58:59 +0100 Subject: [PATCH 24/56] Add Zigbee ZbUnbind command --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 2 ++ tasmota/xdrv_23_zigbee_8_parsers.ino | 27 +++++++++++++++++++++++++++ tasmota/xdrv_23_zigbee_9_impl.ino | 27 +++++++++++++++++++++++---- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0977c85c7..665186b0d 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix Zigbee sending wrong Sat value with Hue emulation - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa +- Add Zigbee ``ZbUnbind``command ## Released diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 47afc7307..04433788f 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -505,6 +505,8 @@ #define D_JSON_ZIGBEE_RECEIVED "ZbReceived" #define D_CMND_ZIGBEE_BIND "Bind" #define D_JSON_ZIGBEE_BIND "ZbBind" +#define D_CMND_ZIGBEE_UNBIND "Unbind" + #define D_JSON_ZIGBEE_UNBIND "ZbUnbind" #define D_CMND_ZIGBEE_PING "Ping" #define D_JSON_ZIGBEE_PING "ZbPing" #define D_JSON_ZIGBEE_IEEE "IEEEAddr" diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 5e05d6c82..cc95d4ed0 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -388,6 +388,31 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { return -1; } +// +// Handle Unbind Rsp incoming message +// +int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + + const char * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, friendlyName, status, getZigbeeStatusMessage(status).c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_UNBIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + "}}"), nwkAddr, status, getZigbeeStatusMessage(status).c_str()); + } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} /*********************************************************************************************\ * Send specific ZNP messages @@ -553,6 +578,7 @@ ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 +ZBM(AREQ_ZDO_UNBIND_RSP, Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP) // 45A2 // Dispatcher callbacks table const Z_Dispatcher Z_DispatchTable[] PROGMEM = { @@ -565,6 +591,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, + { AREQ_ZDO_UNBIND_RSP, &Z_UnbindRsp }, }; /*********************************************************************************************\ diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 49f89c9c7..423ac43f1 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -34,7 +34,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" - D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" + D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE ; @@ -43,7 +43,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, &CmndZbForget, &CmndZbSave, &CmndZbName, - &CmndZbBind, &CmndZbPing, &CmndZbModelId, + &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, &CmndZbLight, CmndZbRestore, }; @@ -534,8 +534,9 @@ void CmndZbSend(void) { // // Command `ZbBind` // -void CmndZbBind(void) { +void ZbBindUnbind(bool unbind) { // false = bind, true = unbind // ZbBind {"Device":"", "Endpoint":, "Cluster":, "ToDevice":"", "ToEndpoint":, "ToGroup": } + // ZbUnbind {"Device":"", "Endpoint":, "Cluster":, "ToDevice":"", "ToEndpoint":, "ToGroup": } // local endpoint is always 1, IEEE addresses are calculated if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } @@ -601,7 +602,11 @@ void CmndZbBind(void) { SBuffer buf(34); buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_BIND_REQ); + if (unbind) { + buf.add8(ZDO_UNBIND_REQ); + } else { + buf.add8(ZDO_BIND_REQ); + } buf.add16(srcDevice); buf.add64(srcLongAddr); buf.add8(endpoint); @@ -620,6 +625,20 @@ void CmndZbBind(void) { ResponseCmndDone(); } +// +// Command ZbBind +// +void CmndZbBind(void) { + ZbBindUnbind(false); +} + +// +// Command ZbBind +// +void CmndZbUnbind(void) { + ZbBindUnbind(true); +} + // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { CmndZbProbeOrPing(true); From 3bf14105631aeefed9799fc8af9971aa176daea2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 27 Mar 2020 16:34:00 +0100 Subject: [PATCH 25/56] Fix PCF8574 and MCP230xx address confict Fix PCF8574 and MCP230xx address confict (#8010) --- tasmota/xdrv_28_pcf8574.ino | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index 26ae9f65a..98773c385 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -77,6 +77,16 @@ void Pcf8574Init(void) uint8_t pcf8574_address = PCF8574_ADDR1; while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { +#ifdef USE_MCP230xx_ADDR + if (USE_MCP230xx_ADDR == pcf8574_address) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Address 0x%02x reserved for MCP320xx skipped"), pcf8574_address); + pcf8574_address++; + if ((PCF8574_ADDR1 +7) == pcf8574_address) { // Support I2C addresses 0x20 to 0x26 and 0x39 to 0x3F + pcf8574_address = PCF8574_ADDR2 +1; + } + } +#endif + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Probing addr: 0x%x for PCF8574"), pcf8574_address); if (I2cSetDevice(pcf8574_address)) { @@ -93,12 +103,6 @@ void Pcf8574Init(void) } pcf8574_address++; -#ifdef USE_MCP230xx_ADDR - if (USE_MCP230xx_ADDR == pcf8574_address) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Addr: 0x%x reserved for MCP320xx, skipping PCF8574 probe"), pcf8574_address); - pcf8574_address++; - } -#endif if ((PCF8574_ADDR1 +7) == pcf8574_address) { // Support I2C addresses 0x20 to 0x26 and 0x39 to 0x3F pcf8574_address = PCF8574_ADDR2 +1; } From aa0ace3763cb6739cd130548771c2d4c4ef99703 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 27 Mar 2020 16:38:29 +0100 Subject: [PATCH 26/56] Add support for 64x48 SSD1306 OLED (#6740) --- .../Adafruit_SSD1306.cpp | 13 ++++++++++--- tasmota/CHANGELOG.md | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp index 9827f7584..ec7097983 100644 --- a/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp +++ b/lib/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp @@ -916,15 +916,22 @@ uint8_t *Adafruit_SSD1306::getBuffer(void) { of graphics commands, as best needed by one's own application. */ void Adafruit_SSD1306::display(void) { + int16_t col_start = 0; + int16_t col_end = WIDTH - 1; + if ((64 == WIDTH) && (48 == HEIGHT)) { // for 64x48, we need to shift by 32 in both directions + col_start += 32; + col_end += 32; + } + TRANSACTION_START static const uint8_t PROGMEM dlist1[] = { SSD1306_PAGEADDR, 0, // Page start address 0xFF, // Page end (not really, but works here) - SSD1306_COLUMNADDR, - 0 }; // Column start address + SSD1306_COLUMNADDR }; ssd1306_commandList(dlist1, sizeof(dlist1)); - ssd1306_command1(WIDTH - 1); // Column end address + ssd1306_command1(col_start); // Column start address + ssd1306_command1(col_end); // Column end address #if defined(ESP8266) // ESP8266 needs a periodic yield() call to avoid watchdog reset. diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 665186b0d..c874a0ef4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add Zigbee ``ZbUnbind``command +- Add support for 64x48 SSD1306 OLED (#6740) ## Released From 898fff9dbc13bae88fc8da564af76de5f0b3c8e4 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 28 Mar 2020 11:13:01 +0100 Subject: [PATCH 27/56] Add multiple GroupTopic (x=1-4) (default disabled) grouptopic (1-4) subscription even when USE_DEVICE_GROUPS is not used. --- tasmota/my_user_config.h | 1 + tasmota/support_tasmota.ino | 4 ++-- tasmota/tasmota_post.h | 6 ++++++ tasmota/xdrv_01_webserver.ino | 11 ++++++++++- tasmota/xdrv_02_mqtt.ino | 28 ++++++++++++++++++---------- tasmota/xdrv_27_shutter.ino | 2 +- 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index ab80c4cf6..910d4c7fe 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -344,6 +344,7 @@ // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) #define MQTT_CLEAN_SESSION 1 // Mqtt clean session connection (0 = No clean session, 1 = Clean session (default)) +//#define USE_GROUPTOPIC_SET // Enable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- MQTT - Domoticz ----------------------------- #define USE_DOMOTICZ // Enable Domoticz (+6k code, +0.3k mem) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 3c4239359..a42515899 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -130,11 +130,11 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi return stopic; } -char* GetGroupTopic_P(char *stopic, const char* subtopic) +char* GetGroupTopic_P(char *stopic, const char* subtopic, int itopic) { // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# // SetOption75 1: cmnd/ - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(itopic), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) } char* GetFallbackTopic_P(char *stopic, const char* subtopic) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 1bba02172..d7a36f160 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -98,6 +98,7 @@ extern "C" void resetPins(); #define CODE_IMAGE_STR "sensors" #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- //#define ROTARY_V1 // Add support for MI Desk Lamp @@ -273,6 +274,7 @@ extern "C" void resetPins(); #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #endif // FIRMWARE_KNX_NO_EMULATION /*********************************************************************************************\ @@ -292,6 +294,7 @@ extern "C" void resetPins(); #undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -373,6 +376,7 @@ extern "C" void resetPins(); //#undef USE_SUNRISE // Disable support for Sunrise and sunset tools //#undef USE_RULES // Disable support for rules #undef USE_DISCOVERY // Disable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -474,6 +478,7 @@ extern "C" void resetPins(); #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant #undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) @@ -595,6 +600,7 @@ extern "C" void resetPins(); #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant //#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 7f55a01fd..31531af88 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2127,7 +2127,16 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); // WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), SettingsText(SET_MQTT_GRP_TOPIC)); - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, "")); +#ifdef USE_GROUPTOPIC_SET + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " 1}2%s"), GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC)); + for(uint32_t i=0; i < 3; i++) { + if (strlen(SettingsText(SET_MQTT_GRP_TOPIC2+i))) { + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 2+i, GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC2+i)); + } + } +#else // USE_GROUPTOPIC_SET + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC)); +#endif // USE_GROUPTOPIC_SET WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, "")); } else { diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 1d084862b..22fcb2d9d 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -510,8 +510,16 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { - GetGroupTopic_P(stopic, PSTR("#")); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ + GetGroupTopic_P(stopic, PSTR("#"), SET_MQTT_GRP_TOPIC); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ MqttSubscribe(stopic); +#ifdef USE_GROUPTOPIC_SET + for(uint32_t i=0; i < 3; i++) { + if (strlen(SettingsText(SET_MQTT_GRP_TOPIC2+i))) { + GetGroupTopic_P(stopic, PSTR("#"), SET_MQTT_GRP_TOPIC2+i); + MqttSubscribe(stopic); + } + } +#endif GetFallbackTopic_P(stopic, PSTR("#")); MqttSubscribe(stopic); } @@ -522,7 +530,7 @@ void MqttConnected(void) if (Mqtt.initial_connection_state) { char stopic2[TOPSZ]; Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "")); + ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { @@ -881,26 +889,26 @@ void CmndPublish(void) void CmndGroupTopic(void) { -#ifdef USE_DEVICE_GROUPS +#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { uint32_t settings_text_index = (XdrvMailbox.index <= 1 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2); -#endif // USE_DEVICE_GROUPS +#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET if (XdrvMailbox.data_len > 0) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } -#ifdef USE_DEVICE_GROUPS +#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) SettingsUpdateText(settings_text_index, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); -#else // USE_DEVICE_GROUPS +#else // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET SettingsUpdateText(SET_MQTT_GRP_TOPIC, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); -#endif // USE_DEVICE_GROUPS +#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET restart_flag = 2; } -#ifdef USE_DEVICE_GROUPS +#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) ResponseCmndChar(SettingsText(settings_text_index)); } -#else // USE_DEVICE_GROUPS +#else // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET ResponseCmndChar(SettingsText(SET_MQTT_GRP_TOPIC)); -#endif // USE_DEVICE_GROUPS +#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET } void CmndTopic(void) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index cedf93e28..b68de3c8d 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -685,7 +685,7 @@ void ShutterButtonHandler(void) for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { if ((i==shutter_index) || (Settings.shutter_button[button_index] & (0x01<<30))) { snprintf_P(scommand, sizeof(scommand),PSTR("ShutterPosition%d"), i+1); - GetGroupTopic_P(stopic, scommand); + GetGroupTopic_P(stopic, scommand, SET_MQTT_GRP_TOPIC); Response_P("%d", position); MqttPublish(stopic, false); } From dbc9f16ffc5c8e6f590b38382ca444dda162c334 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Mar 2020 16:48:36 +0100 Subject: [PATCH 28/56] Add support for up to four MQTT GroupTopics - Bump version to 8.2.0.2 - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) --- RELEASENOTES.md | 10 +++-- tasmota/CHANGELOG.md | 10 +++-- tasmota/my_user_config.h | 1 - tasmota/support_command.ino | 4 +- tasmota/support_tasmota.ino | 2 +- tasmota/tasmota.h | 1 + tasmota/tasmota_post.h | 6 --- tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 14 +++---- tasmota/xdrv_02_mqtt.ino | 76 +++++++++++++++++++++++------------ 10 files changed, 75 insertions(+), 51 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1804b32c5..da5dd225f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,9 +52,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.2.0.1 +### Version 8.2.0.2 - Change HM-10 sensor type detection and add features (#7962) -- Change GPIO initialization solving possible Relay toggle on (OTA) restart +- Fix possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation -- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add Zigbee command ``ZbUnbind`` +- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa +- Add support for 64x48 SSD1306 OLED (#6740) +- Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c874a0ef4..fa969d778 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,13 +1,17 @@ ## Unreleased (development) +### 8.2.0.2 20200328 + +- Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) + ### 8.2.0.1 20200321 - Change HM-10 sensor type detection and add features (#7962) -- Change GPIO initialization solving possible Relay toggle on (OTA) restart +- Fix possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation -- Add command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add ZIgbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add Zigbee command ``ZbUnbind`` - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa -- Add Zigbee ``ZbUnbind``command - Add support for 64x48 SSD1306 OLED (#6740) ## Released diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 910d4c7fe..ab80c4cf6 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -344,7 +344,6 @@ // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) #define MQTT_CLEAN_SESSION 1 // Mqtt clean session connection (0 = No clean session, 1 = Clean session (default)) -//#define USE_GROUPTOPIC_SET // Enable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- MQTT - Domoticz ----------------------------- #define USE_DOMOTICZ // Enable Domoticz (+6k code, +0.3k mem) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index e1cc9e812..133203a3e 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -107,9 +107,11 @@ void ResponseCmndIdxChar(const char* value) void ResponseCmndAll(uint32_t text_index, uint32_t count) { + uint32_t real_index = text_index; mqtt_data[0] = '\0'; for (uint32_t i = 0; i < count; i++) { - ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(text_index +i)); + if ((SET_MQTT_GRP_TOPIC == text_index) && (1 == i)) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(real_index +i)); } ResponseJsonEnd(); } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index a42515899..23a4caad7 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -130,7 +130,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi return stopic; } -char* GetGroupTopic_P(char *stopic, const char* subtopic, int itopic) +char* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic) { // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# // SetOption75 1: cmnd/ diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index a1c7d1082..033b8d783 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -81,6 +81,7 @@ const uint8_t MAX_NTP_SERVERS = 3; // Max number of NTP servers const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names const uint8_t MAX_BUTTON_TEXT = 16; // Max number of GUI button labels +const uint8_t MAX_GROUP_TOPICS = 4; // Max number of Group Topics const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index d7a36f160..1bba02172 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -98,7 +98,6 @@ extern "C" void resetPins(); #define CODE_IMAGE_STR "sensors" #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- //#define ROTARY_V1 // Add support for MI Desk Lamp @@ -274,7 +273,6 @@ extern "C" void resetPins(); #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #endif // FIRMWARE_KNX_NO_EMULATION /*********************************************************************************************\ @@ -294,7 +292,6 @@ extern "C" void resetPins(); #undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -376,7 +373,6 @@ extern "C" void resetPins(); //#undef USE_SUNRISE // Disable support for Sunrise and sunset tools //#undef USE_RULES // Disable support for rules #undef USE_DISCOVERY // Disable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) // -- Optional modules ---------------------------- #undef ROTARY_V1 // Disable support for MI Desk Lamp @@ -478,7 +474,6 @@ extern "C" void resetPins(); #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant #undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) @@ -600,7 +595,6 @@ extern "C" void resetPins(); #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant //#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set -#undef USE_GROUPTOPIC_SET // Disable multiple GROUPTOPIC, x=1-4 (+0k1 code) #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 3bc994c67..47879d1fe 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08020001; +const uint32_t VERSION = 0x08020002; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 31531af88..f48ce9431 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2126,17 +2126,13 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); -// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), SettingsText(SET_MQTT_GRP_TOPIC)); -#ifdef USE_GROUPTOPIC_SET - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " 1}2%s"), GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC)); - for(uint32_t i=0; i < 3; i++) { - if (strlen(SettingsText(SET_MQTT_GRP_TOPIC2+i))) { - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 2+i, GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC2+i)); + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 1 +i, GetGroupTopic_P(stopic, "", real_index +i)); } } -#else // USE_GROUPTOPIC_SET - WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, "", SET_MQTT_GRP_TOPIC)); -#endif // USE_GROUPTOPIC_SET WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, "")); } else { diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 22fcb2d9d..ac3065fe8 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -510,16 +510,14 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { - GetGroupTopic_P(stopic, PSTR("#"), SET_MQTT_GRP_TOPIC); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ - MqttSubscribe(stopic); -#ifdef USE_GROUPTOPIC_SET - for(uint32_t i=0; i < 3; i++) { - if (strlen(SettingsText(SET_MQTT_GRP_TOPIC2+i))) { - GetGroupTopic_P(stopic, PSTR("#"), SET_MQTT_GRP_TOPIC2+i); + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + GetGroupTopic_P(stopic, PSTR("#"), real_index +i); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ MqttSubscribe(stopic); } } -#endif GetFallbackTopic_P(stopic, PSTR("#")); MqttSubscribe(stopic); } @@ -889,26 +887,52 @@ void CmndPublish(void) void CmndGroupTopic(void) { -#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - uint32_t settings_text_index = (XdrvMailbox.index <= 1 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2); -#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET - if (XdrvMailbox.data_len > 0) { - MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } -#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) - SettingsUpdateText(settings_text_index, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); -#else // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET - SettingsUpdateText(SET_MQTT_GRP_TOPIC, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); -#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET - restart_flag = 2; + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_GROUP_TOPICS)) { + if (XdrvMailbox.data_len > 0) { + uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); + + // Eliminate duplicates, have at least one and fill from index 1 + char stemp[MAX_GROUP_TOPICS][TOPSZ]; + uint32_t read_index = 0; + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (strlen(SettingsText(real_index +i))) { + bool not_equal = true; + for (uint32_t j = 0; j < read_index; j++) { + if (!strcmp(SettingsText(real_index +i), stemp[j])) { // Topics are case-sensitive + not_equal = false; + } + } + if (not_equal) { + strncpy(stemp[read_index], SettingsText(real_index +i), sizeof(stemp[read_index])); + read_index++; + } + } + } + if (0 == read_index) { + SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + } else { + uint32_t write_index = 0; + uint32_t real_index = SET_MQTT_GRP_TOPIC; + for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { + if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; } + if (write_index < read_index) { + SettingsUpdateText(real_index +i, stemp[write_index]); + write_index++; + } else { + SettingsUpdateText(real_index +i, ""); + } + } + } + + restart_flag = 2; + } + ResponseCmndAll(SET_MQTT_GRP_TOPIC, MAX_GROUP_TOPICS); } -#if defined(USE_DEVICE_GROUPS ) || defined(USE_GROUPTOPIC_SET) - ResponseCmndChar(SettingsText(settings_text_index)); - } -#else // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET - ResponseCmndChar(SettingsText(SET_MQTT_GRP_TOPIC)); -#endif // USE_DEVICE_GROUPS || USE_GROUPTOPIC_SET } void CmndTopic(void) From e5a44e63262032d1d7e0b356967306e170a4fd00 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Mar 2020 18:08:43 +0100 Subject: [PATCH 29/56] Refactor template --- tasmota/settings.h | 3 +- tasmota/support.ino | 10 +- tasmota/support_command.ino | 2 +- tasmota/tasmota_template.h | 2820 ++++++++++++++++----------------- tasmota/xdrv_01_webserver.ino | 2 +- 5 files changed, 1393 insertions(+), 1444 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 737ce8a82..fa98a8ecf 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -397,7 +397,8 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A uint8_t user_template_base; // 71F - mytmplt user_template; // 720 29 bytes + char user_template_name[15]; // 720 15 bytes + mytmplt user_template; // 72F 14 bytes uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E uint16_t display_width; // 774 diff --git a/tasmota/support.ino b/tasmota/support.ino index 490918276..458a8efd3 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1098,9 +1098,10 @@ bool ValidModule(uint32_t index) String AnyModuleName(uint32_t index) { if (USER_MODULE == index) { - return String(Settings.user_template.name); + return String(Settings.user_template_name); } else { - return FPSTR(kModules[index].name); + char name[15]; + return String(GetTextIndexed(name, sizeof(name), index, kModuleNames)); } } @@ -1153,6 +1154,7 @@ void ModuleDefault(uint32_t module) { if (USER_MODULE == module) { module = WEMOS; } // Generic Settings.user_template_base = module; + GetTextIndexed(Settings.user_template_name, sizeof(Settings.user_template_name), module, kModuleNames); memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); } @@ -1268,7 +1270,7 @@ bool JsonTemplate(const char* dataBuf) // All parameters are optional allowing for partial changes const char* name = obj[D_JSON_NAME]; if (name != nullptr) { - strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); + strlcpy(Settings.user_template_name, name, sizeof(Settings.user_template_name)); } if (obj[D_JSON_GPIO].success()) { for (uint32_t i = 0; i < sizeof(mycfgio); i++) { @@ -1289,7 +1291,7 @@ bool JsonTemplate(const char* dataBuf) void TemplateJson(void) { - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template_name); for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 133203a3e..36e5c08fd 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1064,7 +1064,7 @@ void CmndTemplate(void) if (Settings.module != USER_MODULE) { ModuleDefault(Settings.module); } - snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); + snprintf_P(Settings.user_template_name, sizeof(Settings.user_template_name), PSTR("Merged")); uint32_t j = 0; for (uint32_t i = 0; i < sizeof(mycfgio); i++) { if (6 == i) { j = 9; } diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 4715f682f..e21260741 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -319,157 +319,6 @@ const char kSensorNamesFixed[] PROGMEM = D_SENSOR_SPI_MISO "|" D_SENSOR_SPI_MOSI "|" D_SENSOR_SPI_CLK "|" D_SENSOR_USER; -// User selectable ADC0 functionality -enum UserSelectableAdc0 { - ADC0_NONE, // Not used - ADC0_INPUT, // Analog input - ADC0_TEMP, // Thermistor - ADC0_LIGHT, // Light sensor - ADC0_BUTTON, // Button - ADC0_BUTTON_INV, - ADC0_RANGE, // Range - ADC0_CT_POWER, // Current -// ADC0_SWITCH, // Switch -// ADC0_SWITCH_INV, - ADC0_END }; - -// Programmer selectable ADC0 functionality -enum ProgramSelectableAdc0 { - ADC0_FIX_START = 14, - ADC0_USER, // User configurable needs to be 15 - ADC0_MAX }; - -// Text in webpage Module Parameters and commands ADC -const char kAdc0Names[] PROGMEM = - D_SENSOR_NONE "|" D_ANALOG_INPUT "|" - D_TEMPERATURE "|" D_LIGHT "|" - D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "i|" - D_RANGE "|" - D_CT_POWER "|" -// D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "i|" - ; - -/********************************************************************************************/ - -// Supported hardware modules -enum SupportedModules { - SONOFF_BASIC, - SONOFF_RF, - SONOFF_SV, - SONOFF_TH, - SONOFF_DUAL, - SONOFF_POW, - SONOFF_4CH, - SONOFF_S2X, - SLAMPHER, - SONOFF_TOUCH, - SONOFF_LED, - CH1, - CH4, - MOTOR, - ELECTRODRAGON, - EXS_RELAY, - WION, - WEMOS, - SONOFF_DEV, - H801, - SONOFF_SC, - SONOFF_BN, - SONOFF_4CHPRO, - HUAFAN_SS, - SONOFF_BRIDGE, - SONOFF_B1, - AILIGHT, - SONOFF_T11, - SONOFF_T12, - SONOFF_T13, - SUPLA1, - WITTY, - YUNSHAN, - MAGICHOME, - LUANIHVIO, - KMC_70011, - ARILUX_LC01, - ARILUX_LC11, - SONOFF_DUAL_R2, - ARILUX_LC06, - SONOFF_S31, - ZENGGE_ZF_WF017, - SONOFF_POW_R2, - SONOFF_IFAN02, - BLITZWOLF_BWSHP, - SHELLY1, - SHELLY2, - PHILIPS, - NEO_COOLCAM, - ESP_SWITCH, - OBI, - TECKIN, - APLIC_WDP303075, - TUYA_DIMMER, - GOSUND, - ARMTRONIX_DIMMERS, - SK03_TUYA, - PS_16_DZ, - TECKIN_US, - MANZOKU_EU_4, - OBI2, - YTF_IR_BRIDGE, - DIGOO, - KA10, - ZX2820, - MI_DESK_LAMP, - SP10, - WAGA, - SYF05, - SONOFF_L1, - SONOFF_IFAN03, - EXS_DIMMER, - PWM_DIMMER, - SONOFF_D1, - MAXMODULE}; - -#define USER_MODULE 255 - -/********************************************************************************************/ - -#define MAX_GPIO_PIN 17 // Number of supported GPIO -#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11) - -const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; - -typedef struct MYIO { - uint8_t io[MAX_GPIO_PIN]; -} myio; - -typedef struct MYCFGIO { - uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS]; -} mycfgio; - -#define GPIO_FLAG_USED 0 // Currently two flags used - -#define GPIO_FLAG_SPARE04 16 -#define GPIO_FLAG_SPARE05 32 -#define GPIO_FLAG_SPARE06 64 -#define GPIO_FLAG_SPARE07 128 - -typedef union { - uint8_t data; - struct { - uint8_t adc0 : 4; // Allow ADC0 when define USE_ADC_VCC is disabled - uint8_t spare04 : 1; - uint8_t spare05 : 1; - uint8_t spare06 : 1; - uint8_t spare07 : 1; - }; -} gpio_flag; - -typedef struct MYTMPLT { - char name[15]; - mycfgio gp; - gpio_flag flag; -} mytmplt; - const uint8_t kGpioNiceList[] PROGMEM = { GPIO_NONE, // Not used GPIO_KEY1, // Buttons @@ -809,6 +658,103 @@ const uint8_t kGpioNiceList[] PROGMEM = { #endif }; +/********************************************************************************************/ + +// User selectable ADC0 functionality +enum UserSelectableAdc0 { + ADC0_NONE, // Not used + ADC0_INPUT, // Analog input + ADC0_TEMP, // Thermistor + ADC0_LIGHT, // Light sensor + ADC0_BUTTON, // Button + ADC0_BUTTON_INV, + ADC0_RANGE, // Range + ADC0_CT_POWER, // Current +// ADC0_SWITCH, // Switch +// ADC0_SWITCH_INV, + ADC0_END }; + +// Programmer selectable ADC0 functionality +enum ProgramSelectableAdc0 { + ADC0_FIX_START = 14, + ADC0_USER, // User configurable needs to be 15 + ADC0_MAX }; + +// Text in webpage Module Parameters and commands ADC +const char kAdc0Names[] PROGMEM = + D_SENSOR_NONE "|" D_ANALOG_INPUT "|" + D_TEMPERATURE "|" D_LIGHT "|" + D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "i|" + D_RANGE "|" + D_CT_POWER "|" +// D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "i|" + ; + +/********************************************************************************************/ + +#define MAX_GPIO_PIN 17 // Number of supported GPIO +#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11) + +const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; + +typedef struct MYIO { + uint8_t io[MAX_GPIO_PIN]; +} myio; + +typedef struct MYCFGIO { + uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS]; +} mycfgio; + +#define GPIO_FLAG_USED 0 // Currently two flags used + +#define GPIO_FLAG_SPARE04 16 +#define GPIO_FLAG_SPARE05 32 +#define GPIO_FLAG_SPARE06 64 +#define GPIO_FLAG_SPARE07 128 + +typedef union { + uint8_t data; + struct { + uint8_t adc0 : 4; // Allow ADC0 when define USE_ADC_VCC is disabled + uint8_t spare04 : 1; + uint8_t spare05 : 1; + uint8_t spare06 : 1; + uint8_t spare07 : 1; + }; +} gpio_flag; + +typedef struct MYTMPLT { + mycfgio gp; + gpio_flag flag; +} mytmplt; + +/********************************************************************************************/ + +// Supported hardware modules +enum SupportedModules { + SONOFF_BASIC, SONOFF_RF, SONOFF_SV, SONOFF_TH, SONOFF_DUAL, SONOFF_POW, SONOFF_4CH, SONOFF_S2X, SLAMPHER, SONOFF_TOUCH, + SONOFF_LED, CH1, CH4, MOTOR, ELECTRODRAGON, EXS_RELAY, WION, WEMOS, SONOFF_DEV, H801, + SONOFF_SC, SONOFF_BN, SONOFF_4CHPRO, HUAFAN_SS, SONOFF_BRIDGE, SONOFF_B1, AILIGHT, SONOFF_T11, SONOFF_T12, SONOFF_T13, + SUPLA1, WITTY, YUNSHAN, MAGICHOME, LUANIHVIO, KMC_70011, ARILUX_LC01, ARILUX_LC11, SONOFF_DUAL_R2, ARILUX_LC06, + SONOFF_S31, ZENGGE_ZF_WF017, SONOFF_POW_R2, SONOFF_IFAN02, BLITZWOLF_BWSHP, SHELLY1, SHELLY2, PHILIPS, NEO_COOLCAM, ESP_SWITCH, + OBI, TECKIN, APLIC_WDP303075, TUYA_DIMMER, GOSUND, ARMTRONIX_DIMMERS, SK03_TUYA, PS_16_DZ, TECKIN_US, MANZOKU_EU_4, + OBI2, YTF_IR_BRIDGE, DIGOO, KA10, ZX2820, MI_DESK_LAMP, SP10, WAGA, SYF05, SONOFF_L1, + SONOFF_IFAN03, EXS_DIMMER, PWM_DIMMER, SONOFF_D1, + MAXMODULE}; + +#define USER_MODULE 255 + +const char kModuleNames[] PROGMEM = + "Sonoff Basic|Sonoff RF|Sonoff SV|Sonoff TH|Sonoff Dual|Sonoff Pow|Sonoff 4CH|Sonoff S2X|Slampher|Sonoff Touch|" + "Sonoff LED|1 Channel|4 Channel|Motor C/AC|ElectroDragon|EXS Relay(s)|WiOn|Generic|Sonoff Dev|H801|" + "Sonoff SC|Sonoff BN-SZ|Sonoff 4CH Pro|Huafan SS|Sonoff Bridge|Sonoff B1|AiLight|Sonoff T1 1CH|Sonoff T1 2CH|Sonoff T1 3CH|" + "Supla Espablo|Witty Cloud|Yunshan Relay|MagicHome|Luani HVIO|KMC 70011|Arilux LC01|Arilux LC11|Sonoff Dual R2|Arilux LC06|" + "Sonoff S31|Zengge WF017|Sonoff Pow R2|Sonoff iFan02|BlitzWolf SHP|Shelly 1|Shelly 2|Xiaomi Philips|Neo Coolcam|ESP Switch|" + "OBI Socket|Teckin|AplicWDP303075|Tuya MCU|Gosund SP1 v23|ARMTR Dimmer|SK03 Outdoor|PS-16-DZ|Teckin US|Manzoku strip|" + "OBI Socket 2|YTF IR Bridge|Digoo DG-SP202|KA10|Luminea ZX2820|Mi Desk Lamp|SP10|WAGA CHCZ02MB|SYF05|Sonoff L1|" + "Sonoff iFan03|EXS Dimmer|PWM Dimmer|Sonoff D1" + ; + const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_BASIC, // Sonoff Relay Devices SONOFF_RF, @@ -910,1368 +856,1368 @@ const uint8_t kModuleNiceList[] PROGMEM = { // Default module settings const mytmplt kModules[MAXMODULE] PROGMEM = { - { "Sonoff Basic", // SONOFF_BASIC - Sonoff Basic (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Only available on newer Sonoff Basic R2 V1 - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - 0, // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, // GPIO15 - 0, // GPIO16 - 0 // ADC0 Analog input + { // SONOFF_BASIC - Sonoff Basic (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Only available on newer Sonoff Basic R2 V1 + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + 0, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, // GPIO15 + 0, // GPIO16 + 0 // ADC0 Analog input }, - { "Sonoff RF", // SONOFF_RF - Sonoff RF (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, 0, 0 + { // SONOFF_RF - Sonoff RF (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, 0, 0 }, - { "Sonoff SV", // SONOFF_SV - Sonoff SV (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - GPIO_USER, // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, 0, - ADC0_USER // ADC0 Analog input + { // SONOFF_SV - Sonoff SV (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, 0, + ADC0_USER // ADC0 Analog input }, - { "Sonoff TH", // SONOFF_TH - Sonoff TH10/16 (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, 0, 0 + { // SONOFF_TH - Sonoff TH10/16 (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, 0, 0 }, - { "Sonoff Dual", // SONOFF_DUAL - Sonoff Dual (ESP8266) - 0, - GPIO_TXD, // GPIO01 Relay control - 0, - GPIO_RXD, // GPIO03 Relay control - GPIO_USER, // GPIO04 Optional sensor - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, 0, 0 + { // SONOFF_DUAL - Sonoff Dual (ESP8266) + 0, + GPIO_TXD, // GPIO01 Relay control + 0, + GPIO_RXD, // GPIO03 Relay control + GPIO_USER, // GPIO04 Optional sensor + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, 0, 0 }, - { "Sonoff Pow", // SONOFF_POW - Sonoff Pow (ESP8266 - HLW8012) - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, - GPIO_NRG_SEL, // GPIO05 HLW8012 Sel output (1 = Voltage) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_NRG_CF1, // GPIO13 HLW8012 CF1 voltage / current - GPIO_HLW_CF, // GPIO14 HLW8012 CF power - GPIO_LED1, // GPIO15 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0 + { // SONOFF_POW - Sonoff Pow (ESP8266 - HLW8012) + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, 0, + GPIO_NRG_SEL, // GPIO05 HLW8012 Sel output (1 = Voltage) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_NRG_CF1, // GPIO13 HLW8012 CF1 voltage / current + GPIO_HLW_CF, // GPIO14 HLW8012 CF power + GPIO_LED1, // GPIO15 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0 }, - { "Sonoff 4CH", // SONOFF_4CH - Sonoff 4CH (ESP8285) - GPIO_KEY1, // GPIO00 Button 1 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) - GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_KEY2, // GPIO09 Button 2 - GPIO_KEY3, // GPIO10 Button 3 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - Link and Power status - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - GPIO_KEY4, // GPIO14 Button 4 - GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) - 0, 0 + { // SONOFF_4CH - Sonoff 4CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - Link and Power status + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + GPIO_KEY4, // GPIO14 Button 4 + GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) + 0, 0 }, - { "Sonoff S2X", // SONOFF_S2X - Sonoff S20, S22 and S26 Smart Socket (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status - GPIO_LED1_INV, // GPIO13 Green/Blue Led (0 = On, 1 = Off) - 0, 0, 0, 0 + { // SONOFF_S2X - Sonoff S20, S22 and S26 Smart Socket (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status + GPIO_LED1_INV, // GPIO13 Green/Blue Led (0 = On, 1 = Off) + 0, 0, 0, 0 }, - { "Slampher", // SLAMPHER - Slampher (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SLAMPHER - Slampher (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff Touch", // SONOFF_TOUCH - Sonoff Touch (ESP8285) - GPIO_KEY1, // GPIO00 Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - 0, 0, 0, 0 + { // SONOFF_TOUCH - Sonoff Touch (ESP8285) + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - Link and Power status + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + 0, 0, 0, 0 }, - { "Sonoff LED", // SONOFF_LED - Sonoff LED (ESP8266) - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, - GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) - GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM1, // GPIO12 Cold light (PWM0 Cold) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - GPIO_PWM2, // GPIO14 Warm light (PWM1 Warm) - GPIO_USER, // GPIO15 Optional sensor (PWM4 Blue) - 0, 0 + { // SONOFF_LED - Sonoff LED (ESP8266) + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) + GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM1, // GPIO12 Cold light (PWM0 Cold) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_PWM2, // GPIO14 Warm light (PWM1 Warm) + GPIO_USER, // GPIO15 Optional sensor (PWM4 Blue) + 0, 0 }, - { "1 Channel", // CH1 - 1 Channel Inching/Latching Relay using (PSA-B01 - ESP8266 and PSF-B01 - ESP8285) - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // CH1 - 1 Channel Inching/Latching Relay using (PSA-B01 - ESP8266 and PSF-B01 - ESP8285) + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "4 Channel", // CH4 - 4 Channel Inching/Latching Relays (ESP8266) - 0, - GPIO_TXD, // GPIO01 Relay control - 0, - GPIO_RXD, // GPIO03 Relay control - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // CH4 - 4 Channel Inching/Latching Relays (ESP8266) + 0, + GPIO_TXD, // GPIO01 Relay control + 0, + GPIO_RXD, // GPIO03 Relay control + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Motor C/AC", // MOTOR - Motor Clockwise / Anti clockwise (PSA-B01 - ESP8266) - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // MOTOR - Motor Clockwise / Anti clockwise (PSA-B01 - ESP8266) + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "ElectroDragon", // ELECTRODRAGON - ElectroDragon IoT Relay Board (ESP8266) - GPIO_KEY2, // GPIO00 Button 2 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_KEY1, // GPIO02 Button 1 - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - GPIO_USER, // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL2, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) - GPIO_REL1, // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) - GPIO_USER, // GPIO14 Optional sensor - GPIO_USER, // GPIO15 Optional sensor - GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off) - Link and Power status - ADC0_USER // ADC0 A0 Analog input + { // ELECTRODRAGON - ElectroDragon IoT Relay Board (ESP8266) + GPIO_KEY2, // GPIO00 Button 2 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_KEY1, // GPIO02 Button 1 + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL2, // GPIO12 Red Led and Relay 2 (0 = Off, 1 = On) + GPIO_REL1, // GPIO13 Red Led and Relay 1 (0 = Off, 1 = On) + GPIO_USER, // GPIO14 Optional sensor + GPIO_USER, // GPIO15 Optional sensor + GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off) - Link and Power status + ADC0_USER // ADC0 A0 Analog input }, - { "EXS Relay(s)", // EXS_RELAY - ES-Store Latching relay(s) (ESP8266) - // https://ex-store.de/ESP8266-WiFi-Relay-V31 - // V3.1 Module Pin 1 VCC 3V3, Module Pin 6 GND - // https://ex-store.de/2-Kanal-WiFi-WLan-Relay-V5-Blackline-fuer-Unterputzmontage - GPIO_USER, // GPIO00 V3.1 Module Pin 8 - V5.0 Module Pin 4 - GPIO_USER, // GPIO01 UART0_TXD V3.1 Module Pin 2 - V5.0 Module Pin 3 - GPIO_USER, // GPIO02 V3.1 Module Pin 7 - GPIO_USER, // GPIO03 UART0_RXD V3.1 Module Pin 3 - GPIO_USER, // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 - GPIO_USER, // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) - GPIO_REL2, // GPIO13 Relay1 ( 1 = On) - GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) - GPIO_LED1, // GPIO15 V5.0 LED1 - Link and Power status - GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On) - 0 + { // EXS_RELAY - ES-Store Latching relay(s) (ESP8266) + // https://ex-store.de/ESP8266-WiFi-Relay-V31 + // V3.1 Module Pin 1 VCC 3V3, Module Pin 6 GND + // https://ex-store.de/2-Kanal-WiFi-WLan-Relay-V5-Blackline-fuer-Unterputzmontage + GPIO_USER, // GPIO00 V3.1 Module Pin 8 - V5.0 Module Pin 4 + GPIO_USER, // GPIO01 UART0_TXD V3.1 Module Pin 2 - V5.0 Module Pin 3 + GPIO_USER, // GPIO02 V3.1 Module Pin 7 + GPIO_USER, // GPIO03 UART0_RXD V3.1 Module Pin 3 + GPIO_USER, // GPIO04 V3.1 Module Pin 10 - V5.0 Module Pin 2 + GPIO_USER, // GPIO05 V3.1 Module Pin 9 - V5.0 Module Pin 1 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay1 ( 1 = Off) + GPIO_REL2, // GPIO13 Relay1 ( 1 = On) + GPIO_USER, // GPIO14 V3.1 Module Pin 5 - V5.0 GPIO_REL3_INV Relay2 ( 1 = Off) + GPIO_LED1, // GPIO15 V5.0 LED1 - Link and Power status + GPIO_USER, // GPIO16 V3.1 Module Pin 4 - V5.0 GPIO_REL4_INV Relay2 ( 1 = On) + 0 }, - { "WiOn", // WION - Indoor Tap (ESP8266) - // https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w - GPIO_USER, // GPIO00 Optional sensor (pm clock) - 0, - GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off) - Link and Power status - 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 Optional sensor (pm data) - GPIO_KEY1, // GPIO13 Button - 0, - GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) - 0, 0 + { // WION - Indoor Tap (ESP8266) + // https://www.amazon.com/gp/product/B00ZYLUBJU/ref=s9_acsd_al_bw_c_x_3_w + GPIO_USER, // GPIO00 Optional sensor (pm clock) + 0, + GPIO_LED1, // GPIO02 Green Led (1 = On, 0 = Off) - Link and Power status + 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor (pm data) + GPIO_KEY1, // GPIO13 Button + 0, + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) + 0, 0 }, - { "Generic", // WEMOS - Any ESP8266/ESP8285 device like WeMos and NodeMCU hardware (ESP8266) - GPIO_USER, // GPIO00 D3 Wemos Button Shield - GPIO_USER, // GPIO01 TX Serial RXD - GPIO_USER, // GPIO02 D4 Wemos DHT Shield - GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor - GPIO_USER, // GPIO04 D2 Wemos I2C SDA - GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_USER, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - GPIO_USER, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 D6 - GPIO_USER, // GPIO13 D7 - GPIO_USER, // GPIO14 D5 - GPIO_USER, // GPIO15 D8 - GPIO_USER, // GPIO16 D0 Wemos Wake - ADC0_USER // ADC0 A0 Analog input + { // WEMOS - Any ESP8266/ESP8285 device like WeMos and NodeMCU hardware (ESP8266) + GPIO_USER, // GPIO00 D3 Wemos Button Shield + GPIO_USER, // GPIO01 TX Serial RXD + GPIO_USER, // GPIO02 D4 Wemos DHT Shield + GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor + GPIO_USER, // GPIO04 D2 Wemos I2C SDA + GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_USER, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + GPIO_USER, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 D6 + GPIO_USER, // GPIO13 D7 + GPIO_USER, // GPIO14 D5 + GPIO_USER, // GPIO15 D8 + GPIO_USER, // GPIO16 D0 Wemos Wake + ADC0_USER // ADC0 A0 Analog input }, - { "Sonoff Dev", // SONOFF_DEV - Sonoff Dev (ESP8266) - GPIO_KEY1, // GPIO00 E-FW Button - GPIO_USER, // GPIO01 TX Serial RXD and Optional sensor - 0, // GPIO02 - GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor - GPIO_USER, // GPIO04 Optional sensor - GPIO_USER, // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 - GPIO_USER, // GPIO13 BLUE LED - GPIO_USER, // GPIO14 Optional sensor - 0, // GPIO15 - 0, // GPIO16 - ADC0_USER // ADC0 A0 Analog input + { // SONOFF_DEV - Sonoff Dev (ESP8266) + GPIO_KEY1, // GPIO00 E-FW Button + GPIO_USER, // GPIO01 TX Serial RXD and Optional sensor + 0, // GPIO02 + GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 + GPIO_USER, // GPIO13 BLUE LED + GPIO_USER, // GPIO14 Optional sensor + 0, // GPIO15 + 0, // GPIO16 + ADC0_USER // ADC0 A0 Analog input }, - { "H801", // H801 - Lixada H801 Wifi (ESP8266) - GPIO_USER, // GPIO00 E-FW Button - GPIO_LED1, // GPIO01 Green LED - Link and Power status - GPIO_USER, // GPIO02 TX and Optional sensor - Pin next to TX on the PCB - GPIO_USER, // GPIO03 RX and Optional sensor - Pin next to GND on the PCB - GPIO_PWM5, // GPIO04 W2 - PWM5 - GPIO_LED2_INV, // GPIO05 Red LED - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM3, // GPIO12 Blue - GPIO_PWM2, // GPIO13 Green - GPIO_PWM4, // GPIO14 W1 - PWM4 - GPIO_PWM1, // GPIO15 Red - 0, 0 + { // H801 - Lixada H801 Wifi (ESP8266) + GPIO_USER, // GPIO00 E-FW Button + GPIO_LED1, // GPIO01 Green LED - Link and Power status + GPIO_USER, // GPIO02 TX and Optional sensor - Pin next to TX on the PCB + GPIO_USER, // GPIO03 RX and Optional sensor - Pin next to GND on the PCB + GPIO_PWM5, // GPIO04 W2 - PWM5 + GPIO_LED2_INV, // GPIO05 Red LED + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM3, // GPIO12 Blue + GPIO_PWM2, // GPIO13 Green + GPIO_PWM4, // GPIO14 W1 - PWM4 + GPIO_PWM1, // GPIO15 Red + 0, 0 }, - { "Sonoff SC", // SONOFF_SC - onoff SC (ESP8266) - GPIO_KEY1, // GPIO00 Button - GPIO_TXD, // GPIO01 RXD to ATMEGA328P - GPIO_USER, // GPIO02 Optional sensor - GPIO_RXD, // GPIO03 TXD to ATMEGA328P - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_SC - onoff SC (ESP8266) + GPIO_KEY1, // GPIO00 Button + GPIO_TXD, // GPIO01 RXD to ATMEGA328P + GPIO_USER, // GPIO02 Optional sensor + GPIO_RXD, // GPIO03 TXD to ATMEGA328P + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff BN-SZ", // SONOFF_BN - Sonoff BN-SZ01 Ceiling led (ESP8285) - 0, 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_PWM1, // GPIO12 Light - GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_BN - Sonoff BN-SZ01 Ceiling led (ESP8285) + 0, 0, 0, 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_PWM1, // GPIO12 Light + GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff 4CH Pro", // SONOFF_4CHPRO - Sonoff 4CH Pro (ESP8285) - GPIO_KEY1, // GPIO00 Button 1 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) - GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_KEY2, // GPIO09 Button 2 - GPIO_KEY3, // GPIO10 Button 3 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - GPIO_KEY4, // GPIO14 Button 4 - GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) - 0, 0 + { // SONOFF_4CHPRO - Sonoff 4CH Pro (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_KEY4, // GPIO14 Button 4 + GPIO_REL4, // GPIO15 Red Led and Relay 4 (0 = Off, 1 = On) + 0, 0 }, - { "Huafan SS", // HUAFAN_SS - Hua Fan Smart Socket (ESP8266) - like Sonoff Pow - GPIO_LEDLNK_INV, // GPIO00 Blue Led (0 = On, 1 = Off) - Link status - 0, 0, - GPIO_LED1_INV, // GPIO03 Red Led (0 = On, 1 = Off) - Power status - GPIO_KEY1, // GPIO04 Button - GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_CF1, // GPIO12 HLW8012 CF1 voltage / current - GPIO_NRG_SEL, // GPIO13 HLW8012 Sel output (1 = Voltage) - GPIO_HLW_CF, // GPIO14 HLW8012 CF power - 0, 0, 0 + { // HUAFAN_SS - Hua Fan Smart Socket (ESP8266) - like Sonoff Pow + GPIO_LEDLNK_INV, // GPIO00 Blue Led (0 = On, 1 = Off) - Link status + 0, 0, + GPIO_LED1_INV, // GPIO03 Red Led (0 = On, 1 = Off) - Power status + GPIO_KEY1, // GPIO04 Button + GPIO_REL1_INV, // GPIO05 Relay (0 = On, 1 = Off) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_CF1, // GPIO12 HLW8012 CF1 voltage / current + GPIO_NRG_SEL, // GPIO13 HLW8012 Sel output (1 = Voltage) + GPIO_HLW_CF, // GPIO14 HLW8012 CF power + 0, 0, 0 }, - { "Sonoff Bridge", // SONOFF_BRIDGE - Sonoff RF Bridge 433 (ESP8285) - GPIO_KEY1, // GPIO00 Button - GPIO_TXD, // GPIO01 RF bridge control - GPIO_USER, // GPIO02 Optional sensor - GPIO_RXD, // GPIO03 RF bridge control - GPIO_USER, // GPIO04 Optional sensor - GPIO_USER, // GPIO05 Optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 Optional sensor - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - GPIO_USER, // GPIO14 Optional sensor - 0, 0, 0 + { // SONOFF_BRIDGE - Sonoff RF Bridge 433 (ESP8285) + GPIO_KEY1, // GPIO00 Button + GPIO_TXD, // GPIO01 RF bridge control + GPIO_USER, // GPIO02 Optional sensor + GPIO_RXD, // GPIO03 RF bridge control + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + GPIO_USER, // GPIO14 Optional sensor + 0, 0, 0 }, - { "Sonoff B1", // SONOFF_B1 - Sonoff B1 (ESP8285 - my9231) - GPIO_KEY1, // GPIO00 Pad - GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad - GPIO_USER, // GPIO02 Optional sensor SDA pad - GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_DI, // GPIO12 my9231 DI - 0, - GPIO_DCKI, // GPIO14 my9231 DCKI - 0, 0, 0 + { // SONOFF_B1 - Sonoff B1 (ESP8285 - my9231) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_DI, // GPIO12 my9231 DI + 0, + GPIO_DCKI, // GPIO14 my9231 DCKI + 0, 0, 0 }, - { "AiLight", // AILIGHT - Ai-Thinker RGBW led (ESP8266 - my9291) - GPIO_KEY1, // GPIO00 Pad - GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad - GPIO_USER, // GPIO02 Optional sensor SDA pad - GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, - GPIO_DI, // GPIO13 my9291 DI - 0, - GPIO_DCKI, // GPIO15 my9291 DCKI - 0, 0 + { // AILIGHT - Ai-Thinker RGBW led (ESP8266 - my9291) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, + GPIO_DI, // GPIO13 my9291 DI + 0, + GPIO_DCKI, // GPIO15 my9291 DCKI + 0, 0 }, - { "Sonoff T1 1CH", // SONOFF_T11 - Sonoff T1 1CH (ESP8285) - GPIO_KEY1, // GPIO00 Button 1 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_T11 - Sonoff T1 1CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff T1 2CH", // SONOFF_T12 - Sonoff T1 2CH (ESP8285) - GPIO_KEY1, // GPIO00 Button 1 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, - GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_KEY2, // GPIO09 Button 2 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_T12 - Sonoff T1 2CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, + GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff T1 3CH", // SONOFF_T13 - Sonoff T1 3CH (ESP8285) - GPIO_KEY1, // GPIO00 Button 1 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_REL3, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) - GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_KEY2, // GPIO09 Button 2 - GPIO_KEY3, // GPIO10 Button 3 - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_T13 - Sonoff T1 3CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional Sensor (J3 Pin 5) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Supla Espablo", // SUPLA1 - Supla Espablo (ESP8266) - // http://www.wykop.pl/ramka/3325399/diy-supla-do-puszki-instalacyjnej-podtynkowej-supla-org/ - 0, // GPIO00 Flash jumper - GPIO_USER, // GPIO01 Serial RXD and Optional sensor + { // SUPLA1 - Supla Espablo (ESP8266) + // http://www.wykop.pl/ramka/3325399/diy-supla-do-puszki-instalacyjnej-podtynkowej-supla-org/ + 0, // GPIO00 Flash jumper + GPIO_USER, // GPIO01 Serial RXD and Optional sensor #ifdef USE_DS18x20 - GPIO_DSB, // GPIO02 DS18B20 sensor + GPIO_DSB, // GPIO02 DS18B20 sensor #else - GPIO_USER, // GPIO02 Optional sensor + GPIO_USER, // GPIO02 Optional sensor #endif - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_KEY1, // GPIO04 Button 1 - GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 Optional sensor - GPIO_REL2, // GPIO13 Relay 2 (0 = Off, 1 = On) - GPIO_USER, // GPIO14 Optional sensor - 0, - GPIO_LED1, // GPIO16 Led (1 = On, 0 = Off) - Link and Power status - ADC0_USER // ADC0 A0 Analog input + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 Button 1 + GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Optional sensor + GPIO_REL2, // GPIO13 Relay 2 (0 = Off, 1 = On) + GPIO_USER, // GPIO14 Optional sensor + 0, + GPIO_LED1, // GPIO16 Led (1 = On, 0 = Off) - Link and Power status + ADC0_USER // ADC0 A0 Analog input }, - { "Witty Cloud", // WITTY - Witty Cloud Dev Board (ESP8266) - // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html - GPIO_USER, // GPIO00 D3 flash push button on interface board - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LED1_INV, // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F - Link and Power status - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_KEY1, // GPIO04 D2 push button on ESP-12F board - GPIO_USER, // GPIO05 D1 optional sensor - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM2, // GPIO12 D6 RGB LED Green - GPIO_PWM3, // GPIO13 D7 RGB LED Blue - GPIO_USER, // GPIO14 D5 optional sensor - GPIO_PWM1, // GPIO15 D8 RGB LED Red - GPIO_USER, // GPIO16 D0 optional sensor - ADC0_USER // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled + { // WITTY - Witty Cloud Dev Board (ESP8266) + // https://www.aliexpress.com/item/ESP8266-serial-WIFI-Witty-cloud-Development-Board-ESP-12F-module-MINI-nodemcu/32643464555.html + GPIO_USER, // GPIO00 D3 flash push button on interface board + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 D4 Blue Led (0 = On, 1 = Off) on ESP-12F - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 D2 push button on ESP-12F board + GPIO_USER, // GPIO05 D1 optional sensor + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 D6 RGB LED Green + GPIO_PWM3, // GPIO13 D7 RGB LED Blue + GPIO_USER, // GPIO14 D5 optional sensor + GPIO_PWM1, // GPIO15 D8 RGB LED Red + GPIO_USER, // GPIO16 D0 optional sensor + ADC0_USER // ADC0 A0 Light sensor / Requires USE_ADC_VCC in user_config.h to be disabled }, - { "Yunshan Relay", // YUNSHAN - Yunshan Wifi Relay (ESP8266) - // https://www.ebay.com/p/Esp8266-220v-10a-Network-Relay-WiFi-Module/1369583381 - // Schematics and Info https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/ - 0, // GPIO00 Flash jumper - Module Pin 8 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - Module Pin 2 - GPIO_LED1_INV, // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7 - Link and Power status - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - Module Pin 3 - GPIO_REL1, // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10 - GPIO_KEY1, // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, 0, 0, 0, 0, 0 + { // YUNSHAN - Yunshan Wifi Relay (ESP8266) + // https://www.ebay.com/p/Esp8266-220v-10a-Network-Relay-WiFi-Module/1369583381 + // Schematics and Info https://ucexperiment.wordpress.com/2016/12/18/yunshan-esp8266-250v-15a-acdc-network-wifi-relay-module/ + 0, // GPIO00 Flash jumper - Module Pin 8 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor - Module Pin 2 + GPIO_LED1_INV, // GPIO02 Blue Led (0 = On, 1 = Off) on ESP-12F - Module Pin 7 - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor - Module Pin 3 + GPIO_REL1, // GPIO04 Red Led and Relay (0 = Off, 1 = On) - Module Pin 10 + GPIO_KEY1, // GPIO05 Blue Led and OptoCoupler input - Module Pin 9 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, 0, 0, 0, 0, 0 }, - { "MagicHome", // MAGICHOME - Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) - // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html - 0, - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LED1_INV, // GPIO02 Blue onboard LED - Link and Power status - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) (Arilux LC10) - GPIO_PWM2, // GPIO05 RGB LED Green - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM3, // GPIO12 RGB LED Blue - GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) - GPIO_PWM1, // GPIO14 RGB LED Red - GPIO_ARIRFSEL, // GPIO15 RF receiver control (Arilux LC10) - 0, 0 + { // MAGICHOME - Magic Home (aka Flux-light) (ESP8266) and Arilux LC10 (ESP8285) + // https://www.aliexpress.com/item/Magic-Home-Mini-RGB-RGBW-Wifi-Controller-For-Led-Strip-Panel-light-Timing-Function-16million-colors/32686853650.html + 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LED1_INV, // GPIO02 Blue onboard LED - Link and Power status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) (Arilux LC10) + GPIO_PWM2, // GPIO05 RGB LED Green + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM3, // GPIO12 RGB LED Blue + GPIO_USER, // GPIO13 RGBW LED White (optional - set to PWM4 for Cold White or Warm White as used on Arilux LC10) + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_ARIRFSEL, // GPIO15 RF receiver control (Arilux LC10) + 0, 0 }, - { "Luani HVIO", // LUANIHVIO - ESP8266_HVIO - // https://luani.de/projekte/esp8266-hvio/ - 0, // GPIO00 Flash jumper - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Optional sensor / I2C SDA pad - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_REL1, // GPIO04 Relay 1 (0 = Off, 1 = On) - GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_SWT1, // GPIO12 External input 1 (0 = On, 1 = Off) - GPIO_SWT2, // GPIO13 External input 2 (0 = On, 1 = Off) - GPIO_USER, // GPIO14 Optional sensor / I2C SCL pad - GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) - Link and Power status - 0, - ADC0_USER // ADC0 A0 Analog input + { // LUANIHVIO - ESP8266_HVIO + // https://luani.de/projekte/esp8266-hvio/ + 0, // GPIO00 Flash jumper + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Optional sensor / I2C SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL1, // GPIO04 Relay 1 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_SWT1, // GPIO12 External input 1 (0 = On, 1 = Off) + GPIO_SWT2, // GPIO13 External input 2 (0 = On, 1 = Off) + GPIO_USER, // GPIO14 Optional sensor / I2C SCL pad + GPIO_LED1, // GPIO15 Led (1 = On, 0 = Off) - Link and Power status + 0, + ADC0_USER // ADC0 A0 Analog input }, - { "KMC 70011", // KMC_70011 - KMC 70011 - // https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, - GPIO_HLW_CF, // GPIO04 HLW8012 CF power - GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL, // GPIO12 HLW8012 SEL (1 = Voltage) - GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status - GPIO_REL1, // GPIO14 Relay - 0, 0, 0 + { // KMC_70011 - KMC 70011 + // https://www.amazon.com/KMC-Timing-Monitoring-Network-125V-240V/dp/B06XRX2GTQ + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL, // GPIO12 HLW8012 SEL (1 = Voltage) + GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status + GPIO_REL1, // GPIO14 Relay + 0, 0, 0 }, - { "Arilux LC01", // ARILUX_LC01 - Arilux AL-LC01 (ESP8285) - // https://www.banggood.com/nl/ARILUX-AL-LC01-Super-Mini-LED-WIFI-Smart-RGB-Controller-For-RGB-LED-Strip-Light-DC-9-12V-p-1058603.html - // (PwmFrequency 1111Hz) - GPIO_KEY1, // GPIO00 Optional Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_ARIRFSEL, // GPIO02 RF receiver control - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) - GPIO_PWM1, // GPIO05 RGB LED Red - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM2, // GPIO12 RGB LED Green - GPIO_PWM3, // GPIO13 RGB LED Blue - GPIO_USER, // GPIO14 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) - 0, 0, 0 + { // ARILUX_LC01 - Arilux AL-LC01 (ESP8285) + // https://www.banggood.com/nl/ARILUX-AL-LC01-Super-Mini-LED-WIFI-Smart-RGB-Controller-For-RGB-LED-Strip-Light-DC-9-12V-p-1058603.html + // (PwmFrequency 1111Hz) + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_ARIRFSEL, // GPIO02 RF receiver control + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_ARIRFRCV, // GPIO04 IR or RF receiver (optional) + GPIO_PWM1, // GPIO05 RGB LED Red + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM3, // GPIO13 RGB LED Blue + GPIO_USER, // GPIO14 RGBW LED White (optional - set to PWM4 for Cold White or Warm White) + 0, 0, 0 }, - { "Arilux LC11", // ARILUX_LC11 - Arilux AL-LC11 (ESP8266) - // https://www.banggood.com/nl/ARILUX-AL-LC11-Super-Mini-LED-WIFI-APP-Controller-RF-Remote-Control-For-RGBWW-LED-Strip-DC9-28V-p-1085112.html - // (PwmFrequency 540Hz) - GPIO_KEY1, // GPIO00 Optional Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_ARIRFSEL, // GPIO02 RF receiver control - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_PWM2, // GPIO04 RGB LED Green - GPIO_PWM1, // GPIO05 RGB LED Red - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM5, // GPIO12 RGBCW LED Warm - GPIO_PWM4, // GPIO13 RGBW LED Cold - GPIO_PWM3, // GPIO14 RGB LED Blue - GPIO_ARIRFRCV, // GPIO15 RF receiver input - 0, 0 + { // ARILUX_LC11 - Arilux AL-LC11 (ESP8266) + // https://www.banggood.com/nl/ARILUX-AL-LC11-Super-Mini-LED-WIFI-APP-Controller-RF-Remote-Control-For-RGBWW-LED-Strip-DC9-28V-p-1085112.html + // (PwmFrequency 540Hz) + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_ARIRFSEL, // GPIO02 RF receiver control + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_PWM2, // GPIO04 RGB LED Green + GPIO_PWM1, // GPIO05 RGB LED Red + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM5, // GPIO12 RGBCW LED Warm + GPIO_PWM4, // GPIO13 RGBW LED Cold + GPIO_PWM3, // GPIO14 RGB LED Blue + GPIO_ARIRFRCV, // GPIO15 RF receiver input + 0, 0 }, - { "Sonoff Dual R2", // SONOFF_DUAL_R2 - Sonoff Dual R2 (ESP8285) - GPIO_USER, // GPIO00 Button 0 on header (0 = On, 1 = Off) - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - 0, - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, - GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_USER, // GPIO09 Button 1 on header (0 = On, 1 = Off) - GPIO_KEY1, // GPIO10 Button on casing - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_DUAL_R2 - Sonoff Dual R2 (ESP8285) + GPIO_USER, // GPIO00 Button 0 on header (0 = On, 1 = Off) + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_USER, // GPIO09 Button 1 on header (0 = On, 1 = Off) + GPIO_KEY1, // GPIO10 Button on casing + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Arilux LC06", // ARILUX_LC06 - Arilux AL-LC06 (ESP8285) - // https://www.banggood.com/ARILUX-AL-LC06-LED-WIFI-Smartphone-Controller-Romote-5-Channels-DC12-24V-For-RGBWW-Strip-light-p-1061476.html - GPIO_KEY1, // GPIO00 Optional Button - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_USER, // GPIO02 Empty pad - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_USER, // GPIO04 W2 - PWM5 - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM2, // GPIO12 RGB LED Green - GPIO_PWM3, // GPIO13 RGB LED Blue - GPIO_PWM1, // GPIO14 RGB LED Red - GPIO_USER, // GPIO15 RGBW LED White - 0, 0 + { // ARILUX_LC06 - Arilux AL-LC06 (ESP8285) + // https://www.banggood.com/ARILUX-AL-LC06-LED-WIFI-Smartphone-Controller-Romote-5-Channels-DC12-24V-For-RGBWW-Strip-light-p-1061476.html + GPIO_KEY1, // GPIO00 Optional Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_USER, // GPIO02 Empty pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_USER, // GPIO04 W2 - PWM5 + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM3, // GPIO13 RGB LED Blue + GPIO_PWM1, // GPIO14 RGB LED Red + GPIO_USER, // GPIO15 RGBW LED White + 0, 0 }, - { "Sonoff S31", // SONOFF_S31 - Sonoff S31 (ESP8266 - CSE7766) - GPIO_KEY1, // GPIO00 Button - GPIO_CSE7766_TX, // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor - 0, - GPIO_CSE7766_RX, // GPIO03 Serial TXD - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_S31 - Sonoff S31 (ESP8266 - CSE7766) + GPIO_KEY1, // GPIO00 Button + GPIO_CSE7766_TX, // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor + 0, + GPIO_CSE7766_RX, // GPIO03 Serial TXD + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Green Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Zengge WF017", // ZENGGE_ZF_WF017 - Zenggee ZJ-WF017-A (ESP12S)) - // https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644 - GPIO_KEY1, // GPIO00 Optional Button - 0, - GPIO_USER, // GPIO02 Empty pad - 0, - GPIO_USER, // GPIO04 W2 - PWM5 - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM2, // GPIO12 RGB LED Green - GPIO_PWM1, // GPIO13 RGB LED Red - GPIO_PWM3, // GPIO14 RGB LED Blue - 0, 0, 0 + { // ZENGGE_ZF_WF017 - Zenggee ZJ-WF017-A (ESP12S)) + // https://www.ebay.com/p/Smartphone-Android-IOS-WiFi-Music-Controller-for-RGB-5050-3528-LED-Strip-Light/534446632?_trksid=p2047675.l2644 + GPIO_KEY1, // GPIO00 Optional Button + 0, + GPIO_USER, // GPIO02 Empty pad + 0, + GPIO_USER, // GPIO04 W2 - PWM5 + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 RGB LED Green + GPIO_PWM1, // GPIO13 RGB LED Red + GPIO_PWM3, // GPIO14 RGB LED Blue + 0, 0, 0 }, - { "Sonoff Pow R2", // SONOFF_POW_R2 - Sonoff Pow R2 (ESP8285 - CSE7766) - GPIO_KEY1, // GPIO00 Button - GPIO_CSE7766_TX, // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor - 0, - GPIO_CSE7766_RX, // GPIO03 Serial TXD - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status - 0, 0, 0, 0 + { // SONOFF_POW_R2 - Sonoff Pow R2 (ESP8285 - CSE7766) + GPIO_KEY1, // GPIO00 Button + GPIO_CSE7766_TX, // GPIO01 Serial RXD 4800 baud 8E1 CSE7766 energy sensor + 0, + GPIO_CSE7766_RX, // GPIO03 Serial TXD + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff iFan02", // SONOFF_IFAN02 - Sonoff iFan02 (ESP8285) - GPIO_KEY1, // GPIO00 WIFI_KEY0 Virtual button 1 as feedback from RC - GPIO_USER, // GPIO01 ESP_TXD Serial RXD and Optional sensor - 0, // GPIO02 ESP_LOG - GPIO_USER, // GPIO03 ESP_RXD Serial TXD and Optional sensor - GPIO_REL3, // GPIO04 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan - GPIO_REL2, // GPIO05 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_KEY2, // GPIO09 WIFI_KEY1 Virtual button 2 as feedback from RC - GPIO_KEY3, // GPIO10 WIFI_KEY2 Virtual button 3 as feedback from RC - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light - GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status - GPIO_KEY4, // GPIO14 WIFI_KEY3 Virtual button 4 as feedback from RC - GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan - 0, 0 + { // SONOFF_IFAN02 - Sonoff iFan02 (ESP8285) + GPIO_KEY1, // GPIO00 WIFI_KEY0 Virtual button 1 as feedback from RC + GPIO_USER, // GPIO01 ESP_TXD Serial RXD and Optional sensor + 0, // GPIO02 ESP_LOG + GPIO_USER, // GPIO03 ESP_RXD Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan + GPIO_REL2, // GPIO05 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_KEY2, // GPIO09 WIFI_KEY1 Virtual button 2 as feedback from RC + GPIO_KEY3, // GPIO10 WIFI_KEY2 Virtual button 3 as feedback from RC + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light + GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status + GPIO_KEY4, // GPIO14 WIFI_KEY3 Virtual button 4 as feedback from RC + GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan + 0, 0 }, - { "BlitzWolf SHP", // BLITZWOLF_BWSHP - BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) - // https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html - // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1 - // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1 - // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html - GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - 0, - GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_KEY1, // GPIO13 Button - GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage - GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) - 0, 0 + { // BLITZWOLF_BWSHP - BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring) + // https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html + // https://www.amazon.de/Steckdose-Homecube-intelligente-Verbrauchsanzeige-funktioniert/dp/B076Q2LKHG/ref=sr_1_fkmr0_1 + // https://www.amazon.de/Intelligente-Stromverbrauch-Fernsteurung-Schaltbare-Energieklasse/dp/B076WZQS4S/ref=sr_1_1 + // https://www.aliexpress.com/store/product/BlitzWolf-BW-SHP6-EU-Plug-Metering-Version-WIFI-Smart-Socket-220V-240V-10A-Work-with-Amazon/1965360_32945504669.html + GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) + 0, 0 }, - { "Shelly 1", // SHELLY1 - Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ - GPIO_USER, // GPIO00 - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC - GPIO_USER, // GPIO01 Serial RXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC - 0, - GPIO_USER, // GPIO03 Serial TXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC - GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) - GPIO_SWT1_NP, // GPIO05 SW pin - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, 0, 0, 0, 0, 0 + { // SHELLY1 - Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ + GPIO_USER, // GPIO00 - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + GPIO_USER, // GPIO01 Serial RXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + 0, + GPIO_USER, // GPIO03 Serial TXD - Can be changed to GPIO_USER, only if Shelly is powered with 12V DC + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_SWT1_NP, // GPIO05 SW pin + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, 0, 0, 0, 0, 0 }, - { "Shelly 2", // SHELLY2 - Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ - 0, - GPIO_MCP39F5_TX, // GPIO01 MCP39F501 Serial input - 0, - GPIO_MCP39F5_RX, // GPIO03 MCP39F501 Serial output - GPIO_REL1, // GPIO04 - GPIO_REL2, // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_SWT1, // GPIO12 - 0, - GPIO_SWT2, // GPIO14 - GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset - 0, - 0 + { // SHELLY2 - Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ + 0, + GPIO_MCP39F5_TX, // GPIO01 MCP39F501 Serial input + 0, + GPIO_MCP39F5_RX, // GPIO03 MCP39F501 Serial output + GPIO_REL1, // GPIO04 + GPIO_REL2, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_SWT1, // GPIO12 + 0, + GPIO_SWT2, // GPIO14 + GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset + 0, + 0 }, - { "Xiaomi Philips", // PHILIPS - Xiaomi Philips bulb (ESP8266) - 0, 0, 0, 0, 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_PWM2, // GPIO12 cold/warm light - 0, 0, - GPIO_PWM1, // GPIO15 light intensity - 0, 0 + { // PHILIPS - Xiaomi Philips bulb (ESP8266) + 0, 0, 0, 0, 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_PWM2, // GPIO12 cold/warm light + 0, 0, + GPIO_PWM1, // GPIO15 light intensity + 0, 0 }, - { "Neo Coolcam", // NEO_COOLCAM - Neo Coolcam (ESP8266) - // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN - 0, 0, 0, 0, - GPIO_LED1_INV, // GPIO04 Red Led (0 = On, 1 = Off) - Link and Power status - 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) - GPIO_KEY1, // GPIO13 Button - 0, 0, 0, 0 + { // NEO_COOLCAM - Neo Coolcam (ESP8266) + // https://www.banggood.com/NEO-COOLCAM-WiFi-Mini-Smart-Plug-APP-Remote-Control-Timing-Smart-Socket-EU-Plug-p-1288562.html?cur_warehouse=CN + 0, 0, 0, 0, + GPIO_LED1_INV, // GPIO04 Red Led (0 = On, 1 = Off) - Link and Power status + 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Red Led and Relay (0 = Off, 1 = On) + GPIO_KEY1, // GPIO13 Button + 0, 0, 0, 0 }, - { "ESP Switch", // ESP_SWITCH - Michael Haustein 4 channel wall switch (ESP07 = ESP8266) - // Use rules for further actions like - rule on power1#state do publish cmnd/other_device/power %value% endon - GPIO_KEY2, // GPIO00 Button 2 - GPIO_USER, // GPIO01 Serial RXD and Optional sensor - GPIO_REL3_INV, // GPIO02 Yellow Led 3 (0 = On, 1 = Off) - GPIO_USER, // GPIO03 Serial TXD and Optional sensor - GPIO_KEY1, // GPIO04 Button 1 - GPIO_REL2_INV, // GPIO05 Red Led 2 (0 = On, 1 = Off) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL4_INV, // GPIO12 Blue Led 4 (0 = On, 1 = Off) - GPIO_KEY4, // GPIO13 Button 4 - GPIO_KEY3, // GPIO14 Button 3 - GPIO_LED1, // GPIO15 Optional sensor - GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) - 0 + { // ESP_SWITCH - Michael Haustein 4 channel wall switch (ESP07 = ESP8266) + // Use rules for further actions like - rule on power1#state do publish cmnd/other_device/power %value% endon + GPIO_KEY2, // GPIO00 Button 2 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + GPIO_REL3_INV, // GPIO02 Yellow Led 3 (0 = On, 1 = Off) + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_KEY1, // GPIO04 Button 1 + GPIO_REL2_INV, // GPIO05 Red Led 2 (0 = On, 1 = Off) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL4_INV, // GPIO12 Blue Led 4 (0 = On, 1 = Off) + GPIO_KEY4, // GPIO13 Button 4 + GPIO_KEY3, // GPIO14 Button 3 + GPIO_LED1, // GPIO15 Optional sensor + GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) + 0 }, - { "OBI Socket", // OBI - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 - GPIO_USER, // GPIO00 - GPIO_USER, // GPIO01 Serial RXD - 0, - GPIO_USER, // GPIO03 Serial TXD - GPIO_LED1, // GPIO04 Blue LED - Link and Power status - GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_LED3, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) - GPIO_USER, // GPIO13 - GPIO_KEY1, // GPIO14 Button - 0, - GPIO_USER, // GPIO16 - ADC0_USER // ADC0 A0 Analog input + { // OBI - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 + GPIO_USER, // GPIO00 + GPIO_USER, // GPIO01 Serial RXD + 0, + GPIO_USER, // GPIO03 Serial TXD + GPIO_LED1, // GPIO04 Blue LED - Link and Power status + GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED3, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_USER, // GPIO13 + GPIO_KEY1, // GPIO14 Button + 0, + GPIO_USER, // GPIO16 + ADC0_USER // ADC0 A0 Analog input }, - { "Teckin", // TECKIN - https://www.amazon.de/gp/product/B07D5V139R - 0, - GPIO_KEY1, // GPIO01 Serial TXD and Button - 0, - GPIO_LED1_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status - GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_LEDLNK_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status - GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) - 0, 0, 0 + { // TECKIN - https://www.amazon.de/gp/product/B07D5V139R + 0, + GPIO_KEY1, // GPIO01 Serial TXD and Button + 0, + GPIO_LED1_INV, // GPIO03 Serial RXD and Red Led (0 = On, 1 = Off) - Power status + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LEDLNK_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link status + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) + 0, 0, 0 }, - { "AplicWDP303075", // APLIC_WDP303075 - Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) - // https://www.amazon.de/dp/B07CNWVNJ2 - 0, 0, 0, - GPIO_KEY1, // GPIO03 Button - GPIO_HLW_CF, // GPIO04 HLW8012 CF power - GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) - GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) - Link and Power status - GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) - 0, 0, 0 + { // APLIC_WDP303075 - Aplic WDP 303075 (ESP8285 - HLW8012 Energy Monitoring) + // https://www.amazon.de/dp/B07CNWVNJ2 + 0, 0, 0, + GPIO_KEY1, // GPIO03 Button + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) - Link and Power status + GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) + 0, 0, 0 }, - { "Tuya MCU", // TUYA_DIMMER - 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 - GPIO_USER, - GPIO_USER, // GPIO03 MCU serial control - GPIO_USER, - GPIO_USER, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, - GPIO_USER, - GPIO_USER, // GPIO14 Green Led - GPIO_USER, - GPIO_USER, - 0 + { // TUYA_DIMMER - 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 + GPIO_USER, + GPIO_USER, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_USER, + GPIO_USER, // GPIO14 Green Led + GPIO_USER, + GPIO_USER, + 0 }, - { "Gosund SP1 v23", // GOSUND - https://www.amazon.de/gp/product/B0777BWS1P - 0, - GPIO_LEDLNK_INV, // GPIO01 Serial RXD and LED1 (blue) inv - Link status - 0, - GPIO_KEY1, // GPIO03 Serial TXD and Button - GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_LED1_INV, // GPIO13 LED2 (red) inv - Power status - GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) - 0, 0, 0 + { // GOSUND - https://www.amazon.de/gp/product/B0777BWS1P + 0, + GPIO_LEDLNK_INV, // GPIO01 Serial RXD and LED1 (blue) inv - Link status + 0, + GPIO_KEY1, // GPIO03 Serial TXD and Button + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 LED2 (red) inv - Power status + GPIO_REL1, // GPIO14 Relay (0 = Off, 1 = On) + 0, 0, 0 }, - { "ARMTR Dimmer", // ARMTRONIX_DIMMERS - ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ - // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ - GPIO_USER, - GPIO_TXD, // GPIO01 MCU serial control - GPIO_USER, - GPIO_RXD, // GPIO03 MCU serial control - GPIO_USER, - GPIO_USER, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, - GPIO_USER, - GPIO_USER, - GPIO_USER, - GPIO_USER, - 0 + { // ARMTRONIX_DIMMERS - ARMTRONIX Dimmer, one or two channel (ESP8266 w/ separate MCU dimmer) + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-two-triac-board/ + // https://www.tindie.com/products/Armtronix/wifi-ac-dimmer-esp8266-one-triac-board-alexaecho/ + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, + GPIO_USER, + 0 }, - { "SK03 Outdoor", // SK03_TUYA - Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, - GPIO_HLW_CF, // GPIO04 HLW8012 CF power - GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) - GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Power status - GPIO_LEDLNK_INV, // GPIO14 Blue Led (0 = On, 1 = Off) - Link status - GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) - 0, 0 + { // SK03_TUYA - Outdoor smart plug with power monitoring HLW8012 chip - https://www.amazon.com/gp/product/B07CG7MBPV + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 CF Sel output (0 = Voltage) + GPIO_LED1_INV, // GPIO13 Red Led (0 = On, 1 = Off) - Power status + GPIO_LEDLNK_INV, // GPIO14 Blue Led (0 = On, 1 = Off) - Link status + GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) + 0, 0 }, - { "PS-16-DZ", // PS_16_DZ - PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) - // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html - GPIO_USER, - GPIO_TXD, // GPIO01 MCU serial control - GPIO_USER, - GPIO_RXD, // GPIO03 MCU serial control - GPIO_USER, - GPIO_USER, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, - GPIO_LED1, // GPIO13 WiFi LED - Link and Power status - GPIO_USER, - GPIO_USER, - GPIO_USER, - 0 + { // PS_16_DZ - PS-16-DZ Dimmer (ESP8266 w/ separate Nuvoton MCU dimmer) + // https://www.aliexpress.com/item/SM-Smart-WIFI-Wall-Dimmer-Light-Switch-US-Ewelink-APP-Remote-Control-Wi-Fi-Wirele-Work/32871151902.html + GPIO_USER, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, + GPIO_LED1, // GPIO13 WiFi LED - Link and Power status + GPIO_USER, + GPIO_USER, + GPIO_USER, + 0 }, - { "Teckin US", // TECKIN_US - Teckin SP20 US with Energy Monitoring - // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B - // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN - GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status - 0, - GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status - 0, - GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) - GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_KEY1, // GPIO13 Button - GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage - 0, 0, 0 + { // TECKIN_US - Teckin SP20 US with Energy Monitoring + // https://www.amazon.com/Outlet-Compatible-Monitoring-Function-Required/dp/B079Q5W22B + // https://www.amazon.com/Outlet-ZOOZEE-Monitoring-Function-Compatible/dp/B07J2LR5KN + GPIO_LED1_INV, // GPIO00 Red Led (1 = On, 0 = Off) - Power status + 0, + GPIO_LEDLNK_INV, // GPIO02 Blue Led (1 = On, 0 = Off) - Link status + 0, + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_HJL_CF, // GPIO05 BL0937 or HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 BL0937 or HJL-01 CF1 current / voltage + 0, 0, 0 }, - { "Manzoku strip", // MANZOKU_EU_4 - "MANZOKU" labeled power strip, EU version - // https://www.amazon.de/Steckdosenleiste-AOFO-Mehrfachsteckdose-Überspannungsschutz-Sprachsteuerung/dp/B07GBSD11P/ - // https://www.amazon.de/Steckdosenleiste-Geekbes-USB-Anschluss-Kompatibel-gesteuert/dp/B078W23BW9/ - 0, // GPIO00 - 0, // GPIO01 Serial RXD - 0, - GPIO_KEY1, // GPIO03 Serial TXD + Button - GPIO_REL2, // GPIO04 Relay 2 - GPIO_REL1, // GPIO05 Relay 1 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL3, // GPIO12 Relay 3 - GPIO_REL4, // GPIO13 Relay 4 - GPIO_USER, // GPIO14 - 0, - GPIO_USER, // GPIO16 - 0 + { // MANZOKU_EU_4 - "MANZOKU" labeled power strip, EU version + // https://www.amazon.de/Steckdosenleiste-AOFO-Mehrfachsteckdose-Überspannungsschutz-Sprachsteuerung/dp/B07GBSD11P/ + // https://www.amazon.de/Steckdosenleiste-Geekbes-USB-Anschluss-Kompatibel-gesteuert/dp/B078W23BW9/ + 0, // GPIO00 + 0, // GPIO01 Serial RXD + 0, + GPIO_KEY1, // GPIO03 Serial TXD + Button + GPIO_REL2, // GPIO04 Relay 2 + GPIO_REL1, // GPIO05 Relay 1 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL3, // GPIO12 Relay 3 + GPIO_REL4, // GPIO13 Relay 4 + GPIO_USER, // GPIO14 + 0, + GPIO_USER, // GPIO16 + 0 }, - { "OBI Socket 2", // OBI2 - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673 - 0, // GPIO00 - 0, // GPIO01 Serial RXD - 0, - 0, // GPIO03 Serial TXD - GPIO_REL1, // GPIO04 Relay 1 - GPIO_KEY1, // GPIO05 Button - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_LEDLNK_INV, // GPIO12 Green LED - Link status - GPIO_LED1, // GPIO13 Red LED - Power status - 0, 0, 0, 0 + { // OBI2 - OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko-2-stueck-weiss/p/4077673 + 0, // GPIO00 + 0, // GPIO01 Serial RXD + 0, + 0, // GPIO03 Serial TXD + GPIO_REL1, // GPIO04 Relay 1 + GPIO_KEY1, // GPIO05 Button + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LEDLNK_INV, // GPIO12 Green LED - Link status + GPIO_LED1, // GPIO13 Red LED - Power status + 0, 0, 0, 0 }, - { "YTF IR Bridge", // YTF_IR_BRIDGE - https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html - GPIO_USER, // GPIO00 - GPIO_USER, // GPIO01 Serial RXD - GPIO_USER, // GPIO02 - GPIO_USER, // GPIO03 Serial TXD - GPIO_LED1_INV, // GPIO04 Blue Led - Link status - GPIO_IRRECV, // GPIO05 IR Receiver - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, // GPIO12 - GPIO_KEY1, // GPIO13 Button - GPIO_IRSEND, // GPIO14 IR Transmitter - 0, 0, 0 + { // YTF_IR_BRIDGE - https://www.aliexpress.com/item/Tuya-universal-Smart-IR-Hub-remote-control-Voice-Control-AC-TV-Work-With-Alexa-Google-Home/32951202513.html + GPIO_USER, // GPIO00 + GPIO_USER, // GPIO01 Serial RXD + GPIO_USER, // GPIO02 + GPIO_USER, // GPIO03 Serial TXD + GPIO_LED1_INV, // GPIO04 Blue Led - Link status + GPIO_IRRECV, // GPIO05 IR Receiver + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, // GPIO12 + GPIO_KEY1, // GPIO13 Button + GPIO_IRSEND, // GPIO14 IR Transmitter + 0, 0, 0 }, - { "Digoo DG-SP202", // DIGOO - Digoo DG-SP202 - // https://www.banggood.com/DIGOO-DG-SP202-Dual-EU-Plug-Smart-WIFI-Socket-Individual-Controllable-Energy-Monitor-Remote-Control-Timing-Smart-Home-Outlet-let-p-1375323.html - GPIO_KEY1, // GPIO00 Button1 - 0, // GPIO01 Serial RXD - 0, // GPIO02 - 0, // GPIO03 Serial TXD - GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) - GPIO_LED1, // GPIO13 Blue Leds - Link Status - GPIO_REL2, // GPIO14 Relay2 (0 = Off, 1 = On) and Red Led - GPIO_REL1, // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led - GPIO_KEY2_NP, // GPIO16 Button2, externally pulled up - 0 + { // DIGOO - Digoo DG-SP202 + // https://www.banggood.com/DIGOO-DG-SP202-Dual-EU-Plug-Smart-WIFI-Socket-Individual-Controllable-Energy-Monitor-Remote-Control-Timing-Smart-Home-Outlet-let-p-1375323.html + GPIO_KEY1, // GPIO00 Button1 + 0, // GPIO01 Serial RXD + 0, // GPIO02 + 0, // GPIO03 Serial TXD + GPIO_HJL_CF, // GPIO04 BL0937 or HJL-01 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 or HJL-01 CF1 current / voltage + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 or HJL-01 Sel output (0 = Voltage) + GPIO_LED1, // GPIO13 Blue Leds - Link Status + GPIO_REL2, // GPIO14 Relay2 (0 = Off, 1 = On) and Red Led + GPIO_REL1, // GPIO15 Relay1 (0 = Off, 1 = On) and Red Led + GPIO_KEY2_NP, // GPIO16 Button2, externally pulled up + 0 }, - { "KA10", // KA10 - SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y - 0, // GPIO00 - GPIO_LEDLNK_INV, // GPIO01 Blue LED - Link status - 0, // GPIO02 - GPIO_KEY1, // GPIO03 Button - GPIO_HJL_CF, // GPIO04 BL0937 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) - GPIO_LED1, // GPIO13 Red LED - Power status - GPIO_REL1, // GPIO14 Relay 1 - 0, 0, 0 + { // KA10 - SMANERGY KA10 (ESP8285 - BL0937 Energy Monitoring) - https://www.amazon.es/dp/B07MBTCH2Y + 0, // GPIO00 + GPIO_LEDLNK_INV, // GPIO01 Blue LED - Link status + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Red LED - Power status + GPIO_REL1, // GPIO14 Relay 1 + 0, 0, 0 }, - { "Luminea ZX2820", // ZX2820 - GPIO_KEY1, // GPIO00 Button - 0, 0, 0, - GPIO_HLW_CF, // GPIO04 HLW8012 CF power - GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 HLW8012 SEL (0 = Voltage) - GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status - GPIO_REL1, // GPIO14 Relay - 0, 0, 0 + { // ZX2820 + GPIO_KEY1, // GPIO00 Button + 0, 0, 0, + GPIO_HLW_CF, // GPIO04 HLW8012 CF power + GPIO_NRG_CF1, // GPIO05 HLW8012 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 HLW8012 SEL (0 = Voltage) + GPIO_LED1_INV, // GPIO13 Green Led - Link and Power status + GPIO_REL1, // GPIO14 Relay + 0, 0, 0 }, - { "Mi Desk Lamp", // MI_DESK_LAMP - Mi LED Desk Lamp - https://www.mi.com/global/smartlamp/ - 0, 0, - GPIO_KEY1, // GPIO02 Button - 0, - GPIO_PWM1, // GPIO04 Cold White - GPIO_PWM2, // GPIO05 Warm White - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_ROT1A, // GPIO12 Rotary switch A pin - GPIO_ROT1B, // GPIO13 Rotary switch B pin - 0, 0, 0, 0 + { // MI_DESK_LAMP - Mi LED Desk Lamp - https://www.mi.com/global/smartlamp/ + 0, 0, + GPIO_KEY1, // GPIO02 Button + 0, + GPIO_PWM1, // GPIO04 Cold White + GPIO_PWM2, // GPIO05 Warm White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_ROT1A, // GPIO12 Rotary switch A pin + GPIO_ROT1B, // GPIO13 Rotary switch B pin + 0, 0, 0, 0 }, - { "SP10", // SP10 - Tuya SP10 (BL0937 Energy Monitoring) - // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html - 0, // GPIO00 - GPIO_PWM1, // GPIO01 Nightlight - 0, // GPIO02 - GPIO_KEY1, // GPIO03 Button - GPIO_HJL_CF, // GPIO04 BL0937 CF power - GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) - GPIO_LED1, // GPIO13 Blue LED - Link status - GPIO_REL1, // GPIO14 Relay and red LED - 0, 0, 0 + { // SP10 - Tuya SP10 (BL0937 Energy Monitoring) + // https://www.aliexpress.com/item/Smart-Mini-WiFi-Plug-Outlet-Switch-Work-With-ForEcho-Alexa-Google-Home-Remote-EU-Smart-Socket/32963670423.html + 0, // GPIO00 + GPIO_PWM1, // GPIO01 Nightlight + 0, // GPIO02 + GPIO_KEY1, // GPIO03 Button + GPIO_HJL_CF, // GPIO04 BL0937 CF power + GPIO_NRG_CF1, // GPIO05 BL0937 CF1 voltage / current + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_NRG_SEL_INV, // GPIO12 BL0937 Sel output (1 = Voltage) + GPIO_LED1, // GPIO13 Blue LED - Link status + GPIO_REL1, // GPIO14 Relay and red LED + 0, 0, 0 }, - { "WAGA CHCZ02MB", // WAGA - WAGA life CHCZ02MB (HJL-01 Energy Monitoring) - // https://www.ebay.com/itm/332595697006 - GPIO_LED1_INV, // GPIO00 Red LED - 0, // GPIO01 Serial RXD - 0, // GPIO02 - GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) - 0, // GPIO04 - GPIO_HJL_CF, // GPIO05 HJL-01 CF power - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_REL1, // GPIO12 Relay - GPIO_KEY1, // GPIO13 Button - GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current - GPIO_LEDLNK_INV, // GPIO15 Blue LED - Link status - 0, 0 + { // WAGA - WAGA life CHCZ02MB (HJL-01 Energy Monitoring) + // https://www.ebay.com/itm/332595697006 + GPIO_LED1_INV, // GPIO00 Red LED + 0, // GPIO01 Serial RXD + 0, // GPIO02 + GPIO_NRG_SEL_INV, // GPIO03 HJL-01 Sel output (1 = Voltage) + 0, // GPIO04 + GPIO_HJL_CF, // GPIO05 HJL-01 CF power + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_REL1, // GPIO12 Relay + GPIO_KEY1, // GPIO13 Button + GPIO_NRG_CF1, // GPIO14 HJL-01 CF1 voltage / current + GPIO_LEDLNK_INV, // GPIO15 Blue LED - Link status + 0, 0 }, - { "SYF05", // SYF05 - Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 - // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL - // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n - // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html - // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 - GPIO_USER, // GPIO00 N.C. - 0, // GPIO01 Serial RXD - GPIO_USER, // GPIO02 N.C. - 0, // GPIO03 Serial TXD - GPIO_SM16716_CLK, // GPIO04 SM16716 Clock - GPIO_PWM1, // GPIO05 White - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 Alt. White on some devices - GPIO_USER, // GPIO13 SM16716 Enable on some devices - GPIO_SM16716_DAT, // GPIO14 SM16716 Data - 0, // GPIO15 wired to GND - GPIO_USER, // GPIO16 N.C. - ADC0_USER // ADC0 A0 Analog input + { // SYF05 - Sunyesmart SYF05 (a.k.a. Fcmila) = TYWE3S + SM16726 + // Also works with Merkury 904 RGBW Bulbs with 13 set to GPIO_SM16716_SEL + // https://www.flipkart.com/fc-mila-bxav-xs-ad-smart-bulb/p/itmf85zgs45fzr7n + // https://docs.tuya.com/en/hardware/WiFi-module/wifi-e3s-module.html + // http://www.datasheet-pdf.com/PDF/SM16716-Datasheet-Sunmoon-932771 + GPIO_USER, // GPIO00 N.C. + 0, // GPIO01 Serial RXD + GPIO_USER, // GPIO02 N.C. + 0, // GPIO03 Serial TXD + GPIO_SM16716_CLK, // GPIO04 SM16716 Clock + GPIO_PWM1, // GPIO05 White + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 Alt. White on some devices + GPIO_USER, // GPIO13 SM16716 Enable on some devices + GPIO_SM16716_DAT, // GPIO14 SM16716 Data + 0, // GPIO15 wired to GND + GPIO_USER, // GPIO16 N.C. + ADC0_USER // ADC0 A0 Analog input }, - { "Sonoff L1", // SONOFF_L1 - Sonoff L1 RGB LED controller (ESP8266 w/ separate Nuvoton MCU) - 0, - GPIO_TXD, // GPIO01 MCU serial control - 0, - GPIO_RXD, // GPIO03 MCU serial control - 0, 0, - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - 0, - GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status - 0, 0, 0, 0 + { // SONOFF_L1 - Sonoff L1 RGB LED controller (ESP8266 w/ separate Nuvoton MCU) + 0, + GPIO_TXD, // GPIO01 MCU serial control + 0, + GPIO_RXD, // GPIO03 MCU serial control + 0, 0, + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + 0, + GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status + 0, 0, 0, 0 }, - { "Sonoff iFan03", // SONOFF_IFAN03 - Sonoff iFan03 (ESP8285) - GPIO_KEY1, // GPIO00 WIFI_KEY0 Button 1 - GPIO_TXD, // GPIO01 ESP_TXD Serial RXD connection to P0.5 of RF microcontroller - 0, // GPIO02 ESP_LOG - GPIO_RXD, // GPIO03 ESP_RXD Serial TXD connection to P0.4 of RF microcontroller - 0, // GPIO04 DEBUG_RX - 0, // GPIO05 DEBUG_TX - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - GPIO_REL1_INV, // GPIO09 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light - GPIO_BUZZER_INV, // GPIO10 WIFI_O4 Buzzer (0 = Off, 1 = On) - // GPIO11 (SD_CMD Flash) - GPIO_REL3, // GPIO12 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan - GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status - GPIO_REL2, // GPIO14 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan - GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan - 0, 0 + { // SONOFF_IFAN03 - Sonoff iFan03 (ESP8285) + GPIO_KEY1, // GPIO00 WIFI_KEY0 Button 1 + GPIO_TXD, // GPIO01 ESP_TXD Serial RXD connection to P0.5 of RF microcontroller + 0, // GPIO02 ESP_LOG + GPIO_RXD, // GPIO03 ESP_RXD Serial TXD connection to P0.4 of RF microcontroller + 0, // GPIO04 DEBUG_RX + 0, // GPIO05 DEBUG_TX + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + GPIO_REL1_INV, // GPIO09 WIFI_O0 Relay 1 (0 = Off, 1 = On) controlling the light + GPIO_BUZZER_INV, // GPIO10 WIFI_O4 Buzzer (0 = Off, 1 = On) + // GPIO11 (SD_CMD Flash) + GPIO_REL3, // GPIO12 WIFI_O2 Relay 3 (0 = Off, 1 = On) controlling the fan + GPIO_LED1_INV, // GPIO13 WIFI_CHK Blue Led on PCA (0 = On, 1 = Off) - Link and Power status + GPIO_REL2, // GPIO14 WIFI_O1 Relay 2 (0 = Off, 1 = On) controlling the fan + GPIO_REL4, // GPIO15 WIFI_O3 Relay 4 (0 = Off, 1 = On) controlling the fan + 0, 0 }, - { "EXS Dimmer", // EXS_DIMMER - EX-Store WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) - // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A - // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten - 0, - GPIO_TXD, // GPIO01 MCU serial control - GPIO_LEDLNK, // GPIO02 LED Link - GPIO_RXD, // GPIO03 MCU serial control - GPIO_USER, // GPIO04 - GPIO_USER, // GPIO05 - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_USER, // GPIO12 - GPIO_EXS_ENABLE, // GPIO13 EXS MCU Enable - GPIO_USER, // GPIO14 - 0, // GPIO15 - 0, 0 + { // EXS_DIMMER - EX-Store WiFi Dimmer v4, two channel (ESP8266 w/ separate MCU dimmer) + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A + // https://ex-store.de/2-Kanal-RS232-WiFi-WLan-Dimmer-Modul-V4-fuer-Unterputzmontage-230V-3A-ESP8266-V12-Stift-und-Buchsenleisten + 0, + GPIO_TXD, // GPIO01 MCU serial control + GPIO_LEDLNK, // GPIO02 LED Link + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, // GPIO04 + GPIO_USER, // GPIO05 + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_USER, // GPIO12 + GPIO_EXS_ENABLE, // GPIO13 EXS MCU Enable + GPIO_USER, // GPIO14 + 0, // GPIO15 + 0, 0 }, - { "PWM Dimmer", // PWM_DIMMER - Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM - // dimmer switches. The brightness of the load for these dimmers is - // controlled by a PWM GPIO pin. There are typically power, up & down - // buttons and 4 LED's. Examples are: - // https://www.amazon.com/dp/B07FXYSVR1 - // https://www.amazon.com/dp/B07V26Q3VD - // https://www.amazon.com/dp/B07K67D43J - // https://www.amazon.com/dp/B07TTGFWFM - GPIO_KEY3, // GPIO00 Up button - GPIO_KEY2, // GPIO01 Down button - 0, // GPIO02 - GPIO_LED4_INV, // GPIO03 Level 5 LED - GPIO_LEDLNK_INV, // GPIO04 LED Link - GPIO_LED3_INV, // GPIO05 Level 4 LED - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) - 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) - // GPIO11 (SD_CMD Flash) - GPIO_LED2_INV, // GPIO12 Level 3 LED - GPIO_PWM1, // GPIO13 Dimmer PWM - GPIO_LED1_INV, // GPIO12 Level 2 LED - GPIO_KEY1_INV, // GPIO15 Power button - GPIO_REL1_INV, // GPIO16 Power relay/Level 1 LED - 0 + { // PWM_DIMMER - Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM + // dimmer switches. The brightness of the load for these dimmers is + // controlled by a PWM GPIO pin. There are typically power, up & down + // buttons and 4 LED's. Examples are: + // https://www.amazon.com/dp/B07FXYSVR1 + // https://www.amazon.com/dp/B07V26Q3VD + // https://www.amazon.com/dp/B07K67D43J + // https://www.amazon.com/dp/B07TTGFWFM + GPIO_KEY3, // GPIO00 Up button + GPIO_KEY2, // GPIO01 Down button + 0, // GPIO02 + GPIO_LED4_INV, // GPIO03 Level 5 LED + GPIO_LEDLNK_INV, // GPIO04 LED Link + GPIO_LED3_INV, // GPIO05 Level 4 LED + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED2_INV, // GPIO12 Level 3 LED + GPIO_PWM1, // GPIO13 Dimmer PWM + GPIO_LED1_INV, // GPIO12 Level 2 LED + GPIO_KEY1_INV, // GPIO15 Power button + GPIO_REL1_INV, // GPIO16 Power relay/Level 1 LED + 0 }, - { "Sonoff D1", // SONOFF_D1 - Sonoff D1 RF Dimmer 433 (ESP8285) - GPIO_USER, // GPIO00 Pad - GPIO_TXD, // GPIO01 D1 control - 0, // GPIO02 - GPIO_RXD, // GPIO03 D1 control - 0, // GPIO04 DEBUG_RX - 0, // GPIO05 DEBUG_TX - // GPIO06 (SD_CLK Flash) - // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) - // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) - 0, // GPIO09 - 0, // GPIO10 - // GPIO11 (SD_CMD Flash) - 0, // GPIO12 - GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status - 0, 0, 0, 0 + { // SONOFF_D1 - Sonoff D1 RF Dimmer 433 (ESP8285) + GPIO_USER, // GPIO00 Pad + GPIO_TXD, // GPIO01 D1 control + 0, // GPIO02 + GPIO_RXD, // GPIO03 D1 control + 0, // GPIO04 DEBUG_RX + 0, // GPIO05 DEBUG_TX + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + 0, // GPIO12 + GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status + 0, 0, 0, 0 } }; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index f48ce9431..c6cf97580 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1494,7 +1494,7 @@ void HandleTemplateConfiguration(void) void TemplateSaveSettings(void) { - char tmp[sizeof(Settings.user_template.name)]; // WebGetArg NAME and GPIO/BASE/FLAG byte value + char tmp[sizeof(Settings.user_template_name)]; // WebGetArg NAME and GPIO/BASE/FLAG byte value char webindex[5]; // WebGetArg name char svalue[128]; // Template command string From 397fea3bb2d65f501c592af53f8dd22f19943af6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Mar 2020 15:17:54 +0200 Subject: [PATCH 30/56] Add Console command history Add Console command history (#8015) --- tasmota/xdrv_01_webserver.ino | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index c6cf97580..e4336b736 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -31,7 +31,7 @@ #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by WifiManager web GUI #endif -const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size = MESSZ) +const uint16_t CHUNKED_BUFFER_SIZE = (MESSZ / 2) - 100; // Chunk buffer size (should be smaller than half mqtt_data size = MESSZ) const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds #define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds @@ -184,7 +184,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "clearTimeout(lt);" "t=eb('t1');" "if(p==1){" - "c=eb('c1');" + "c=eb('c1');" // Console command id "o='&c1='+encodeURIComponent(c.value);" "c.value='';" "t.scrollTop=99999;" @@ -211,6 +211,16 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "lt=setTimeout(l,%d);" "return false;" "}" + + // Console command history - part 2 + "var mh=20,hc=[],cn=0;" + "function cH(a){" + "var b=qs('#c1'),c=a.keyCode;" // c1 = Console command id + "38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // Arrow Up + "40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // Arrow Down + "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter + "}" + "wl(l);"; const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM = @@ -329,6 +339,12 @@ const char HTTP_HEAD_LAST_SCRIPT[] PROGMEM = "}" "t++;" "}" + + // Console command history - part 1 + "if(qs('#c1')){" // c1 = Console command id + "qs('#c1').addEventListener('keydown',cH);" + "}" + "}" "wl(jd);" // Add name='' to any id='' in input,button,textarea,select ""; @@ -745,7 +761,7 @@ void _WSContentSend(const String& content) // Low level sendContent for a #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("WSContentSend")); #endif - DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d"), len); + DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d/%d"), len, sizeof(mqtt_data)); } void WSContentFlush(void) @@ -1735,7 +1751,7 @@ void HandleWifiConfiguration(void) //display networks in page for (uint32_t i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } // skip dups - int32_t rssi = WiFi.RSSI(indices[i]) + int32_t rssi = WiFi.RSSI(indices[i]); DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); int quality = WifiGetRssiAsQuality(rssi); From 257dd1879611a08090eaa2e3fe9d5bb464bf34a9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Mar 2020 15:35:58 +0200 Subject: [PATCH 31/56] Add console command history (#7483, #8015) Add console command history (#7483, #8015) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/xdrv_01_webserver.ino | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index da5dd225f..9e22461e2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -62,3 +62,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) +- Add console command history (#7483, #8015) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index fa969d778..1d9d2e919 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.2.0.2 20200328 - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) +- Add console command history (#7483, #8015) ### 8.2.0.1 20200321 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index e4336b736..308fd5ed9 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -213,12 +213,12 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "}" // Console command history - part 2 - "var mh=20,hc=[],cn=0;" + "var hc=[],cn=0;" // hc = History commands, cn = Number of history being shown "function cH(a){" "var b=qs('#c1'),c=a.keyCode;" // c1 = Console command id "38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // Arrow Up "40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // Arrow Down - "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter + "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter, 19 = Max number -1 of commands in history "}" "wl(l);"; From 61b97350daefe4581162994b38482d241f7ecfcd Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 29 Mar 2020 16:29:22 +0200 Subject: [PATCH 32/56] ed300L support --- tasmota/xdrv_10_scripter.ino | 15 ++++++++++----- tasmota/xsns_53_sml.ino | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 30ed26598..330512c9d 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1508,9 +1508,9 @@ chknext: lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); SCRIPT_SKIP_SPACES fvar=fvar1; - if ((*opp=='<' && fvar1' && fvar1>fvar2) || - (*opp=='=' && fvar1==fvar2)) + if ((*opp=='<' && fvar1' && fvar1>fvar2) || + (*opp=='=' && fvar1==fvar2)) { if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { float fvar3; @@ -1759,13 +1759,18 @@ chknext: float fvar3; lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); fvar=SML_SetBaud(fvar1,fvar3); - } else { + } else if (fvar2==1) { char str[SCRIPT_MAXSSIZE]; lp=GetStringResult(lp,OPER_EQU,str,0); fvar=SML_Write(fvar1,str); + } else { +#ifdef ED300L + fvar=SML_Status(fvar1); +#else + fvar=0; +#endif } lp++; - fvar=0; len=0; goto exit; } diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index 53e6fff25..c5f2d3cc2 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -901,6 +901,11 @@ uint8_t dchars[16]; } } +#ifdef ED300L +uint8_t sml_status[MAX_METERS]; +uint8_t g_mindex; +#endif + // skip sml entries uint8_t *skip_sml(uint8_t *cp,int16_t *res) { uint8_t len,len1,type; @@ -933,6 +938,14 @@ double dval; // scan for values // check status +#ifdef ED300L + unsigned char *cpx=cp-5; + // decode OBIS 0180 amd extract direction info + if (*cp==0x64 && *cpx==0 && *(cpx+1)==0x01 && *(cpx+2)==0x08 && *(cpx+3)==0) { + sml_status[g_mindex]=*(cp+3); + } +#endif + cp=skip_sml(cp,&result); // check time cp=skip_sml(cp,&result); @@ -941,6 +954,7 @@ double dval; // check scaler cp=skip_sml(cp,&result); scaler=result; + // get value type=*cp&0x70; len=*cp&0x0f; @@ -1033,6 +1047,15 @@ double dval; } else if (scaler==3) { dval*=1000; } + #ifdef ED300L + // decode current power OBIS 00 0F 07 00 + if (*cpx==0x00 && *(cpx+1)==0x0f && *(cpx+2)==0x07 && *(cpx+3)==0) { + if (sml_status[g_mindex]&0x20) { + // and invert sign on solar feed + dval*=-1; + } + } + #endif return dval; } @@ -1465,6 +1488,9 @@ void SML_Decode(uint8_t index) { if (found) { // matches, get value mp++; +#ifdef ED300L + g_mindex=mindex; +#endif if (*mp=='#') { // get string value mp++; @@ -2061,6 +2087,17 @@ uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { return 1; } +uint32_t SML_Status(uint32_t meter) { + if (meter<1 || meter>meters_used) return 0; + meter--; +#ifdef ED300L + return sml_status[meter]; +#else + return 0; +#endif +} + + uint32_t SML_Write(uint32_t meter,char *hstr) { if (meter<1 || meter>meters_used) return 0; meter--; From 4a2f3d87c5bd8e9ffc9369dccfdb8940ee3656ea Mon Sep 17 00:00:00 2001 From: to-scho Date: Sun, 29 Mar 2020 17:05:52 +0200 Subject: [PATCH 33/56] Enhanced counter debouncing New commands CounterDebounceLow and CounterDebounceHigh to allow individual debounce times for low and high pulse widths to discard non valid falling edges. These are checked before legacy CounterDebounce checks distance between to valid falling edges. Useful to have robust counter results when using e.g. an TCRT5000 optical sensor to count electromechanical "Ferraris" electricity meters. --- tasmota/settings.h | 4 ++- tasmota/xsns_01_counter.ino | 59 ++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index fa98a8ecf..7bbb0e5de 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -470,8 +470,10 @@ struct SYSCFG { uint8_t bri_preset_high; // F07 int8_t hum_comp; // F08 - uint8_t free_f09[179]; // F09 + uint8_t free_f09[175]; // F09 + uint16_t pulse_counter_debounce_low; // FB8 + uint16_t pulse_counter_debounce_high; // FBA uint32_t keeloq_master_msb; // FBC uint32_t keeloq_master_lsb; // FC0 uint32_t keeloq_serial; // FC4 diff --git a/tasmota/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino index 095693771..663d9413a 100644 --- a/tasmota/xsns_01_counter.ino +++ b/tasmota/xsns_01_counter.ino @@ -27,16 +27,20 @@ #define D_PRFX_COUNTER "Counter" #define D_CMND_COUNTERTYPE "Type" #define D_CMND_COUNTERDEBOUNCE "Debounce" +#define D_CMND_COUNTERDEBOUNCELOW "DebounceLow" +#define D_CMND_COUNTERDEBOUNCEHIGH "DebounceHigh" const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" // Prefix - "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; + "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE "|" D_CMND_COUNTERDEBOUNCELOW "|" D_CMND_COUNTERDEBOUNCEHIGH ; void (* const CounterCommand[])(void) PROGMEM = { - &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; + &CmndCounter, &CmndCounterType, &CmndCounterDebounce, &CmndCounterDebounceLow, &CmndCounterDebounceHigh }; struct COUNTER { uint32_t timer[MAX_COUNTERS]; // Last counter time in micro seconds + uint32_t timer_low_high[MAX_COUNTERS]; // Last low/high counter time in micro seconds uint8_t no_pullup = 0; // Counter input pullup flag (1 = No pullup) + uint8_t pin_state = 0; // LSB0..3 Last state of counter pin; LSB7==0 IRQ is FALLING, LSB7==1 IRQ is CHANGE bool any_counter = false; } Counter; @@ -51,7 +55,30 @@ void CounterUpdate4(void) ICACHE_RAM_ATTR; void CounterUpdate(uint8_t index) { uint32_t time = micros(); - uint32_t debounce_time = time - Counter.timer[index]; + uint32_t debounce_time; + + if (Counter.pin_state) { + // handle low and high debounce times when configured + if (digitalRead(pin[GPIO_CNTR1 +index]) == bitRead(Counter.pin_state, index)) { + // new pin state to be ignored because debounce time was not met during last IRQ + return; + } + debounce_time = time - Counter.timer_low_high[index]; + if bitRead(Counter.pin_state, index) { + // last valid pin state was high, current pin state is low + if (debounce_time <= Settings.pulse_counter_debounce_high * 1000) return; + } else { + // last valid pin state was low, current pin state is high + if (debounce_time <= Settings.pulse_counter_debounce_low * 1000) return; + } + // passed debounce check, save pin state and timing + Counter.timer_low_high[index] = time; + Counter.pin_state ^= (1< Settings.pulse_counter_debounce * 1000) { Counter.timer[index] = time; if (bitRead(Settings.pulse_counter_type, index)) { @@ -103,7 +130,13 @@ void CounterInit(void) if (pin[GPIO_CNTR1 +i] < 99) { Counter.any_counter = true; pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); - attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + if ((0 == Settings.pulse_counter_debounce_low) && (0 == Settings.pulse_counter_debounce_high)) { + Counter.pin_state = 0; + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + } else { + Counter.pin_state = 0x8f; + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], CHANGE); + } } } } @@ -213,6 +246,24 @@ void CmndCounterDebounce(void) ResponseCmndNumber(Settings.pulse_counter_debounce); } +void CmndCounterDebounceLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce_low = XdrvMailbox.payload; + CounterInit(); + } + ResponseCmndNumber(Settings.pulse_counter_debounce_low); +} + +void CmndCounterDebounceHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce_high = XdrvMailbox.payload; + CounterInit(); + } + ResponseCmndNumber(Settings.pulse_counter_debounce_high); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From d713468c0c4699dba64000e6b388495c38ccdcdb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 29 Mar 2020 17:41:31 +0200 Subject: [PATCH 34/56] Add support for longer template names Add support for longer template names --- RELEASENOTES.md | 3 ++- tasmota/CHANGELOG.md | 4 ++++ tasmota/settings.h | 4 +++- tasmota/settings.ino | 11 ++++++++++- tasmota/support.ino | 13 +++++++------ tasmota/support_command.ino | 2 +- tasmota/tasmota.h | 1 + tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 8 ++++---- 9 files changed, 33 insertions(+), 15 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9e22461e2..43a769512 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.2.0.2 +### Version 8.2.0.3 - Change HM-10 sensor type detection and add features (#7962) - Fix possible Relay toggle on (OTA) restart @@ -63,3 +63,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) - Add console command history (#7483, #8015) +- Add support for longer template names diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 1d9d2e919..0248d4ff7 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.2.0.3 20200329 + +- Add support for longer template names + ### 8.2.0.2 20200328 - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/settings.h b/tasmota/settings.h index fa98a8ecf..df15a0bfd 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -397,7 +397,9 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A uint8_t user_template_base; // 71F - char user_template_name[15]; // 720 15 bytes + + char user_template_name[15]; // 720 15 bytes - Backward compatibility since v8.2.0.3 + mytmplt user_template; // 72F 14 bytes uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 5ebf970d4..3bb58ff43 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -589,6 +589,12 @@ char* SettingsText(uint32_t index) * Config Save - Save parameters to Flash ONLY if any parameter has changed \*********************************************************************************************/ +void UpdateBackwardCompatibility(void) +{ + // Perform updates for backward compatibility + strlcpy(Settings.user_template_name, SettingsText(SET_TEMPLATE_NAME), sizeof(Settings.user_template_name)); +} + uint32_t GetSettingsAddress(void) { return settings_location * SPI_FLASH_SEC_SIZE; @@ -605,6 +611,7 @@ void SettingsSave(uint8_t rotate) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) */ #ifndef FIRMWARE_MINIMAL + UpdateBackwardCompatibility(); 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; @@ -1394,7 +1401,6 @@ void SettingsDelta(void) Settings.mqtt_port = Settings.ex_mqtt_port; // 20A -> EFC memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE } - if (Settings.version < 0x08000000) { char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); // Was ota_url char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); @@ -1466,6 +1472,9 @@ void SettingsDelta(void) SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]); } + if (Settings.version < 0x08020003) { + SettingsUpdateText(SET_TEMPLATE_NAME, Settings.user_template_name); + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support.ino b/tasmota/support.ino index 458a8efd3..81cb1b002 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1098,9 +1098,9 @@ bool ValidModule(uint32_t index) String AnyModuleName(uint32_t index) { if (USER_MODULE == index) { - return String(Settings.user_template_name); + return String(SettingsText(SET_TEMPLATE_NAME)); } else { - char name[15]; + char name[TOPSZ]; return String(GetTextIndexed(name, sizeof(name), index, kModuleNames)); } } @@ -1154,7 +1154,8 @@ void ModuleDefault(uint32_t module) { if (USER_MODULE == module) { module = WEMOS; } // Generic Settings.user_template_base = module; - GetTextIndexed(Settings.user_template_name, sizeof(Settings.user_template_name), module, kModuleNames); + char name[TOPSZ]; + SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames)); memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); } @@ -1263,14 +1264,14 @@ bool JsonTemplate(const char* dataBuf) if (strlen(dataBuf) < 9) { return false; } // Workaround exception if empty JSON like {} - Needs checks - StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/ + StaticJsonBuffer<400> jb; // 331 from https://arduinojson.org/v5/assistant/ JsonObject& obj = jb.parseObject(dataBuf); if (!obj.success()) { return false; } // All parameters are optional allowing for partial changes const char* name = obj[D_JSON_NAME]; if (name != nullptr) { - strlcpy(Settings.user_template_name, name, sizeof(Settings.user_template_name)); + SettingsUpdateText(SET_TEMPLATE_NAME, name); } if (obj[D_JSON_GPIO].success()) { for (uint32_t i = 0; i < sizeof(mycfgio); i++) { @@ -1291,7 +1292,7 @@ bool JsonTemplate(const char* dataBuf) void TemplateJson(void) { - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template_name); + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME)); for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 36e5c08fd..64fd45997 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1064,7 +1064,7 @@ void CmndTemplate(void) if (Settings.module != USER_MODULE) { ModuleDefault(Settings.module); } - snprintf_P(Settings.user_template_name, sizeof(Settings.user_template_name), PSTR("Merged")); + SettingsUpdateText(SET_TEMPLATE_NAME, "Merged"); uint32_t j = 0; for (uint32_t i = 0; i < sizeof(mycfgio); i++) { if (6 == i) { j = 9; } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 033b8d783..48a853891 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -302,6 +302,7 @@ enum SettingsTextIndex { SET_OTAURL, SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, SET_MQTT_GRP_TOPIC2, SET_MQTT_GRP_TOPIC3, SET_MQTT_GRP_TOPIC4, + SET_TEMPLATE_NAME, SET_MAX }; enum DeviceGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYP_REUPDATE }; diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 47879d1fe..3b8314f65 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08020002; +const uint32_t VERSION = 0x08020003; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 308fd5ed9..80c4bf417 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1510,9 +1510,9 @@ void HandleTemplateConfiguration(void) void TemplateSaveSettings(void) { - char tmp[sizeof(Settings.user_template_name)]; // WebGetArg NAME and GPIO/BASE/FLAG byte value + char tmp[TOPSZ]; // WebGetArg NAME and GPIO/BASE/FLAG byte value char webindex[5]; // WebGetArg name - char svalue[128]; // Template command string + char svalue[200]; // Template command string WebGetArg("s1", tmp, sizeof(tmp)); // NAME snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); @@ -1528,11 +1528,11 @@ void TemplateSaveSettings(void) j++; } - WebGetArg("g17", tmp, sizeof(tmp)); // FLAG - ADC0 + WebGetArg("g17", tmp, sizeof(tmp)); // FLAG - ADC0 uint32_t flag = atoi(tmp); for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = WebServer->hasArg(webindex) << i +4; // FLAG + uint32_t state = WebServer->hasArg(webindex) << i +4; // FLAG flag += state; } WebGetArg("g99", tmp, sizeof(tmp)); // BASE From dd9f7920dec84f35c969b45fdefdc2cc26b7ab03 Mon Sep 17 00:00:00 2001 From: blakadder Date: Sun, 29 Mar 2020 23:28:41 +0200 Subject: [PATCH 35/56] changed links to new docs architecture --- .github/ISSUE_TEMPLATE/Bug_report.md | 4 ++-- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/issue-close-app.yml | 2 +- API.md | 2 +- CONTRIBUTING.md | 2 +- README.md | 12 ++++++------ RELEASENOTES.md | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 19c9bd00d..993c31ea3 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -13,7 +13,7 @@ Please DO NOT OPEN AN ISSUE: - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue - - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://tasmota.github.io/docs/#/help/FAQ) and [Troubleshooting](https://tasmota.github.io/docs/#/help/Troubleshooting) + - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://tasmota.github.io/docs/FAQ) and [Troubleshooting](https://tasmota.github.io/docs/Troubleshooting) Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. @@ -29,7 +29,7 @@ _Make sure your have performed every step and checked the applicable boxes befor - [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues) -- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/#/help/FAQ) +- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/FAQ) - [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4) - [ ] Device used (e.g., Sonoff Basic): _____ diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 9c78f2c84..225df7f86 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Tasmota Docs - url: https://tasmota.github.io/docs/#/ + url: https://tasmota.github.io/docs about: All the information related to Tasmota - name: Tasmota Support Chat url: https://discord.gg/Ks2Kzd4 diff --git a/.github/issue-close-app.yml b/.github/issue-close-app.yml index d222d8980..6a6947a9c 100644 --- a/.github/issue-close-app.yml +++ b/.github/issue-close-app.yml @@ -19,7 +19,7 @@ comment: >- [Support Information](https://github.com/arendst/Sonoff-Tasmota/blob/development/SUPPORT.md) - [Wiki](https://tasmota.github.io/docs/#/) for more information. + [Wiki](https://tasmota.github.io/docs/) for more information. [Chat](https://discord.gg/Ks2Kzd4) for more user experience. diff --git a/API.md b/API.md index f10ae2c93..7bb77735b 100644 --- a/API.md +++ b/API.md @@ -2,7 +2,7 @@ # Basic API information -Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. Read [Sensor API](https://tasmota.github.io/docs/#/Sensor-API) for more information. +Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. Read [Sensor API](https://tasmota.github.io/docs/Sensor-API) for more information. Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall, XnrgCall and XlgtCall. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43cead24a..26db830ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Everybody is welcome and invited to contribute to Tasmota Project by: * Testing newly released features and reporting issues. * Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) -* Contributing missing documentation for features and devices in our [documentation](https://tasmota.github.io/docs/#/Contributing) +* Contributing missing documentation for features and devices in our [documentation](https://tasmota.github.io/docs/Contributing) This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. diff --git a/README.md b/README.md index 53f977ae2..23359fe22 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ We don't take any responsibility nor liability for using this software nor for t ## Note -Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://tasmota.github.io/docs/#/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://tasmota.github.io/docs/#/Templates?id=creating-your-template). +Please do not ask to add new devices unless it requires additional code for new features. If the device is not listed as a module, try using [Templates](https://tasmota.github.io/docs/Templates) first. If it is not listed in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) create your own [Template](https://tasmota.github.io/docs/Templates#creating-your-template). ## Quick Install -Download one of the released binaries from https://github.com/arendst/Tasmota/releases and flash it to your hardware [using our installation guide](https://tasmota.github.io/docs/#/installation/). +Download one of the released binaries from https://github.com/arendst/Tasmota/releases and flash it to your hardware [using our installation guide](https://tasmota.github.io/docs/Getting-Started). ## Important User Compilation Information If you want to compile Tasmota yourself keep in mind the following: @@ -60,7 +60,7 @@ Please refer to the installation and configuration articles in our [documentatio ## Migration Information -See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: +See [wiki migration path](https://tasmota.github.io/docs/Upgrading#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** @@ -77,15 +77,15 @@ See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migratio -For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates) +For a database of supported devices see [Tasmota Device Templates Repository](https://templates.blakadder.com) If you're looking for support on **Tasmota** there are some options available: ### Documentation * [Documentation Site](https://tasmota.github.io/docs): For information on how to flash Tasmota, configure, use and expand it -* [FAQ and Troubleshooting](https://tasmota.github.io/docs/#/help/): For information on common problems and solutions. -* [Commands Information](https://tasmota.github.io/docs/#/Commands): For information on all the commands supported by Tasmota. +* [FAQ and Troubleshooting](https://tasmota.github.io/docs/FAQ/): For information on common problems and solutions. +* [Commands Information](https://tasmota.github.io/docs/Commands): For information on all the commands supported by Tasmota. ### Support's Community diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 43a769512..c4c1c4c61 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,7 +4,7 @@ ## Migration Information -See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: +See [migration path](https://tasmota.github.io/docs/Upgrading#migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** @@ -27,7 +27,7 @@ Although it might still compile on previous Core versions all support will be re ## Support of TLS -To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. Read [full documentation](https://tasmota.github.io/docs/#/integrations/AWS-IoT) +To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. Read [full documentation](https://tasmota.github.io/docs/AWS-IoT) ## Initial configuration tools From 4631fb729ae2539012d18f65007340fff172a362 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 30 Mar 2020 12:52:09 +0200 Subject: [PATCH 36/56] Add compile error message Add compile error message when both rules and scripts are selected (#8026) --- tasmota/my_user_config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index ab80c4cf6..70504293c 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -684,4 +684,8 @@ #error "Select either USE_DISCOVERY or USE_MQTT_AWS_IOT, mDNS takes too much code space and is not needed for AWS IoT" #endif +#if defined(USE_RULES) && defined(USE_SCRIPT) + #error "Select either USE_RULES or USE_SCRIPT. They can't both be used at the same time" +#endif + #endif // _MY_USER_CONFIG_H_ From 490a7f2d9f123ae96d8fcbe9564b99adbfa2aa17 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 30 Mar 2020 17:11:07 +0200 Subject: [PATCH 37/56] Turn browser autocomplete off whan arrow is pressed Turn browser autocomplete off and use command history as soon as an arrow key is pressed allowing mobiles and tablets to keep using browser autocomplete. (#8015) --- tasmota/xdrv_01_webserver.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 80c4bf417..ea874b7f2 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -216,6 +216,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "var hc=[],cn=0;" // hc = History commands, cn = Number of history being shown "function cH(a){" "var b=qs('#c1'),c=a.keyCode;" // c1 = Console command id + "if(38==c||40==c){b.autocomplete='off';}" // Arrow up or down must be a keyboard so stop browser autocomplete "38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // Arrow Up "40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // Arrow Down "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter, 19 = Max number -1 of commands in history From 89014a915e77d2614b3f1b66aac3d9e7e42a29f6 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Mon, 30 Mar 2020 17:33:12 +0200 Subject: [PATCH 38/56] Update Italian language Update italian language Revised with feedback of @effeelle Fixed a typo about D_SENSOR_RELAY --- tasmota/language/it-IT.h | 726 +++++++++++++++++++-------------------- 1 file changed, 363 insertions(+), 363 deletions(-) diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index d9a4b9a6b..12b730bbc 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -56,14 +56,14 @@ #define D_AP "AP" // Access Point #define D_AS "come" #define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" +#define D_BLINK "Lampeggia" +#define D_BLINKOFF "Lampeggia OFF" #define D_BOOT_COUNT "Numero di boot" #define D_BRIGHTLIGHT "Luminoso" #define D_BSSID "BSSId" #define D_BUTTON "Pulsante" #define D_BY "da" // Written by me -#define D_BYTES "Bytes" +#define D_BYTES "Byte" #define D_CELSIUS "Celsius" #define D_CHANNEL "Canale" #define D_CO2 "CO2" @@ -71,24 +71,24 @@ #define D_COLDLIGHT "Fredda" #define D_COMMAND "Comando" #define D_CONNECTED "Connesso" -#define D_CORS_DOMAIN "CORS Domain" +#define D_CORS_DOMAIN "Dominio CORS" #define D_COUNT "Conteggio" #define D_COUNTER "Contatore" -#define D_CT_POWER "CT Power" +#define D_CT_POWER "Alimentazione CT" #define D_CURRENT "Corrente" // As in Voltage and Current #define D_DATA "Dati" #define D_DARKLIGHT "Scuro" #define D_DEBUG "Debug" -#define D_DEWPOINT "Dew point" +#define D_DEWPOINT "Punto rugiada" // #define D_DISABLED "Disabilitato" #define D_DISTANCE "Distanza" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Fatto" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Completato" #define D_DST_TIME "DST" #define D_ECO2 "eCO₂" #define D_EMULATION "Emulazione" #define D_ENABLED "Abilitato" -#define D_ERASE "Cancellare" +#define D_ERASE "Cancella" #define D_ERROR "Errore" #define D_FAHRENHEIT "Fahrenheit" #define D_FAILED "Fallito" @@ -96,14 +96,14 @@ #define D_FALLBACK_TOPIC "Topic Riserva" #define D_FALSE "Falso" #define D_FILE "File" -#define D_FLOW_RATE "Flow rate" +#define D_FLOW_RATE "Flusso dati" #define D_FREE_MEMORY "Memoria Libera" #define D_FREQUENCY "Frequenza" #define D_GAS "Gas" #define D_GATEWAY "Gateway" #define D_GROUP "Gruppo" #define D_HOST "Host" -#define D_HOSTNAME "Nome Host" +#define D_HOSTNAME "Nome host" #define D_HUMIDITY "Umidità" #define D_ILLUMINANCE "Illuminazione" #define D_IMMEDIATE "immediato" // Button immediate @@ -120,55 +120,55 @@ #define D_MULTI_PRESS "multi-pressione" #define D_NOISE "Rumore" #define D_NONE "Nessuno" -#define D_OFF "Off" +#define D_OFF "OFF" #define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" +#define D_OK "OK" +#define D_ON "ON" #define D_ONLINE "Online" #define D_PASSWORD "Password" #define D_PORT "Porta" #define D_POWER_FACTOR "Fattore di potenza" #define D_POWERUSAGE "Potenza" -#define D_POWERUSAGE_ACTIVE "Potenza Attiva" -#define D_POWERUSAGE_APPARENT "Potenza Apparente" -#define D_POWERUSAGE_REACTIVE "Potenza Reattiva" +#define D_POWERUSAGE_ACTIVE "Potenza attiva" +#define D_POWERUSAGE_APPARENT "Potenza apparente" +#define D_POWERUSAGE_REACTIVE "Potenza reattiva" #define D_PRESSURE "Pressione" #define D_PRESSUREATSEALEVEL "Pressione al livello del mare" -#define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" -#define D_PROGRAM_SIZE "Dimensione Programma" +#define D_PROGRAM_FLASH_SIZE "Dimensione flash programma" +#define D_PROGRAM_SIZE "Dimensione programma" #define D_PROJECT "Progetto" -#define D_RAIN "Rain" -#define D_RANGE "Range" +#define D_RAIN "Pioggia" +#define D_RANGE "Intervallo" #define D_RECEIVED "Ricevuto" #define D_RESTART "Riavvio" -#define D_RESTARTING "Riavviando" -#define D_RESTART_REASON "Causa Riavvio" +#define D_RESTARTING "Riavvio" +#define D_RESTART_REASON "Causa riavvio" #define D_RESTORE "ripristino" #define D_RETAINED "salvato" -#define D_RULE "Rule" +#define D_RULE "Regola" #define D_SAVE "Salva" #define D_SENSOR "Sensore" -#define D_SSID "SSId" -#define D_START "Start" +#define D_SSID "SSID" +#define D_START "Avvia" #define D_STD_TIME "STD" #define D_STOP "Stop" -#define D_SUBNET_MASK "Maschera Subnet" -#define D_SUBSCRIBE_TO "Sottoscrivi a" -#define D_UNSUBSCRIBE_FROM "Cancella da" -#define D_SUCCESSFUL "Riuscito" +#define D_SUBNET_MASK "Maschera sottorete" +#define D_SUBSCRIBE_TO "Abbonati a" +#define D_UNSUBSCRIBE_FROM "Rimuovi abbonamento da" +#define D_SUCCESSFUL "Completato" #define D_SUNRISE "Alba" #define D_SUNSET "Tramonto" #define D_TEMPERATURE "Temperatura" #define D_TO "a" -#define D_TOGGLE "Toggle" +#define D_TOGGLE "ON/OFF" #define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" +#define D_TOTAL_USAGE "Uso totale" #define D_TRANSMIT "Trasmesso" #define D_TRUE "Vero" #define D_TVOC "TVOC" -#define D_UPGRADE "Aggiornamento" +#define D_UPGRADE "Aggiorna" #define D_UPLOAD "Invio" -#define D_UPTIME "Uptime" +#define D_UPTIME "Tempo accensione" #define D_USER "Utente" #define D_UTC_TIME "UTC" #define D_UV_INDEX "Indice UV" @@ -178,242 +178,242 @@ #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" +#define D_UV_INDEX_7 "OoR" // Out of Range #define D_UV_LEVEL "Livello UV" #define D_UV_POWER "Intensità UV" #define D_VERSION "Versione" #define D_VOLTAGE "Tensione" #define D_WEIGHT "Peso" #define D_WARMLIGHT "Calda" -#define D_WEB_SERVER "Web Server" +#define D_WEB_SERVER "Server web" // tasmota.ino #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_LEVEL_10 "livello 1-0" +#define D_LEVEL_01 "livello 0-1" +#define D_SERIAL_LOGGING_DISABLED "Registro attività seriale disabilitato" #define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" -#define D_SET_BAUDRATE_TO "Baudrate impostato a" +#define D_SET_BAUDRATE_TO "Imposta baudrate" #define D_RECEIVED_TOPIC "Topic Ricevuto" -#define D_DATA_SIZE "Dimensione Dati" -#define D_ANALOG_INPUT "Ingresso Analogico" +#define D_DATA_SIZE "Dimensione dati" +#define D_ANALOG_INPUT "Ingresso analogico" // support.ino #define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Ciclo Bloccato" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" +#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_FAILED_TO_START "Partenza fallita" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_FAILED_TO_START "Avvio fallito" +#define D_PATCH_ISSUE_2186 "Patch problema 2186" #define D_CONNECTING_TO_AP "Connessione ad AP" #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" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita, timeout AP" +#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" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita - timeout AP" #define D_ATTEMPTING_CONNECTION "Tentativo di connessione..." #define D_CHECKING_CONNECTION "Controllo connessione..." #define D_QUERY_DONE "Query eseguita. Servizio MQTT trovato" -#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato su" -#define D_FOUND_AT "trovato a" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host non trovato" +#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato in" +#define D_FOUND_AT "trovato in" +#define D_SYSLOG_HOST_NOT_FOUND "Host Syslog non trovato" // settings.ino #define D_SAVED_TO_FLASH_AT "Salvato nella flash in" #define D_LOADED_FROM_FLASH_AT "Caricato dalla flash da" -#define D_USE_DEFAULTS "Utilizzo valori default" +#define D_USE_DEFAULTS "Usa valori predefiniti" #define D_ERASED_SECTOR "Settore cancellato" // xdrv_02_webserver.ino -#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" -#define D_WEBSERVER_ACTIVE_ON "Web server attivo su" +#define D_NOSCRIPT "Per usare Tasmota abilita JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "FFirmware MINIMALE
Effettua aggiornamento" +#define D_WEBSERVER_ACTIVE_ON "Server web attivo in" #define D_WITH_IP_ADDRESS "con indirizzo IP" -#define D_WEBSERVER_STOPPED "Web server arrestato" -#define D_FILE_NOT_FOUND "File Non Trovato" +#define D_WEBSERVER_STOPPED "Server web arrestato" +#define D_FILE_NOT_FOUND "File non trovato" #define D_REDIRECTED "Redirezione al captive portal" #define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Impostazione Wifimanager come AccessPoint e Station" #define D_WIFIMANAGER_SET_ACCESSPOINT "Impostazione Wifimanager come AccessPoint" -#define D_TRYING_TO_CONNECT "Tentativo di connessione del dispositivo alla rete" +#define D_TRYING_TO_CONNECT "Tentativo connessione dispositivo alla rete" -#define D_RESTART_IN "Riavvio in" +#define D_RESTART_IN "Riavvio tra" #define D_SECONDS "secondi" #define D_DEVICE_WILL_RESTART "Il dispositivo verrà riavviato tra pochi secondi" -#define D_BUTTON_TOGGLE "On/Off" +#define D_BUTTON_TOGGLE "ON/OFF" #define D_CONFIGURATION "Configurazione" #define D_INFORMATION "Informazioni" -#define D_FIRMWARE_UPGRADE "Aggiornamento Firmware" +#define D_FIRMWARE_UPGRADE "Aggiornamento firmware" #define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Conferma Riavvio" +#define D_CONFIRM_RESTART "Conferma riavvio" -#define D_CONFIGURE_MODULE "Configurazione Modulo" -#define D_CONFIGURE_WIFI "Configurazione WiFi" -#define D_CONFIGURE_MQTT "Configurazione MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz" -#define D_CONFIGURE_LOGGING "Configurazione Logging" -#define D_CONFIGURE_OTHER "Configurazione Extra" -#define D_CONFIRM_RESET_CONFIGURATION "Conferma Reset Configurazione" -#define D_RESET_CONFIGURATION "Reset Configurazione" -#define D_BACKUP_CONFIGURATION "Backup Configurazione" -#define D_RESTORE_CONFIGURATION "Ripristino Configurazione" -#define D_MAIN_MENU "Menu Principale" +#define D_CONFIGURE_MODULE "Configura modulo" +#define D_CONFIGURE_WIFI "Configura WiFi" +#define D_CONFIGURE_MQTT "Configura MQTT" +#define D_CONFIGURE_DOMOTICZ "Configura Domoticz" +#define D_CONFIGURE_LOGGING "Configura registrazione" +#define D_CONFIGURE_OTHER "Configura extra" +#define D_CONFIRM_RESET_CONFIGURATION "Conferma ripristino configurazione" +#define D_RESET_CONFIGURATION "Ripristino configurazione" +#define D_BACKUP_CONFIGURATION "Backup configurazione" +#define D_RESTORE_CONFIGURATION "Ripristino configurazione" +#define D_MAIN_MENU "Menu principale" -#define D_MODULE_PARAMETERS "Parametri del modulo" +#define D_MODULE_PARAMETERS "Parametri modulo" #define D_MODULE_TYPE "Tipo modulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_PULLUP_ENABLE "Nessun pulsante/switch pull-up" #define D_ADC "ADC" #define D_GPIO "GPIO" -#define D_SERIAL_IN "Seriale In" -#define D_SERIAL_OUT "Seriale 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" -#define D_SCAN_DONE "Scansione effettuata" +#define D_WIFI_PARAMETERS "Parametri WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scansione reti WiFi" +#define D_SCAN_DONE "Scansione completata" #define D_NO_NETWORKS_FOUND "Nessuna rete trovata" -#define D_REFRESH_TO_SCAN_AGAIN "Ricarica per nuova scansione" +#define D_REFRESH_TO_SCAN_AGAIN "Aggiorna per nuova scansione" #define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicato" #define D_SKIPPING_LOW_QUALITY "Ignorato a causa di bassa qualità" #define D_RSSI "RSSI" #define D_WEP "WEP" #define D_WPA_PSK "WPA PSK" #define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" +#define D_AP1_SSID "AP1 - SSID" +#define D_AP1_PASSWORD "AP1 - Password" +#define D_AP2_SSID "AP2 - SSID" +#define D_AP2_PASSWORD "AP2 - Password" #define D_MQTT_PARAMETERS "Parametri MQTT" #define D_CLIENT "Client" #define D_FULL_TOPIC "Full Topic" -#define D_LOGGING_PARAMETERS "Parametri Logging" -#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "livello di log Web" -#define D_SYS_LOG_LEVEL "livello di log Sys" +#define D_LOGGING_PARAMETERS "Parametri registrazione" +#define D_SERIAL_LOG_LEVEL "Livello registrazione seriale" +#define D_MQTT_LOG_LEVEL "Livello registrazione MQTT" +#define D_WEB_LOG_LEVEL "Livello registrazione web" +#define D_SYS_LOG_LEVEL "Livello registrazione Sys" #define D_MORE_DEBUG "Debug aggiuntivo" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog porta" +#define D_SYSLOG_HOST "Host Syslog" +#define D_SYSLOG_PORT "Porta Syslog" #define D_TELEMETRY_PERIOD "Periodo Telemetria" #define D_OTHER_PARAMETERS "Altri parametri" #define D_TEMPLATE "Modello" -#define D_ACTIVATE "Attivare" -#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" +#define D_ACTIVATE "Attiva" +#define D_WEB_ADMIN_PASSWORD "Password amministratore web" #define D_MQTT_ENABLE "Abilita MQTT" #define D_FRIENDLY_NAME "Nome amichevole" #define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" +#define D_HUE_BRIDGE "Bridge Hue" #define D_SINGLE_DEVICE "dispositivo singolo" #define D_MULTI_DEVICE "dispositivo multiplo" -#define D_CONFIGURE_TEMPLATE "Configurare Modello" -#define D_TEMPLATE_PARAMETERS "Parametri Modello" +#define D_CONFIGURE_TEMPLATE "Configura modello" +#define D_TEMPLATE_PARAMETERS "Parametri modello" #define D_TEMPLATE_NAME "Nome" -#define D_BASE_TYPE "Basato nel" +#define D_BASE_TYPE "Basato su" #define D_TEMPLATE_FLAGS "Opzioni" #define D_SAVE_CONFIGURATION "Salva configurazione" #define D_CONFIGURATION_SAVED "Configurazione salvata" -#define D_CONFIGURATION_RESET "Configurazione azzerata" +#define D_CONFIGURATION_RESET "Configurazione ripristinata" -#define D_PROGRAM_VERSION "Versione del programma" +#define D_PROGRAM_VERSION "Versione programma" #define D_BUILD_DATE_AND_TIME "Data e ora compilazione" -#define D_CORE_AND_SDK_VERSION "Versione Core/SDK" -#define D_FLASH_WRITE_COUNT "Contatore scrittura Flash" +#define D_CORE_AND_SDK_VERSION "Versione core/SDK" +#define D_FLASH_WRITE_COUNT "Contatore scritture flash" #define D_MAC_ADDRESS "Indirizzo MAC" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Utente" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Dimensione Flash" -#define D_FREE_PROGRAM_SPACE "Spazio Libero Memoria Programma" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Porta MQTT" +#define D_MQTT_CLIENT "Client MQTT" +#define D_MQTT_USER "Utente MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Gruppo topic MQTT" +#define D_MQTT_FULL_TOPIC "Full topic MQTT" +#define D_MDNS_DISCOVERY "Ricerca mDNS" +#define D_MDNS_ADVERTISE "Notifica mDNS" +#define D_ESP_CHIP_ID "ID chip ESP" +#define D_FLASH_CHIP_ID "ID chip flash" +#define D_FLASH_CHIP_SIZE "Dimensione flash" +#define D_FREE_PROGRAM_SPACE "Spazio libero memoria programma" -#define D_UPGRADE_BY_WEBSERVER "Aggiornamento da web server" -#define D_OTA_URL "OTA Url" +#define D_UPGRADE_BY_WEBSERVER "Aggiornamento via server web" +#define D_OTA_URL "OTA URL" #define D_START_UPGRADE "Avvio aggiornamento" -#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite invio file" -#define D_UPLOAD_STARTED "Invio iniziato" +#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite upload file" +#define D_UPLOAD_STARTED "Upload iniziato" #define D_UPGRADE_STARTED "Aggiornamento avviato" -#define D_UPLOAD_DONE "Invio effettuato" +#define D_UPLOAD_DONE "Upload completato" #define D_UPLOAD_ERR_1 "Nessun file selezionato" #define D_UPLOAD_ERR_2 "Spazio insufficiente" #define D_UPLOAD_ERR_3 "Magic byte non corrispondente a 0xE9" -#define D_UPLOAD_ERR_4 "Dimensione della memoria programma maggiore della dimensione reale della flash" -#define D_UPLOAD_ERR_5 "Errore di comparazione del buffer di invio" -#define D_UPLOAD_ERR_6 "Invio fallito. Abilitare logging 3" -#define D_UPLOAD_ERR_7 "Invio annullato" +#define D_UPLOAD_ERR_4 "Dimensione memoria programma maggiore della dimensione reale della flash" +#define D_UPLOAD_ERR_5 "Errore comparazione buffer upload" +#define D_UPLOAD_ERR_6 "Invio fallito. Abilita registrazione logging 3" +#define D_UPLOAD_ERR_7 "Upload annullato" #define D_UPLOAD_ERR_8 "File non valido" #define D_UPLOAD_ERR_9 "File troppo grande" -#define D_UPLOAD_ERR_10 "Inizializzazione fallita del chip RF" -#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" -#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" -#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" -#define D_UPLOAD_ERR_14 "Not compatible" -#define D_UPLOAD_ERROR_CODE "Codice errore invio" +#define D_UPLOAD_ERR_10 "Inizializzazione chip RF fallita" +#define D_UPLOAD_ERR_11 "Cancellazione chip RF fallita" +#define D_UPLOAD_ERR_12 "Scrittura chip RF fallita" +#define D_UPLOAD_ERR_13 "Decodifica firmware RF fallita" +#define D_UPLOAD_ERR_14 "Non compatibile" +#define D_UPLOAD_ERROR_CODE "Codice errore upload" -#define D_ENTER_COMMAND "Inserire comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitare weblog 2 se è attesa una risposta" -#define D_NEED_USER_AND_PASSWORD "Richiesto user=&password=" +#define D_ENTER_COMMAND "Inserisci comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilita weblog 2 se è attesa una risposta" +#define D_NEED_USER_AND_PASSWORD "Richiesto utente=&password=" // xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifica TLS fingerprint..." +#define D_FINGERPRINT "Verifica chiave TLS..." #define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a" #define D_RETRY_IN "Nuovo tentativo in" -#define D_VERIFIED "Verificato Fingerprint" -#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido" -#define D_CONNECT_FAILED_TO "Connessione Fallita a" +#define D_VERIFIED "Verificato tramite chiave" +#define D_INSECURE "Connessione non sicura a causa di chiave non valida" +#define D_CONNECT_FAILED_TO "Connessione fallita a" // xplg_wemohue.ino #define D_MULTICAST_DISABLED "Multicast disabilitato" #define D_MULTICAST_REJOINED "Multicast (ri)associato" -#define D_MULTICAST_JOIN_FAILED "Associazione Multicast fallita" +#define D_MULTICAST_JOIN_FAILED "Associazione multicast fallita" #define D_FAILED_TO_SEND_RESPONSE "Invio risposta fallito" #define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento base" -#define D_WEMO_EVENT_SERVICE "WeMo servizio eventi" -#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_BASIC_EVENT "Evento base WeMo" +#define D_WEMO_EVENT_SERVICE "Servizio eventi WeMo" +#define D_WEMO_META_SERVICE "Servizio meta WeMo" #define D_WEMO_SETUP "Impostazione WeMo" #define D_RESPONSE_SENT "Risposta inviata" #define D_HUE "Hue" #define D_HUE_BRIDGE_SETUP "Impostazione Hue" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API non implementata" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argomenti" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implementata" +#define D_HUE_API "API Hue" +#define D_HUE_POST_ARGS "POST argomenti Hue" #define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati" // xdrv_07_domoticz.ino #define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" #define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" +#define D_DOMOTICZ_KEY_IDX "Idx chiave" +#define D_DOMOTICZ_SWITCH_IDX "Idx switch" +#define D_DOMOTICZ_SENSOR_IDX "Idx sensore" #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_TEMP_HUM "Temp,Umd" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umd,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Alim,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Illuminazione" + #define D_DOMOTICZ_COUNT "Cont/PM1" + #define D_DOMOTICZ_VOLTAGE "Tensione/PM2.5" + #define D_DOMOTICZ_CURRENT "Corrente/PM10" + #define D_DOMOTICZ_AIRQUALITY "QualitàAria" #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Intervallo di aggiornamento" +#define D_DOMOTICZ_UPDATE_TIMER "Intervallo aggiornamento" // xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configura Timer" -#define D_TIMER_PARAMETERS "Parametri Timer" -#define D_TIMER_ENABLE "Abilita Timer" +#define D_CONFIGURE_TIMER "Configura timer" +#define D_TIMER_PARAMETERS "Parametri timer" +#define D_TIMER_ENABLE "Abilita timer" #define D_TIMER_ARM "Attiva" #define D_TIMER_TIME "Ora" #define D_TIMER_DAYS "Giorni" @@ -425,57 +425,57 @@ #define D_CONFIGURE_KNX "Configura KNX" #define D_KNX_PARAMETERS "Parametri KNX" #define D_KNX_GENERAL_CONFIG "Generale" -#define D_KNX_PHYSICAL_ADDRESS "Indirizzo Fisico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve essere univoco nella rete KNX )" +#define D_KNX_PHYSICAL_ADDRESS "Indirizzo fisico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(deve essere univoco nella rete KNX )" #define D_KNX_ENABLE "Abilita KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da Inviare al Gruppo di Indirizzi" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da inviare al gruppo di indirizzi" #define D_ADD "Aggiungi" #define D_DELETE "Elimina" #define D_REPLY "Rispondi" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di Indirizzi da cui Ricevere Dati" -#define D_RECEIVED_FROM "Ricevuto Da" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di indirizzi da cui ricevere dati" +#define D_RECEIVED_FROM "Ricevuto da" #define D_KNX_COMMAND_WRITE "Scrivi" #define D_KNX_COMMAND_READ "Leggi" #define D_KNX_COMMAND_OTHER "Altro" #define D_SENT_TO "invia a" #define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato." -#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" +#define D_KNX_ENHANCEMENT "Miglioramento comunicazione" +#define D_KNX_TX_SLOT "KNX - TX" +#define D_KNX_RX_SLOT "KNX - RX" // xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energia Oggi" -#define D_ENERGY_YESTERDAY "Energia Ieri" -#define D_ENERGY_TOTAL "Energia Totale" +#define D_ENERGY_TODAY "Energia - oggi" +#define D_ENERGY_YESTERDAY "Energia - ieri" +#define D_ENERGY_TOTAL "Energia - totale" // xdrv_27_shutter.ino -#define D_OPEN "Aperta" -#define D_CLOSE "Chiusa" +#define D_OPEN "Apri" +#define D_CLOSE "Chiudi" #define D_DOMOTICZ_SHUTTER "Serranda" // xdrv_28_pcf8574.ino #define D_CONFIGURE_PCF8574 "Configura PCF8574" #define D_PCF8574_PARAMETERS "Parametri PCF8574" -#define D_INVERT_PORTS "Porte Invertite" +#define D_INVERT_PORTS "Inverti porte" #define D_DEVICE "Dispositivo" #define D_DEVICE_INPUT "Input" #define D_DEVICE_OUTPUT "Output" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Sensore occupato" -#define D_SENSOR_CRC_ERROR "Sensore errore CRC" +#define D_SENSOR_CRC_ERROR "Errore CRC sensore" #define D_SENSORS_FOUND "Sensori trovati" // xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Attesa timeout per" +#define D_TIMEOUT_WAITING_FOR "Timeout attesa per" #define D_START_SIGNAL_LOW "inizio segnale basso" #define D_START_SIGNAL_HIGH "inizio segnale alto" #define D_PULSE "impulso" #define D_CHECKSUM_FAILURE "Checksum fallito" // xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensore non ha eseguito il comando ACK" -#define D_SHT1X_FOUND "SHT1X trovato" +#define D_SENSOR_DID_NOT_ACK_COMMAND "Il sensore non ha eseguito il comando ACK" +#define D_SHT1X_FOUND "Trovato SHT1X" // xsns_18_pms5003.ino #define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter @@ -483,55 +483,55 @@ #define D_PARTICALS_BEYOND "Particelle" // xsns_32_mpu6050.ino -#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" +#define D_AX_AXIS "Accelerazione asse X" +#define D_AY_AXIS "Accelerazione asse Y" +#define D_AZ_AXIS "Accelerazione asse Z" +#define D_GX_AXIS "Giroscopio asse X" +#define D_GY_AXIS "Giroscopio asse Y" +#define D_GZ_AXIS "Giroscopio asse Z" // xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Rimuovere peso" -#define D_HX_CAL_REFERENCE "Caricare peso di riferimento" +#define D_HX_CAL_REMOVE "Rimuovi peso" +#define D_HX_CAL_REFERENCE "Carica riferimento peso" #define D_HX_CAL_DONE "Calibrato" #define D_HX_CAL_FAIL "Calibrazione fallita" -#define D_RESET_HX711 "Reset Scala" -#define D_CONFIGURE_HX711 "Configura Scala" -#define D_HX711_PARAMETERS "Parametri Scala" +#define D_RESET_HX711 "Ripristino scala" +#define D_CONFIGURE_HX711 "Configura scala" +#define D_HX711_PARAMETERS "Parametri scala" #define D_ITEM_WEIGHT "Peso oggetto" #define D_REFERENCE_WEIGHT "Peso di riferimento" #define D_CALIBRATE "Calibrato" #define D_CALIBRATION "Calibrazione" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direzione Vento" -#define D_TX20_WIND_SPEED "Velocità Vento" -#define D_TX20_WIND_SPEED_MIN "Velocità Minima Vento" -#define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" +#define D_TX20_WIND_DIRECTION "Direzione vento" +#define D_TX20_WIND_SPEED "Velocità vento" +#define D_TX20_WIND_SPEED_MIN "Velocità minima vento" +#define D_TX20_WIND_SPEED_MAX "Velocità massima vento" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" // xsns_53_sml.ino -#define D_TPWRIN "Energy Total-In" -#define D_TPWROUT "Energy Total-Out" -#define D_TPWRCURR "Active Power-In/Out" -#define D_TPWRCURR1 "Active Power-In p1" -#define D_TPWRCURR2 "Active Power-In p2" -#define D_TPWRCURR3 "Active Power-In p3" -#define D_Strom_L1 "Current L1" -#define D_Strom_L2 "Current L2" -#define D_Strom_L3 "Current L3" -#define D_Spannung_L1 "Voltage L1" -#define D_Spannung_L2 "Voltage L2" -#define D_Spannung_L3 "Voltage L3" +#define D_TPWRIN "Energia totale IN" +#define D_TPWROUT "Energia totale OUT" +#define D_TPWRCURR "Corrente IN/OUT" +#define D_TPWRCURR1 "Corrente IN p1" +#define D_TPWRCURR2 "Corrente IN p2" +#define D_TPWRCURR3 "Corrente IN p3" +#define D_Strom_L1 "Corrente L1" +#define D_Strom_L2 "Corrente L2" +#define D_Strom_L3 "Corrente L3" +#define D_Spannung_L1 "Tensione L1" +#define D_Spannung_L2 "Tensione L2" +#define D_Spannung_L3 "Tensione L3" #define D_METERNR "Meter_number" -#define D_METERSID "Service ID" -#define D_GasIN "Counter" -#define D_H2oIN "Counter" -#define D_StL1L2L3 "Current L1+L2+L3" -#define D_SpL1L2L3 "Voltage L1+L2+L3/3" +#define D_METERSID "ID servizio" +#define D_GasIN "Contatore" +#define D_H2oIN "Contatore" +#define D_StL1L2L3 "Corrente L1+L2+L3" +#define D_SpL1L2L3 "Tensione L1+L2+L3/3" // tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nessuno" @@ -543,133 +543,133 @@ #define D_SENSOR_I2C_SCL "I2C SCL" #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_DFR562 "Riproduttore MP3" +#define D_SENSOR_IRSEND "IR - TX" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Pulsante" // Suffix "1" +#define D_SENSOR_RELAY "Relè" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "Led - Lampeggio" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contatore" // Suffix "1" +#define D_SENSOR_IRRECV "IR - RX" +#define D_SENSOR_MHZ_RX "MHZ - RX" +#define D_SENSOR_MHZ_TX "MHZ - TX" +#define D_SENSOR_PZEM004_RX "PZEM004 - RX" +#define D_SENSOR_PZEM016_RX "PZEM016 - RX" +#define D_SENSOR_PZEM017_RX "PZEM017 - RX" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX - TX" +#define D_SENSOR_SAIR_RX "SAir - RX" +#define D_SENSOR_SAIR_TX "SAir - TX" +#define D_SENSOR_SPI_CS "SPI - CS" +#define D_SENSOR_SPI_DC "SPI - DC" +#define D_SENSOR_SPI_MISO "SPI - MISO" +#define D_SENSOR_SPI_MOSI "SPI - MOSI" +#define D_SENSOR_SPI_CLK "SPI - CLK" +#define D_SENSOR_BACKLIGHT "Retroilluminazione" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_SDS0X1_RX "SDS0X1 - RX" +#define D_SENSOR_SDS0X1_TX "SDS0X1 - TX" +#define D_SENSOR_HPMA_RX "HPMA - RX" +#define D_SENSOR_HPMA_TX "HPMA - TX" +#define D_SENSOR_SBR_RX "SerBr - RX" +#define D_SENSOR_SBR_TX "SerBr - TX" +#define D_SENSOR_SR04_TRIG "SR04 Tri - TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech - RX" +#define D_SENSOR_SDM120_TX "SDMx20 - TX" +#define D_SENSOR_SDM120_RX "SDMx20 - RX" +#define D_SENSOR_SDM630_TX "SDM630 - TX" +#define D_SENSOR_SDM630_RX "SDM630 - RX" +#define D_SENSOR_TM1638_CLK "TM16 - CLK" +#define D_SENSOR_TM1638_DIO "TM16 - DIO" +#define D_SENSOR_TM1638_STB "TM16 - STB" +#define D_SENSOR_HX711_SCK "HX711 - SCK" +#define D_SENSOR_HX711_DAT "HX711 - DAT" #define D_SENSOR_TX2X_TX "TX2x" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_RFSEND "RF - TX" +#define D_SENSOR_RFRECV "RF - RX" +#define D_SENSOR_TUYA_TX "Tuya - TX" +#define D_SENSOR_TUYA_RX "Tuya - RX" +#define D_SENSOR_MGC3130_XFER "MGC3130 - XFR" +#define D_SENSOR_MGC3130_RESET "MGC3130 - RST" +#define D_SENSOR_SSPI_MISO "SSPI - MISO" +#define D_SENSOR_SSPI_MOSI "SSPI - MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI - SCLK" +#define D_SENSOR_SSPI_CS "SSPI - CS" +#define D_SENSOR_SSPI_DC "SSPI - DC" +#define D_SENSOR_RF_SENSOR "Sensore RF" +#define D_SENSOR_AZ_RX "AZ - RX" +#define D_SENSOR_AZ_TX "AZ - TX" +#define D_SENSOR_MAX31855_CS "MX31855 - CS" +#define D_SENSOR_MAX31855_CLK "MX31855 - CLK" +#define D_SENSOR_MAX31855_DO "MX31855 - DO" +#define D_SENSOR_NRG_SEL "HLWBL - SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL - CF1" +#define D_SENSOR_HLW_CF "HLW8012 - CF" +#define D_SENSOR_HJL_CF "BL0937 - CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 - TX" +#define D_SENSOR_MCP39F5_RX "MCP39F5 - RX" #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_CSE7766_TX "CSE7766 - TX" +#define D_SENSOR_CSE7766_RX "CSE7766 - RX" +#define D_SENSOR_PN532_TX "PN532 - TX" +#define D_SENSOR_PN532_RX "PN532 - RX" +#define D_SENSOR_SM16716_CLK "SM16716 - CLK" +#define D_SENSOR_SM16716_DAT "SM16716 - DAT" +#define D_SENSOR_SM16716_POWER "SM16716 - PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 - DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 - DCKI" +#define D_SENSOR_ARIRFRCV "IR ALux - RCV" +#define D_SENSOR_ARIRFSEL "IR ALux - SEL" +#define D_SENSOR_TXD "Seriale - TX" +#define D_SENSOR_RXD "Seriale - RX" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" -#define D_SENSOR_HM10_RX "HM10 RX" -#define D_SENSOR_HM10_TX "HM10 TX" -#define D_SENSOR_LE01MR_RX "LE-01MR Rx" -#define D_SENSOR_LE01MR_TX "LE-01MR Tx" -#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" -#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" -#define D_SENSOR_HRXL_RX "HRXL Rx" -#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx" +#define D_SENSOR_HRE_CLOCK "HRE - Clock" +#define D_SENSOR_HRE_DATA "HRE - Dati" +#define D_SENSOR_ADE7953_IRQ "ADE7953 - IRQ" +#define D_SENSOR_BUZZER "Cicalino" +#define D_SENSOR_OLED_RESET "Ripristino OLED" +#define D_SENSOR_ZIGBEE_TXD "Zigbee - TX" +#define D_SENSOR_ZIGBEE_RXD "Zigbee - RX" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 - TX" +#define D_SENSOR_SOLAXX1_RX "SolaxX1- RX" +#define D_SENSOR_IBEACON_TX "iBeacon - TX" +#define D_SENSOR_IBEACON_RX "iBeacon - RX" +#define D_SENSOR_RDM6300_RX "RDM6300 - RX" +#define D_SENSOR_CC1101_CS "CC1101 - CS" +#define D_SENSOR_A4988_DIR "A4988 - DIR" +#define D_SENSOR_A4988_STP "A4988 - STP" +#define D_SENSOR_A4988_ENA "A4988 - ENA" +#define D_SENSOR_A4988_MS1 "A4988 - MS1" +#define D_SENSOR_A4988_MS2 "A4988 - MS2" +#define D_SENSOR_A4988_MS3 "A4988 - MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 - TX" +#define D_SENSOR_DDS2382_RX "DDS238-2 - RX" +#define D_SENSOR_DDSU666_TX "DDSU666 - TX" +#define D_SENSOR_DDSU666_RX "DDSU666 - RX" +#define D_SENSOR_SM2135_CLK "SM2135 - CLK" +#define D_SENSOR_SM2135_DAT "SM2135 - DATI" +#define D_SENSOR_DEEPSLEEP "Deep sleep" +#define D_SENSOR_EXS_ENABLE "EXS - Abilita" +#define D_SENSOR_SLAVE_TX "Slave - TX" +#define D_SENSOR_SLAVE_RX "Slave - RX" +#define D_SENSOR_SLAVE_RESET "Slave - RST" +#define D_SENSOR_GPS_RX "GPS - RX" +#define D_SENSOR_GPS_TX "GPS - TX" +#define D_SENSOR_HM10_RX "HM10 - RX" +#define D_SENSOR_HM10_TX "HM10 - TX" +#define D_SENSOR_LE01MR_RX "LE-01MR - RX" +#define D_SENSOR_LE01MR_TX "LE-01MR - TX" +#define D_SENSOR_CC1101_GDO0 "CC1101 - GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 - GDO2" +#define D_SENSOR_HRXL_RX "HRXL - RX" +#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" +#define D_UNIT_HOUR "o" #define D_UNIT_GALLONS "gal" #define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" @@ -701,50 +701,50 @@ //SDM220, SDM120, LE01MR #define D_PHASE_ANGLE "Angolo Fase" -#define D_IMPORT_ACTIVE "Potenza Attiva Importata" -#define D_EXPORT_ACTIVE "Potenza Attiva Esportata" -#define D_IMPORT_REACTIVE "Potenza Reattiva Importata" -#define D_EXPORT_REACTIVE "Potenza Reattiva Esportata" -#define D_TOTAL_REACTIVE "Potenza Reattiva Totale" +#define D_IMPORT_ACTIVE "Potenza attiva importata" +#define D_EXPORT_ACTIVE "Potenza attiva esportata" +#define D_IMPORT_REACTIVE "Potenza reattiva importata" +#define D_EXPORT_REACTIVE "Potenza reattiva esportata" +#define D_TOTAL_REACTIVE "Potenza reattiva totale" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "°" -#define D_TOTAL_ACTIVE "Total Active" +#define D_TOTAL_ACTIVE "Potenza attiva totale" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltaggio" -#define D_PV1_CURRENT "PV1 Corrente" -#define D_PV1_POWER "PV1 Eergia" -#define D_PV2_VOLTAGE "PV2 Voltaggio" -#define D_PV2_CURRENT "PV2 Corrente" -#define D_PV2_POWER "PV2 Energia" -#define D_SOLAR_POWER "Energia Solar" -#define D_INVERTER_POWER "Energia Inverter" +#define D_PV1_VOLTAGE "PV1 - Voltaggio" +#define D_PV1_CURRENT "PV1 - Corrente" +#define D_PV1_POWER "PV1 - Energia" +#define D_PV2_VOLTAGE "PV2 - Voltaggio" +#define D_PV2_CURRENT "PV2 - Corrente" +#define D_PV2_POWER "PV2 - Energia" +#define D_SOLAR_POWER "Energia solare" +#define D_INVERTER_POWER "Energia inverter" #define D_STATUS "Stato" #define D_WAITING "In attesa" -#define D_CHECKING "Controllando" -#define D_WORKING "Lavorando" +#define D_CHECKING "Controllo" +#define D_WORKING "Attivo" #define D_FAILURE "Errore" -#define D_SOLAX_ERROR_0 "No Codice Errore" -#define D_SOLAX_ERROR_1 "Errore Grid Persa" -#define D_SOLAX_ERROR_2 "Errore Voltaggio Grid" -#define D_SOLAX_ERROR_3 "Errore Frequenza Grid" -#define D_SOLAX_ERROR_4 "Errore Voltaggio Pv" -#define D_SOLAX_ERROR_5 "Errore Isolamento" -#define D_SOLAX_ERROR_6 "Errore Temperatura Eccessiva" -#define D_SOLAX_ERROR_7 "Errore Ventilatore" -#define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" +#define D_SOLAX_ERROR_0 "Nessun codice errore" +#define D_SOLAX_ERROR_1 "Griglia errore persa" +#define D_SOLAX_ERROR_2 "Griglia errore tensione" +#define D_SOLAX_ERROR_3 "Griglia errore frequenza" +#define D_SOLAX_ERROR_4 "Errore tensione PV" +#define D_SOLAX_ERROR_5 "Errore isolamento" +#define D_SOLAX_ERROR_6 "Errore temperatura eccessiva" +#define D_SOLAX_ERROR_7 "Errore ventilatore" +#define D_SOLAX_ERROR_8 "Altro errore dispositivo" //xdrv_10_scripter.ino -#define D_CONFIGURE_SCRIPT "Edit script" -#define D_SCRIPT "edit script" -#define D_SDCARD_UPLOAD "file upload" -#define D_SDCARD_DIR "sd card directory" -#define D_UPL_DONE "Done" -#define D_SCRIPT_CHARS_LEFT "chars left" -#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_CONFIGURE_SCRIPT "Modifica script" +#define D_SCRIPT "modifica script" +#define D_SDCARD_UPLOAD "upload file" +#define D_SDCARD_DIR "cartella scheda SD" +#define D_UPL_DONE "Completato" +#define D_SCRIPT_CHARS_LEFT "caratteri rimanenti" +#define D_SCRIPT_CHARS_NO_MORE "nessun altro carattere" #define D_SCRIPT_DOWNLOAD "Download" -#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_ENABLE "abilita script" #define D_SCRIPT_UPLOAD "Upload" -#define D_SCRIPT_UPLOAD_FILES "Upload files" +#define D_SCRIPT_UPLOAD_FILES "Upload file" #endif // _LANGUAGE_IT_IT_H_ From 06774daba6e39739c2c8aed90fe8ef2e6c0bd3ba Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 30 Mar 2020 19:23:06 +0200 Subject: [PATCH 39/56] Add Zigbee commands ``ZbBindState`` and ``manuf``attribute --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 2 + tasmota/xdrv_23_zigbee_0_constants.ino | 4 +- tasmota/xdrv_23_zigbee_3_hue.ino | 10 +-- tasmota/xdrv_23_zigbee_6_commands.ino | 6 +- tasmota/xdrv_23_zigbee_7_statemachine.ino | 6 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 70 +++++++++++++++++ tasmota/xdrv_23_zigbee_9_impl.ino | 95 ++++++++++++++++------- 8 files changed, 152 insertions(+), 42 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0248d4ff7..affa7f008 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.2.0.3 20200329 - Add support for longer template names +- Add Zigbee commands ``ZbBindState`` and ``manuf``attribute ### 8.2.0.2 20200328 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 04433788f..7f225838e 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -507,6 +507,8 @@ #define D_JSON_ZIGBEE_BIND "ZbBind" #define D_CMND_ZIGBEE_UNBIND "Unbind" #define D_JSON_ZIGBEE_UNBIND "ZbUnbind" +#define D_CMND_ZIGBEE_BIND_STATE "BindState" + #define D_JSON_ZIGBEE_BIND_STATE "ZbBindState" #define D_CMND_ZIGBEE_PING "Ping" #define D_JSON_ZIGBEE_PING "ZbPing" #define D_JSON_ZIGBEE_IEEE "IEEEAddr" diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index 1a23c98dd..2aeade28d 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -399,14 +399,14 @@ String getZigbeeStatusMessage(uint8_t status) { "|UNSUP_MANUF_CLUSTER_COMMAND|UNSUP_MANUF_GENERAL_COMMAND|INVALID_FIELD|UNSUPPORTED_ATTRIBUTE|INVALID_VALE|READ_ONLY" "|INSUFFICIENT_SPACE|DUPLICATE_EXISTS|NOT_FOUND|UNREPORTABLE_ATTRIBUTE|INVALID_DATA_TYPE|INVALID_SELECTOR|WRITE_ONLY" "|INCONSISTENT_STARTUP_STATE|DEFINED_OUT_OF_BAND|INCONSISTENT|ACTION_DENIED|TIMEOUT|ABORT|INVALID_IMAGE|WAIT_FOR_DATA" - "|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER" + "|NO_IMAGE_AVAILABLE|REQUIRE_MORE_IMAGE|NOTIFICATION_PENDING|HARDWARE_FAILURE|SOFTWARE_FAILURE|CALIBRATION_ERROR|UNSUPPORTED_CLUSTER|NO_ROUTE" "|CHANNEL_ACCESS_FAILURE|NO_ACK|NO_APP_ACK|NO_ROUTE" ; static const uint8_t StatusIdx[] PROGMEM = { 0x00, 0x01, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, + 0x98, 0x99, 0x9A, 0xC0, 0xC1, 0xC2, 0xC3, 0xCD, 0xE1, 0xE9, 0xA7, 0xD0}; char msg[32]; diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index ffbec109c..0d00ad9e0 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -130,7 +130,7 @@ void ZigbeeHueGroups(String * lights) { // Send commands // Power On/Off void ZigbeeHuePower(uint16_t shortaddr, bool power) { - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0006, power ? 1 : 0, ""); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0006, power ? 1 : 0, ""); zigbee_devices.updateHueState(shortaddr, &power, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } @@ -139,7 +139,7 @@ void ZigbeeHueDimmer(uint16_t shortaddr, uint8_t dimmer) { if (dimmer > 0xFE) { dimmer = 0xFE; } char param[8]; snprintf_P(param, sizeof(param), PSTR("%02X0A00"), dimmer); - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0008, 0x04, param); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0008, 0x04, param); zigbee_devices.updateHueState(shortaddr, nullptr, nullptr, &dimmer, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } @@ -150,7 +150,7 @@ void ZigbeeHueCT(uint16_t shortaddr, uint16_t ct) { char param[12]; snprintf_P(param, sizeof(param), PSTR("%02X%02X0A00"), ct & 0xFF, ct >> 8); uint8_t colormode = 2; // "ct" - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x0A, param); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x0A, param); zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, &ct, nullptr, nullptr, nullptr, nullptr); } @@ -161,7 +161,7 @@ void ZigbeeHueXY(uint16_t shortaddr, uint16_t x, uint16_t y) { if (y > 0xFEFF) { y = 0xFEFF; } snprintf_P(param, sizeof(param), PSTR("%02X%02X%02X%02X0A00"), x & 0xFF, x >> 8, y & 0xFF, y >> 8); uint8_t colormode = 1; // "xy" - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x07, param); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x07, param); zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, nullptr, nullptr, nullptr, &x, &y, nullptr); } @@ -172,7 +172,7 @@ void ZigbeeHueHS(uint16_t shortaddr, uint16_t hue, uint8_t sat) { if (sat > 0xFE) { sat = 0xFE; } snprintf_P(param, sizeof(param), PSTR("%02X%02X0000"), hue8, sat); uint8_t colormode = 0; // "hs" - zigbeeZCLSendStr(shortaddr, 0, 0, true, 0x0300, 0x06, param); + zigbeeZCLSendStr(shortaddr, 0, 0, true, 0, 0x0300, 0x06, param); zigbee_devices.updateHueState(shortaddr, nullptr, &colormode, nullptr, &sat, nullptr, &hue, nullptr, nullptr, nullptr); } diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 818f8afbe..1893925f3 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -169,7 +169,7 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t clus break; } if (attrs) { - ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr)); + ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, 0, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr)); } } @@ -306,10 +306,10 @@ void sendHueUpdate(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uin } if (z_cat >= 0) { uint8_t endpoint = 0; - if (!groupaddr) { + if (shortaddr) { endpoint = zigbee_devices.findFirstEndpoint(shortaddr); } - if ((endpoint) || (groupaddr)) { // send only if we know the endpoint + if ((!shortaddr) || (endpoint)) { // send if group address or endpoint is known zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms, cluster, endpoint, z_cat, 0 /* value */, &Z_ReadAttrCallback); if (shortaddr) { // reachability test is not possible for group addresses, since we don't know the list of devices in the group zigbee_devices.setTimer(shortaddr, groupaddr, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, cluster, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 1c4f782b4..fc93e8a8d 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -56,7 +56,7 @@ typedef struct Zigbee_Instruction_Type { } Zigbee_Instruction_Type; enum Zigbee_StateMachine_Instruction_Set { - // 2 bytes instructions + // 4 bytes instructions ZGB_INSTR_4_BYTES = 0, ZGB_INSTR_NOOP = 0, // do nothing ZGB_INSTR_LABEL, // define a label @@ -67,7 +67,7 @@ enum Zigbee_StateMachine_Instruction_Set { ZGB_INSTR_WAIT_FOREVER, // wait forever but state machine still active ZGB_INSTR_STOP, // stop state machine with optional error code - // 6 bytes instructions + // 8 bytes instructions ZGB_INSTR_8_BYTES = 0x80, ZGB_INSTR_CALL = 0x80, // call a function ZGB_INSTR_LOG, // log a message, if more detailed logging required, call a function @@ -77,7 +77,7 @@ enum Zigbee_StateMachine_Instruction_Set { ZGB_INSTR_WAIT_RECV, // wait for a message according to the filter ZGB_ON_RECV_UNEXPECTED, // function to handle unexpected messages, or nullptr - // 10 bytes instructions + // 12 bytes instructions ZGB_INSTR_12_BYTES = 0xF0, ZGB_INSTR_WAIT_RECV_CALL, // wait for a filtered message and call function upon receive }; diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index cc95d4ed0..7de0d56f4 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -388,6 +388,7 @@ int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { return -1; } + // // Handle Unbind Rsp incoming message // @@ -413,6 +414,72 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { return -1; } +// +// Handle MgMt Bind Rsp incoming message +// +int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { + uint16_t shortaddr = buf.get16(2); + uint8_t status = buf.get8(4); + uint8_t bind_total = buf.get8(5); + uint8_t bind_start = buf.get8(6); + uint8_t bind_len = buf.get8(7); + + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND_STATE "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + ",\"BindingsTotal\":%d" + //",\"BindingsStart\":%d" + ",\"Bindings\":[" + ), status, getZigbeeStatusMessage(status).c_str(), bind_total); + + uint32_t idx = 8; + for (uint32_t i = 0; i < bind_len; i++) { + if (idx + 14 > buf.len()) { break; } // overflow, frame size is between 14 and 21 + + //uint64_t srcaddr = buf.get16(idx); // unused + uint8_t srcep = buf.get8(idx + 8); + uint8_t cluster = buf.get16(idx + 9); + uint8_t addrmode = buf.get8(idx + 11); + uint16_t group = 0x0000; + uint64_t dstaddr = 0; + uint8_t dstep = 0x00; + if (Z_Addr_Group == addrmode) { // Group address mode + group = buf.get16(idx + 12); + idx += 14; + } else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode + dstaddr = buf.get64(idx + 12); + dstep = buf.get8(idx + 20); + idx += 21; + } else { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Z_MgmtBindRsp unknwon address mode %d"), addrmode); + break; // abort for any other value since we don't know the length of the field + } + + if (i > 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"Cluster\":\"0x%04X\",\"Endpoint\":%d,"), cluster, srcep); + if (Z_Addr_Group == addrmode) { // Group address mode + ResponseAppend_P(PSTR("\"ToGroup\":%d}"), group); + } else if (Z_Addr_IEEEAddress == addrmode) { // IEEE address mode + char hex[20]; + Uint64toHex(dstaddr, hex, 64); + ResponseAppend_P(PSTR("\"ToDevice\":\"0x%s\",\"ToEndpoint\":%d}"), hex, dstep); + } + } + + ResponseAppend_P(PSTR("]}}")); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_BIND_STATE)); + XdrvRulesProcess(); + + return -1; +} /*********************************************************************************************\ * Send specific ZNP messages @@ -579,6 +646,7 @@ ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4 ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 ZBM(AREQ_ZDO_UNBIND_RSP, Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP) // 45A2 +ZBM(AREQ_ZDO_MGMT_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP) // 45B3 // Dispatcher callbacks table const Z_Dispatcher Z_DispatchTable[] PROGMEM = { @@ -592,6 +660,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, { AREQ_ZDO_UNBIND_RSP, &Z_UnbindRsp }, + { AREQ_ZDO_MGMT_BIND_RSP, &Z_MgmtBindRsp }, }; /*********************************************************************************************\ @@ -643,6 +712,7 @@ void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) { zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, wait_ms, 0x0300, endpoint, Z_CAT_NONE, 0 /* value */, &Z_ReadAttrCallback); wait_ms += inter_message_ms; zigbee_devices.setTimer(shortaddr, 0, wait_ms + Z_CAT_REACHABILITY_TIMEOUT, 0, endpoint, Z_CAT_REACHABILITY, 0 /* value */, &Z_Unreachable); + wait_ms += 1000; // wait 1 second between devices } } } diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 423ac43f1..163580255 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -35,7 +35,7 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" - D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE + D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE ; void (* const ZigbeeCommand[])(void) PROGMEM = { @@ -44,7 +44,7 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, - &CmndZbLight, CmndZbRestore, + &CmndZbLight, &CmndZbRestore, &CmndZbBindState, }; // @@ -294,12 +294,12 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { // - transacId: 8-bits, transation id of message (should be incremented at each message), used both for Zigbee message number and ZCL message number // Returns: None // -void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { +void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, uint16_t manuf, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { SBuffer buf(32+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST_EXT); // 02 - if (groupaddr) { + if (0x0000 == shortaddr) { // if no shortaddr we assume group address buf.add8(Z_Addr_Group); // 01 buf.add64(groupaddr); // group address, only 2 LSB, upper 6 MSB are discarded buf.add8(0xFF); // dest endpoint is not used for group addresses @@ -315,8 +315,11 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI buf.add8(0x30); // 30 options buf.add8(0x1E); // 1E radius - buf.add16(3 + len); - buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field + buf.add16(3 + len + (manuf ? 2 : 0)); + buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00) | (manuf ? 0x04 : 0x00)); // Frame Control Field + if (manuf) { + buf.add16(manuf); // add Manuf Id if not null + } buf.add8(transacId); // Transaction Sequance Number buf.add8(cmdId); if (len > 0) { @@ -342,7 +345,7 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI // - param: pointer to HEX string for payload, should not be nullptr // Returns: None // -void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, +void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, bool clusterSpecific, uint16_t manuf, uint16_t cluster, uint8_t cmd, const char *param) { size_t size = param ? strlen(param) : 0; SBuffer buf((size+2)/2); // actual bytes buffer for data @@ -368,7 +371,7 @@ void zigbeeZCLSendStr(uint16_t shortaddr, uint16_t groupaddr, uint8_t endpoint, } // everything is good, we can send the command - ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr)); + ZigbeeZCLSend_Raw(shortaddr, groupaddr, cluster, endpoint, cmd, clusterSpecific, manuf, buf.getBuffer(), buf.len(), true, zigbee_devices.getNextSeqNumber(shortaddr)); // now set the timer, if any, to read back the state later if (clusterSpecific) { zigbeeSetCommandTimer(shortaddr, groupaddr, cluster, endpoint); @@ -397,9 +400,10 @@ void CmndZbSend(void) { // params static char delim[] = ", "; // delimiters for parameters - uint16_t device = 0x0000; // 0xFFFF is broadcast, so considered valid - uint16_t groupaddr = 0x0000; // ignore group address if 0x0000 + uint16_t device = 0x0000; // 0x0000 is local, so considered invalid + uint16_t groupaddr = 0x0000; // group address uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + uint16_t manuf = 0x0000; // Manuf Id in ZCL frame // Command elements uint16_t cluster = 0; uint8_t cmd = 0; @@ -408,19 +412,25 @@ void CmndZbSend(void) { bool clusterSpecific = true; // parse JSON - const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group")); - if (nullptr != &val_group) { groupaddr = strToUInt(val_group); } - if (0x0000 == groupaddr) { // if no group address, we need a device address - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + } + if (0x0000 == device) { // if not found, check if we have a group + const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group")); + if (nullptr != &val_group) { + groupaddr = strToUInt(val_group); + } else { // no device nor group + ResponseCmndChar_P(PSTR("Unknown device")); + return; } - if ((nullptr == &val_device) || (0x0000 == device)) { ResponseCmndChar_P(PSTR("Unknown device")); return; } } const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf")); + if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); } const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); if (nullptr != &val_cmd) { // probe the type of the argument @@ -523,7 +533,7 @@ void CmndZbSend(void) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLSend device: 0x%04X, group: 0x%04X, endpoint:%d, cluster:0x%04X, cmd:0x%02X, send:\"%s\""), device, groupaddr, endpoint, cluster, cmd, cmd_s); - zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, cluster, cmd, cmd_s); + zigbeeZCLSendStr(device, groupaddr, endpoint, clusterSpecific, manuf, cluster, cmd, cmd_s); ResponseCmndDone(); } else { Response_P(PSTR("Missing zigbee 'Send'")); @@ -639,6 +649,26 @@ void CmndZbUnbind(void) { ZbBindUnbind(true); } +// +// Command `ZbBindState` +// +void CmndZbBindState(void) { + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + + SBuffer buf(10); + buf.add8(Z_SREQ | Z_ZDO); // 25 + buf.add8(ZDO_MGMT_BIND_REQ); // 33 + buf.add16(shortaddr); // shortaddr + buf.add8(0); // StartIndex = 0 + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + + ResponseCmndDone(); +} + // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { CmndZbProbeOrPing(true); @@ -865,24 +895,31 @@ void CmndZbRead(void) { uint16_t groupaddr = 0x0000; // if 0x0000 ignore group adress uint16_t cluster = 0x0000; // default to general cluster uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + uint16_t manuf = 0x0000; // Manuf Id in ZCL frame size_t attrs_len = 0; uint8_t* attrs = nullptr; // empty string is valid - const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group")); - if (nullptr != &val_group) { groupaddr = strToUInt(val_group); } - if (0x0000 == groupaddr) { // if no group address, we need a device address - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar_P(PSTR("Invalid parameter")); return; } + } + if (0x0000 == device) { // if not found, check if we have a group + const JsonVariant &val_group = getCaseInsensitive(json, PSTR("Group")); + if (nullptr != &val_group) { + groupaddr = strToUInt(val_group); + } else { // no device nor group + ResponseCmndChar_P(PSTR("Unknown device")); + return; } - if ((nullptr == &val_device) || (0x0000 == device)) { ResponseCmndChar_P(PSTR("Unknown device")); return; } } const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_manuf = getCaseInsensitive(json, PSTR("Manuf")); + if (nullptr != &val_manuf) { manuf = strToUInt(val_manuf); } const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); if (nullptr != &val_attr) { @@ -910,12 +947,12 @@ void CmndZbRead(void) { endpoint = zigbee_devices.findFirstEndpoint(device); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } - if (groupaddr) { + if (0x0000 == device) { endpoint = 0xFF; // endpoint not used for group addresses } if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend_Raw(device, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); + ZigbeeZCLSend_Raw(device, groupaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, manuf, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); ResponseCmndDone(); } else { ResponseCmndChar_P(PSTR("Missing parameters")); From 86667651080199f6d786d488459f8cdc147a62a5 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 30 Mar 2020 21:38:48 +0200 Subject: [PATCH 40/56] Zigbee change boolean attributes to int BREAKING CHANGE, "Power" attribute will be reported as `0`/`1` insteas of `false`/`true` --- tasmota/xdrv_23_zigbee_5_converters.ino | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index edd5ab682..7a8ea4806 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -202,13 +202,6 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer case 0xFF: // unk break; case 0x10: // bool - { - uint8_t val_bool = buf.get8(i++); - if (0xFF != val_bool) { - json[attrid_str] = (bool) (val_bool ? true : false); - } - } - break; case 0x20: // uint8 case 0x30: // enum8 { From eccd5cdd19270a7a652b51c2fe25b56cc6b99216 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 31 Mar 2020 13:01:50 +0200 Subject: [PATCH 41/56] Refactor web command history --- tasmota/xdrv_01_webserver.ino | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index ea874b7f2..1bfc841c2 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -211,18 +211,21 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "lt=setTimeout(l,%d);" "return false;" "}" + "wl(l);" // Load initial console text - // Console command history - part 2 + // Console command history "var hc=[],cn=0;" // hc = History commands, cn = Number of history being shown - "function cH(a){" - "var b=qs('#c1'),c=a.keyCode;" // c1 = Console command id - "if(38==c||40==c){b.autocomplete='off';}" // Arrow up or down must be a keyboard so stop browser autocomplete - "38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // Arrow Up - "40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // Arrow Down - "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter, 19 = Max number -1 of commands in history + "function h(){" +// "if(!(navigator.maxTouchPoints||'ontouchstart'in document.documentElement)){eb('c1').autocomplete='off';}" // No touch so stop browser autocomplete + "eb('c1').addEventListener('keydown',function(e){" + "var b=eb('c1'),c=e.keyCode;" // c1 = Console command id + "if(38==c||40==c){b.autocomplete='off';}" // ArrowUp or ArrowDown must be a keyboard so stop browser autocomplete + "38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // ArrowUp + "40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // ArrowDown + "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter, 19 = Max number -1 of commands in history + "});" "}" - - "wl(l);"; + "wl(h);"; // Add console command key eventlistener after name has been synced with id (= wl(jd)) const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM = "}2%d'>%s (%d}3"; // }2 and }3 are used in below os.replace @@ -340,12 +343,6 @@ const char HTTP_HEAD_LAST_SCRIPT[] PROGMEM = "}" "t++;" "}" - - // Console command history - part 1 - "if(qs('#c1')){" // c1 = Console command id - "qs('#c1').addEventListener('keydown',cH);" - "}" - "}" "wl(jd);" // Add name='' to any id='' in input,button,textarea,select ""; From 7ebb5f3cb9c8eef0eec1033cf3d72006006f4b02 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 31 Mar 2020 16:30:30 +0200 Subject: [PATCH 42/56] Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c4c1c4c61..6d4c9c1c7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -59,6 +59,8 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix Zigbee sending wrong Sat value with Hue emulation - Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add Zigbee command ``ZbUnbind`` +- Add Zigbee command ``ZbBindState`` and ``manuf``attribute +- Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index affa7f008..59985d6fc 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,7 +3,8 @@ ### 8.2.0.3 20200329 - Add support for longer template names -- Add Zigbee commands ``ZbBindState`` and ``manuf``attribute +- Add Zigbee command ``ZbBindState`` and ``manuf``attribute +- Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) ### 8.2.0.2 20200328 @@ -15,7 +16,7 @@ - Change HM-10 sensor type detection and add features (#7962) - Fix possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation -- Add ZIgbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` +- Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add Zigbee command ``ZbUnbind`` - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) From 39d8011c89807e4490342c7de13af3d524c937bc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 31 Mar 2020 17:27:33 +0200 Subject: [PATCH 43/56] Change light scheme 2,3,4 cycle time Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 9 +++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6d4c9c1c7..23bd31fef 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,6 +55,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.2.0.3 - Change HM-10 sensor type detection and add features (#7962) +- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) - Fix possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation - Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 59985d6fc..bfd407b22 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,7 @@ ### 8.2.0.3 20200329 +- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) - Add support for longer template names - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 6b72da9b2..174ef74a9 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1612,8 +1612,9 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = void LightCycleColor(int8_t direction) { - if (Light.strip_timer_counter % (Settings.light_speed * 2)) { - return; + if (Settings.light_speed > 3) { +// if (Light.strip_timer_counter % (Settings.light_speed * 2)) { return; } + if (Light.strip_timer_counter % (Settings.light_speed - 2)) { return; } // Speed 4: 24sec, 5: 36sec, 6: 48sec, etc } if (0 == direction) { @@ -1630,7 +1631,11 @@ void LightCycleColor(int8_t direction) // direction = (Light.random < Light.wheel) ? -1 : 1; direction = (Light.random &0x01) ? 1 : -1; } + + if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } // Speed 1: 12/3=4sec, 2: 12/2=6sec, 3: 12sec +// if (Settings.light_speed < 3) { direction <<= (3 - Settings.light_speed); } // Speed 1: 12/4=3sec, 2: 12/2=6sec, 3: 12sec Light.wheel += direction; + uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: random %d, wheel %d, hue %d"), Light.random, Light.wheel, hue); From e319f4ec40aa06907b4e280fd8f292cff821de1a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 31 Mar 2020 17:36:23 +0200 Subject: [PATCH 44/56] Refactor light --- tasmota/xdrv_04_light.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 174ef74a9..a3f7a6be5 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1612,8 +1612,8 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = void LightCycleColor(int8_t direction) { +// if (Light.strip_timer_counter % (Settings.light_speed * 2)) { return; } // Speed 1: 24sec, 2: 48sec, 3: 72sec, etc if (Settings.light_speed > 3) { -// if (Light.strip_timer_counter % (Settings.light_speed * 2)) { return; } if (Light.strip_timer_counter % (Settings.light_speed - 2)) { return; } // Speed 4: 24sec, 5: 36sec, 6: 48sec, etc } @@ -1632,10 +1632,9 @@ void LightCycleColor(int8_t direction) direction = (Light.random &0x01) ? 1 : -1; } - if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } // Speed 1: 12/3=4sec, 2: 12/2=6sec, 3: 12sec // if (Settings.light_speed < 3) { direction <<= (3 - Settings.light_speed); } // Speed 1: 12/4=3sec, 2: 12/2=6sec, 3: 12sec + if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } // Speed 1: 12/3=4sec, 2: 12/2=6sec, 3: 12sec Light.wheel += direction; - uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: random %d, wheel %d, hue %d"), Light.random, Light.wheel, hue); From a515a10c4250c6fdab42f5263af0b02423fb3a13 Mon Sep 17 00:00:00 2001 From: Markus Peter Date: Tue, 31 Mar 2020 18:04:32 +0200 Subject: [PATCH 45/56] Use unicode decimal code for shutter buttons Use unicode decimal code for up and down triangles in shutter button labels instead of unicode character --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 1bfc841c2..3521c0adb 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1178,7 +1178,7 @@ void HandleRoot(void) int32_t ShutterWebButton; if (ShutterWebButton = IsShutterWebButton(idx)) { WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "â–¼" : "â–²") : ((ShutterWebButton>0) ? "â–²" : "â–¼"))), + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), ""); continue; } From f46923ba1e53d5da4e12d2ddadccb0969a34c2f3 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 31 Mar 2020 23:04:17 +0200 Subject: [PATCH 46/56] Change remove floating point libs from IRAM --- platformio.ini | 3 +- tasmota/CHANGELOG.md | 1 + tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM | 336 ++++++++++++++++++++++ tasmota/ld/eagle.rom.addr.v6.ld | 352 ++++++++++++++++++++++++ 4 files changed, 691 insertions(+), 1 deletion(-) create mode 100644 tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM create mode 100644 tasmota/ld/eagle.rom.addr.v6.ld diff --git a/platformio.ini b/platformio.ini index 2c78a4583..6b0bb6edc 100755 --- a/platformio.ini +++ b/platformio.ini @@ -57,7 +57,8 @@ default_envs = framework = arduino board = esp01_1m board_build.flash_mode = dout -board_build.ldscript = eagle.flash.1m.ld +; board_build.ldscript = eagle.flash.1m.ld +board_build.ldscript = ${PROJECTSRC_DIR}/ld/eagle.flash.1m.ld_FP_IN_IROM platform = ${core_active.platform} platform_packages = ${core_active.platform_packages} diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index bfd407b22..cf6941a6d 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Add support for longer template names - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) +- Change remove floating point libs from IRAM ### 8.2.0.2 20200328 diff --git a/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM b/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM new file mode 100644 index 000000000..3e338cebd --- /dev/null +++ b/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM @@ -0,0 +1,336 @@ +/* Flash Split for 1M chips */ +/* sketch @0x40200000 (~999KB) (1023984B) */ +/* empty @0x402F9FF0 (~4KB) (4112B) */ +/* spiffs @0x402FB000 (~0KB) (0B) */ +/* eeprom @0x402FB000 (4KB) */ +/* rfcal @0x402FC000 (4KB) */ +/* wifi @0x402FD000 (12KB) */ + +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40201010, len = 0xf9ff0 +} + +PROVIDE ( _FS_start = 0x402FB000 ); +PROVIDE ( _FS_end = 0x402FB000 ); +PROVIDE ( _FS_page = 0x0 ); +PROVIDE ( _FS_block = 0x0 ); +PROVIDE ( _EEPROM_start = 0x402fb000 ); +/* The following symbols are DEPRECATED and will be REMOVED in a future release */ +PROVIDE ( _SPIFFS_start = 0x402FB000 ); +PROVIDE ( _SPIFFS_end = 0x402FB000 ); +PROVIDE ( _SPIFFS_page = 0x0 ); +PROVIDE ( _SPIFFS_block = 0x0 ); + +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(app_entry) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +EXTERN(core_version) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + . = ALIGN(4); + _Pri_3_HandlerAddress = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .noinit : ALIGN(4) + { + *(.noinit) + } >dram0_0_seg :dram0_0_phdr + + /* IRAM is split into .text and .text1 to allow for moving specific */ + /* functions into IRAM that would be matched by the irom0.text matcher */ + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + + *(.text.app_entry*) /* The main startup code */ + + *(.text.gdbstub*, .text.gdb_init) /* Any GDB hooks */ + + /* all functional callers are placed in IRAM (including SPI/IRQ callbacks/etc) here */ + *(.text._ZNKSt8functionIF*EE*) /* std::function::operator()() const */ + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.ver_number) + *.c.o(.literal*, .text*) + *.cpp.o(EXCLUDE_FILE (umm_malloc.cpp.o) .literal*, EXCLUDE_FILE (umm_malloc.cpp.o) .text*) + *.cc.o(.literal*, .text*) +/* #ifdef VTABLES_IN_FLASH */ + *(.rodata._ZTV*) /* C++ vtables */ +/* #endif */ + + *libgcc.a:unwind-dw2.o(.literal .text .rodata .literal.* .text.* .rodata.*) + *libgcc.a:unwind-dw2-fde.o(.literal .text .rodata .literal.* .text.* .rodata.*) + + *libc.a:(.literal .text .literal.* .text.*) + *libm.a:(.literal .text .literal.* .text.*) +/* #ifdef FP_IN_IROM */ + *libgcc.a:*f2.o(.literal .text) + *libgcc.a:*f3.o(.literal .text) + *libgcc.a:*fsi.o(.literal .text) + *libgcc.a:*fdi.o(.literal .text) + *libgcc.a:*ifs.o(.literal .text) + *libgcc.a:*idf.o(.literal .text) +/* #endif */ + *libgcc.a:_umoddi3.o(.literal .text) + *libgcc.a:_udivdi3.o(.literal .text) + *libstdc++.a:( .literal .text .literal.* .text.*) + *libstdc++-exc.a:( .literal .text .literal.* .text.*) + *libsmartconfig.a:(.literal .text .literal.* .text.*) + *liblwip_gcc.a:(.literal .text .literal.* .text.*) + *liblwip_src.a:(.literal .text .literal.* .text.*) + *liblwip2-536.a:(.literal .text .literal.* .text.*) + *liblwip2-1460.a:(.literal .text .literal.* .text.*) + *liblwip2-536-feat.a:(.literal .text .literal.* .text.*) + *liblwip2-1460-feat.a:(.literal .text .literal.* .text.*) + *liblwip6-536-feat.a:(.literal .text .literal.* .text.*) + *liblwip6-1460-feat.a:(.literal .text .literal.* .text.*) + *libbearssl.a:(.literal .text .literal.* .text.*) + *libaxtls.a:(.literal .text .literal.* .text.*) + *libat.a:(.literal.* .text.*) + *libcrypto.a:(.literal.* .text.*) + *libespnow.a:(.literal.* .text.*) + *libjson.a:(.literal.* .text.*) + *liblwip.a:(.literal.* .text.*) + *libmesh.a:(.literal.* .text.*) + *libnet80211.a:(.literal.* .text.*) + *libsmartconfig.a:(.literal.* .text.*) + *libssl.a:(.literal.* .text.*) + *libupgrade.a:(.literal.* .text.*) + *libwpa.a:(.literal.* .text.*) + *libwpa2.a:(.literal.* .text.*) + *libwps.a:(.literal.* .text.*) + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom0.text.* .irom.text .irom.text.*) + + /* Constant strings in flash (PSTRs) */ + *(.irom0.pstr.*) + + /* __FUNCTION__ locals */ + *(.rodata._ZZ*__FUNCTION__) + *(.rodata._ZZ*__PRETTY_FUNCTION__) + *(.rodata._ZZ*__func__) + + /* std::* exception strings, in their own section to allow string coalescing */ + *(.irom.exceptiontext) + + /* c++ typeof IDs, etc. */ + *(.rodata._ZTIN* .rodata._ZTSN10* .rodata._ZTISt* .rodata._ZTSSt*) + + /* Fundamental type info */ + *(.rodata._ZTIPKc .rodata._ZTIc .rodata._ZTIv .rodata._ZTSv .rodata._ZTSc .rodata._ZTSPKc .rodata._ZTSi .rodata._ZTIi) + + . = ALIGN(4); + *(.gcc_except_table .gcc_except_table.*) + . = ALIGN(4); + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; /* Add a 0 entry to terminate the list */ + + _irom0_text_end = ABSOLUTE(.); + _flash_code_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr + + + + .text1 : ALIGN(4) + { + *(.literal .text .iram.literal .iram.text .iram.text.* .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.sdk.version) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + . = (. + 3) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/tasmota/ld/eagle.rom.addr.v6.ld b/tasmota/ld/eagle.rom.addr.v6.ld new file mode 100644 index 000000000..84c5e3acf --- /dev/null +++ b/tasmota/ld/eagle.rom.addr.v6.ld @@ -0,0 +1,352 @@ +PROVIDE ( Cache_Read_Disable = 0x400047f0 ); +PROVIDE ( Cache_Read_Enable = 0x40004678 ); +PROVIDE ( FilePacketSendReqMsgProc = 0x400035a0 ); +PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000368c ); +PROVIDE ( FlashDwnLdStartMsgProc = 0x40003538 ); +PROVIDE ( FlashDwnLdStopReqMsgProc = 0x40003658 ); +PROVIDE ( GetUartDevice = 0x40003f4c ); +PROVIDE ( MD5Final = 0x40009900 ); +PROVIDE ( MD5Init = 0x40009818 ); +PROVIDE ( MD5Update = 0x40009834 ); +PROVIDE ( MemDwnLdStartMsgProc = 0x400036c4 ); +PROVIDE ( MemDwnLdStopReqMsgProc = 0x4000377c ); +PROVIDE ( MemPacketSendReqMsgProc = 0x400036f0 ); +PROVIDE ( RcvMsg = 0x40003eac ); +PROVIDE ( SHA1Final = 0x4000b648 ); +PROVIDE ( SHA1Init = 0x4000b584 ); +PROVIDE ( SHA1Transform = 0x4000a364 ); +PROVIDE ( SHA1Update = 0x4000b5a8 ); +PROVIDE ( SPI_read_status = 0x400043c8 ); +PROVIDE ( SPI_write_status = 0x40004400 ); +PROVIDE ( SPI_write_enable = 0x4000443c ); +PROVIDE ( Wait_SPI_Idle = 0x4000448c ); +PROVIDE ( Enable_QMode = 0x400044c0 ); +PROVIDE ( SPIEraseArea = 0x40004b44 ); +PROVIDE ( SPIEraseBlock = 0x400049b4 ); +PROVIDE ( SPIEraseChip = 0x40004984 ); +PROVIDE ( SPIEraseSector = 0x40004a00 ); +PROVIDE ( SPILock = 0x400048a8 ); +PROVIDE ( SPIParamCfg = 0x40004c2c ); +PROVIDE ( SPIRead = 0x40004b1c ); +PROVIDE ( SPIReadModeCnfig = 0x400048ec ); +PROVIDE ( SPIUnlock = 0x40004878 ); +PROVIDE ( SPIWrite = 0x40004a4c ); +PROVIDE ( SelectSpiFunction = 0x40003f58 ); +PROVIDE ( SendMsg = 0x40003cf4 ); +PROVIDE ( UartConnCheck = 0x40003230 ); +PROVIDE ( UartConnectProc = 0x400037a0 ); +PROVIDE ( UartDwnLdProc = 0x40003368 ); +PROVIDE ( UartGetCmdLn = 0x40003ef4 ); +PROVIDE ( UartRegReadProc = 0x4000381c ); +PROVIDE ( UartRegWriteProc = 0x400037ac ); +PROVIDE ( UartRxString = 0x40003c30 ); +PROVIDE ( Uart_Init = 0x40003a14 ); +PROVIDE ( _ResetHandler = 0x400000a4 ); +PROVIDE ( _ResetVector = 0x40000080 ); +PROVIDE ( __adddf3 = 0x4000c538 ); +PROVIDE ( __addsf3 = 0x4000c180 ); +PROVIDE ( __divdf3 = 0x4000cb94 ); +PROVIDE ( __divdi3 = 0x4000ce60 ); +PROVIDE ( __divsi3 = 0x4000dc88 ); +PROVIDE ( __extendsfdf2 = 0x4000cdfc ); +PROVIDE ( __fixdfsi = 0x4000ccb8 ); +PROVIDE ( __fixunsdfsi = 0x4000cd00 ); +PROVIDE ( __fixunssfsi = 0x4000c4c4 ); +PROVIDE ( __floatsidf = 0x4000e2f0 ); +PROVIDE ( __floatsisf = 0x4000e2ac ); +PROVIDE ( __floatunsidf = 0x4000e2e8 ); +PROVIDE ( __floatunsisf = 0x4000e2a4 ); +PROVIDE ( __muldf3 = 0x4000c8f0 ); +PROVIDE ( __muldi3 = 0x40000650 ); +PROVIDE ( __mulsf3 = 0x4000c3dc ); +PROVIDE ( __subdf3 = 0x4000c688 ); +PROVIDE ( __subsf3 = 0x4000c268 ); +PROVIDE ( __truncdfsf2 = 0x4000cd5c ); +PROVIDE ( __udivdi3 = 0x4000d310 ); +PROVIDE ( __udivsi3 = 0x4000e21c ); +PROVIDE ( __umoddi3 = 0x4000d770 ); +PROVIDE ( __umodsi3 = 0x4000e268 ); +PROVIDE ( __umulsidi3 = 0x4000dcf0 ); +PROVIDE ( _rom_store = 0x4000e388 ); +PROVIDE ( _rom_store_table = 0x4000e328 ); +PROVIDE ( _start = 0x4000042c ); +PROVIDE ( _xtos_alloca_handler = 0x4000dbe0 ); +PROVIDE ( _xtos_c_wrapper_handler = 0x40000598 ); +PROVIDE ( _xtos_cause3_handler = 0x40000590 ); +PROVIDE ( _xtos_ints_off = 0x4000bda4 ); +PROVIDE ( _xtos_ints_on = 0x4000bd84 ); +PROVIDE ( _xtos_l1int_handler = 0x4000048c ); +PROVIDE ( _xtos_p_none = 0x4000dbf8 ); +PROVIDE ( _xtos_restore_intlevel = 0x4000056c ); +PROVIDE ( _xtos_return_from_exc = 0x4000dc54 ); +PROVIDE ( _xtos_set_exception_handler = 0x40000454 ); +PROVIDE ( _xtos_set_interrupt_handler = 0x4000bd70 ); +PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bd28 ); +PROVIDE ( _xtos_set_intlevel = 0x4000dbfc ); +PROVIDE ( _xtos_set_min_intlevel = 0x4000dc18 ); +PROVIDE ( _xtos_set_vpri = 0x40000574 ); +PROVIDE ( _xtos_syscall_handler = 0x4000dbe4 ); +PROVIDE ( _xtos_unhandled_exception = 0x4000dc44 ); +PROVIDE ( _xtos_unhandled_interrupt = 0x4000dc3c ); +PROVIDE ( aes_decrypt = 0x400092d4 ); +PROVIDE ( aes_decrypt_deinit = 0x400092e4 ); +PROVIDE ( aes_decrypt_init = 0x40008ea4 ); +PROVIDE ( aes_unwrap = 0x40009410 ); +PROVIDE ( base64_decode = 0x40009648 ); +PROVIDE ( base64_encode = 0x400094fc ); +PROVIDE ( bzero = 0x4000de84 ); +PROVIDE ( cmd_parse = 0x40000814 ); +PROVIDE ( conv_str_decimal = 0x40000b24 ); +PROVIDE ( conv_str_hex = 0x40000cb8 ); +PROVIDE ( convert_para_str = 0x40000a60 ); +PROVIDE ( dtm_get_intr_mask = 0x400026d0 ); +PROVIDE ( dtm_params_init = 0x4000269c ); +PROVIDE ( dtm_set_intr_mask = 0x400026c8 ); +PROVIDE ( dtm_set_params = 0x400026dc ); +PROVIDE ( eprintf = 0x40001d14 ); +PROVIDE ( eprintf_init_buf = 0x40001cb8 ); +PROVIDE ( eprintf_to_host = 0x40001d48 ); +PROVIDE ( est_get_printf_buf_remain_len = 0x40002494 ); +PROVIDE ( est_reset_printf_buf_len = 0x4000249c ); +PROVIDE ( ets_bzero = 0x40002ae8 ); +PROVIDE ( ets_char2xdigit = 0x40002b74 ); +PROVIDE ( ets_delay_us = 0x40002ecc ); +PROVIDE ( ets_enter_sleep = 0x400027b8 ); +PROVIDE ( ets_external_printf = 0x40002578 ); +PROVIDE ( ets_get_cpu_frequency = 0x40002f0c ); +PROVIDE ( ets_getc = 0x40002bcc ); +PROVIDE ( ets_install_external_printf = 0x40002450 ); +PROVIDE ( ets_install_putc1 = 0x4000242c ); +PROVIDE ( ets_install_putc2 = 0x4000248c ); +PROVIDE ( ets_install_uart_printf = 0x40002438 ); +/* Undocumented function to print character to UART */ +PROVIDE ( ets_uart_putc1 = 0x40001dcc ); +/* permanently hide reimplemented ets_intr_*lock(), see #6484 +PROVIDE ( ets_intr_lock = 0x40000f74 ); +PROVIDE ( ets_intr_unlock = 0x40000f80 ); +*/ +PROVIDE ( ets_isr_attach = 0x40000f88 ); +PROVIDE ( ets_isr_mask = 0x40000f98 ); +PROVIDE ( ets_isr_unmask = 0x40000fa8 ); +PROVIDE ( ets_memcmp = 0x400018d4 ); +PROVIDE ( ets_memcpy = 0x400018b4 ); +PROVIDE ( ets_memmove = 0x400018c4 ); +PROVIDE ( ets_memset = 0x400018a4 ); +/* renamed to ets_post_rom(), see #6484 +PROVIDE ( ets_post = 0x40000e24 ); +*/ +PROVIDE ( ets_post_rom = 0x40000e24 ); +PROVIDE ( ets_printf = 0x400024cc ); +PROVIDE ( ets_putc = 0x40002be8 ); +PROVIDE ( ets_rtc_int_register = 0x40002a40 ); +PROVIDE ( ets_run = 0x40000e04 ); +PROVIDE ( ets_set_idle_cb = 0x40000dc0 ); +PROVIDE ( ets_set_user_start = 0x40000fbc ); +PROVIDE ( ets_str2macaddr = 0x40002af8 ); +PROVIDE ( ets_strcmp = 0x40002aa8 ); +PROVIDE ( ets_strcpy = 0x40002a88 ); +PROVIDE ( ets_strlen = 0x40002ac8 ); +PROVIDE ( ets_strncmp = 0x40002ab8 ); +PROVIDE ( ets_strncpy = 0x40002a98 ); +PROVIDE ( ets_strstr = 0x40002ad8 ); +PROVIDE ( ets_task = 0x40000dd0 ); +PROVIDE ( ets_timer_arm = 0x40002cc4 ); +PROVIDE ( ets_timer_disarm = 0x40002d40 ); +PROVIDE ( ets_timer_done = 0x40002d80 ); +PROVIDE ( ets_timer_handler_isr = 0x40002da8 ); +PROVIDE ( ets_timer_init = 0x40002e68 ); +PROVIDE ( ets_timer_setfn = 0x40002c48 ); +PROVIDE ( ets_uart_printf = 0x40002544 ); +PROVIDE ( ets_update_cpu_frequency = 0x40002f04 ); +PROVIDE ( ets_vprintf = 0x40001f00 ); +PROVIDE ( ets_wdt_disable = 0x400030f0 ); +PROVIDE ( ets_wdt_enable = 0x40002fa0 ); +PROVIDE ( ets_wdt_get_mode = 0x40002f34 ); +PROVIDE ( ets_wdt_init = 0x40003170 ); +PROVIDE ( ets_wdt_restore = 0x40003158 ); +PROVIDE ( ets_write_char = 0x40001da0 ); +PROVIDE ( get_first_seg = 0x4000091c ); +PROVIDE ( gpio_init = 0x40004c50 ); +PROVIDE ( gpio_input_get = 0x40004cf0 ); +PROVIDE ( gpio_intr_ack = 0x40004dcc ); +PROVIDE ( gpio_intr_handler_register = 0x40004e28 ); +PROVIDE ( gpio_intr_pending = 0x40004d88 ); +PROVIDE ( gpio_intr_test = 0x40004efc ); +PROVIDE ( gpio_output_set = 0x40004cd0 ); +PROVIDE ( gpio_pin_intr_state_set = 0x40004d90 ); +PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 ); +PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 ); +PROVIDE ( gpio_register_get = 0x40004d5c ); +PROVIDE ( gpio_register_set = 0x40004d04 ); +PROVIDE ( hmac_md5 = 0x4000a2cc ); +PROVIDE ( hmac_md5_vector = 0x4000a160 ); +PROVIDE ( hmac_sha1 = 0x4000ba28 ); +PROVIDE ( hmac_sha1_vector = 0x4000b8b4 ); +PROVIDE ( lldesc_build_chain = 0x40004f40 ); +PROVIDE ( lldesc_num2link = 0x40005050 ); +PROVIDE ( lldesc_set_owner = 0x4000507c ); +PROVIDE ( main = 0x40000fec ); +PROVIDE ( md5_vector = 0x400097ac ); +PROVIDE ( mem_calloc = 0x40001c2c ); +PROVIDE ( mem_free = 0x400019e0 ); +PROVIDE ( mem_init = 0x40001998 ); +PROVIDE ( mem_malloc = 0x40001b40 ); +PROVIDE ( mem_realloc = 0x40001c6c ); +PROVIDE ( mem_trim = 0x40001a14 ); +PROVIDE ( mem_zalloc = 0x40001c58 ); +PROVIDE ( memcmp = 0x4000dea8 ); +PROVIDE ( memcpy = 0x4000df48 ); +PROVIDE ( memmove = 0x4000e04c ); +PROVIDE ( memset = 0x4000e190 ); +PROVIDE ( multofup = 0x400031c0 ); +PROVIDE ( pbkdf2_sha1 = 0x4000b840 ); +PROVIDE ( phy_get_romfuncs = 0x40006b08 ); +PROVIDE ( rand = 0x40000600 ); +PROVIDE ( rc4_skip = 0x4000dd68 ); +PROVIDE ( recv_packet = 0x40003d08 ); +PROVIDE ( remove_head_space = 0x40000a04 ); +PROVIDE ( rijndaelKeySetupDec = 0x40008dd0 ); +PROVIDE ( rijndaelKeySetupEnc = 0x40009300 ); +PROVIDE ( rom_abs_temp = 0x400060c0 ); +PROVIDE ( rom_ana_inf_gating_en = 0x40006b10 ); +PROVIDE ( rom_cal_tos_v50 = 0x40007a28 ); +PROVIDE ( rom_chip_50_set_channel = 0x40006f84 ); +PROVIDE ( rom_chip_v5_disable_cca = 0x400060d0 ); +PROVIDE ( rom_chip_v5_enable_cca = 0x400060ec ); +PROVIDE ( rom_chip_v5_rx_init = 0x4000711c ); +PROVIDE ( rom_chip_v5_sense_backoff = 0x4000610c ); +PROVIDE ( rom_chip_v5_tx_init = 0x4000718c ); +PROVIDE ( rom_dc_iq_est = 0x4000615c ); +PROVIDE ( rom_en_pwdet = 0x400061b8 ); +PROVIDE ( rom_get_bb_atten = 0x40006238 ); +PROVIDE ( rom_get_corr_power = 0x40006260 ); +PROVIDE ( rom_get_fm_sar_dout = 0x400062dc ); +PROVIDE ( rom_get_noisefloor = 0x40006394 ); +PROVIDE ( rom_get_power_db = 0x400063b0 ); +PROVIDE ( rom_i2c_readReg = 0x40007268 ); +PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c ); +PROVIDE ( rom_i2c_writeReg = 0x400072d8 ); +PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c ); +PROVIDE ( rom_iq_est_disable = 0x40006400 ); +PROVIDE ( rom_iq_est_enable = 0x40006430 ); +PROVIDE ( rom_linear_to_db = 0x40006484 ); +PROVIDE ( rom_mhz2ieee = 0x400065a4 ); +PROVIDE ( rom_pbus_dco___SA2 = 0x40007bf0 ); +PROVIDE ( rom_pbus_debugmode = 0x4000737c ); +PROVIDE ( rom_pbus_enter_debugmode = 0x40007410 ); +PROVIDE ( rom_pbus_exit_debugmode = 0x40007448 ); +PROVIDE ( rom_pbus_force_test = 0x4000747c ); +PROVIDE ( rom_pbus_rd = 0x400074d8 ); +PROVIDE ( rom_pbus_set_rxgain = 0x4000754c ); +PROVIDE ( rom_pbus_set_txgain = 0x40007610 ); +PROVIDE ( rom_pbus_workmode = 0x40007648 ); +PROVIDE ( rom_pbus_xpd_rx_off = 0x40007688 ); +PROVIDE ( rom_pbus_xpd_rx_on = 0x400076cc ); +PROVIDE ( rom_pbus_xpd_tx_off = 0x400076fc ); +PROVIDE ( rom_pbus_xpd_tx_on = 0x40007740 ); +PROVIDE ( rom_pbus_xpd_tx_on__low_gain = 0x400077a0 ); +PROVIDE ( rom_phy_reset_req = 0x40007804 ); +PROVIDE ( rom_restart_cal = 0x4000781c ); +PROVIDE ( rom_rfcal_pwrctrl = 0x40007eb4 ); +PROVIDE ( rom_rfcal_rxiq = 0x4000804c ); +PROVIDE ( rom_rfcal_rxiq_set_reg = 0x40008264 ); +PROVIDE ( rom_rfcal_txcap = 0x40008388 ); +PROVIDE ( rom_rfcal_txiq = 0x40008610 ); +PROVIDE ( rom_rfcal_txiq_cover = 0x400088b8 ); +PROVIDE ( rom_rfcal_txiq_set_reg = 0x40008a70 ); +PROVIDE ( rom_rfpll_reset = 0x40007868 ); +PROVIDE ( rom_rfpll_set_freq = 0x40007968 ); +PROVIDE ( rom_rxiq_cover_mg_mp = 0x40008b6c ); +PROVIDE ( rom_rxiq_get_mis = 0x40006628 ); +PROVIDE ( rom_sar_init = 0x40006738 ); +PROVIDE ( rom_set_ana_inf_tx_scale = 0x4000678c ); +PROVIDE ( rom_set_channel_freq = 0x40006c50 ); +PROVIDE ( rom_set_loopback_gain = 0x400067c8 ); +PROVIDE ( rom_set_noise_floor = 0x40006830 ); +PROVIDE ( rom_set_rxclk_en = 0x40006550 ); +PROVIDE ( rom_set_txbb_atten = 0x40008c6c ); +PROVIDE ( rom_set_txclk_en = 0x4000650c ); +PROVIDE ( rom_set_txiq_cal = 0x40008d34 ); +PROVIDE ( rom_start_noisefloor = 0x40006874 ); +PROVIDE ( rom_start_tx_tone = 0x400068b4 ); +PROVIDE ( rom_stop_tx_tone = 0x4000698c ); +PROVIDE ( rom_tx_mac_disable = 0x40006a98 ); +PROVIDE ( rom_tx_mac_enable = 0x40006ad4 ); +PROVIDE ( rom_txtone_linear_pwr = 0x40006a1c ); +PROVIDE ( rom_write_rfpll_sdm = 0x400078dc ); +PROVIDE ( roundup2 = 0x400031b4 ); +PROVIDE ( rtc_enter_sleep = 0x40002870 ); +PROVIDE ( rtc_get_reset_reason = 0x400025e0 ); +PROVIDE ( rtc_intr_handler = 0x400029ec ); +PROVIDE ( rtc_set_sleep_mode = 0x40002668 ); +PROVIDE ( save_rxbcn_mactime = 0x400027a4 ); +PROVIDE ( save_tsf_us = 0x400027ac ); +PROVIDE ( send_packet = 0x40003c80 ); +PROVIDE ( sha1_prf = 0x4000ba48 ); +PROVIDE ( sha1_vector = 0x4000a2ec ); +PROVIDE ( sip_alloc_to_host_evt = 0x40005180 ); +PROVIDE ( sip_get_ptr = 0x400058a8 ); +PROVIDE ( sip_get_state = 0x40005668 ); +PROVIDE ( sip_init_attach = 0x4000567c ); +PROVIDE ( sip_install_rx_ctrl_cb = 0x4000544c ); +PROVIDE ( sip_install_rx_data_cb = 0x4000545c ); +PROVIDE ( sip_post = 0x400050fc ); +PROVIDE ( sip_post_init = 0x400056c4 ); +PROVIDE ( sip_reclaim_from_host_cmd = 0x4000534c ); +PROVIDE ( sip_reclaim_tx_data_pkt = 0x400052c0 ); +PROVIDE ( sip_send = 0x40005808 ); +PROVIDE ( sip_to_host_chain_append = 0x40005864 ); +PROVIDE ( sip_to_host_evt_send_done = 0x40005234 ); +PROVIDE ( slc_add_credits = 0x400060ac ); +PROVIDE ( slc_enable = 0x40005d90 ); +PROVIDE ( slc_from_host_chain_fetch = 0x40005f24 ); +PROVIDE ( slc_from_host_chain_recycle = 0x40005e94 ); +PROVIDE ( slc_init_attach = 0x40005c50 ); +PROVIDE ( slc_init_credit = 0x4000608c ); +PROVIDE ( slc_pause_from_host = 0x40006014 ); +PROVIDE ( slc_reattach = 0x40005c1c ); +PROVIDE ( slc_resume_from_host = 0x4000603c ); +PROVIDE ( slc_select_tohost_gpio = 0x40005dc0 ); +PROVIDE ( slc_select_tohost_gpio_mode = 0x40005db8 ); +PROVIDE ( slc_send_to_host_chain = 0x40005de4 ); +PROVIDE ( slc_set_host_io_max_window = 0x40006068 ); +PROVIDE ( slc_to_host_chain_recycle = 0x40005f10 ); +PROVIDE ( software_reset = 0x4000264c ); +PROVIDE ( spi_flash_attach = 0x40004644 ); +PROVIDE ( srand = 0x400005f0 ); +PROVIDE ( strcmp = 0x4000bdc8 ); +PROVIDE ( strcpy = 0x4000bec8 ); +PROVIDE ( strlen = 0x4000bf4c ); +PROVIDE ( strncmp = 0x4000bfa8 ); +PROVIDE ( strncpy = 0x4000c0a0 ); +PROVIDE ( strstr = 0x4000e1e0 ); +PROVIDE ( timer_insert = 0x40002c64 ); +PROVIDE ( uartAttach = 0x4000383c ); +PROVIDE ( uart_baudrate_detect = 0x40003924 ); +PROVIDE ( uart_buff_switch = 0x400038a4 ); +PROVIDE ( uart_rx_intr_handler = 0x40003bbc ); +PROVIDE ( uart_rx_one_char = 0x40003b8c ); +PROVIDE ( uart_rx_one_char_block = 0x40003b64 ); +PROVIDE ( uart_rx_readbuff = 0x40003ec8 ); +PROVIDE ( uart_tx_one_char = 0x40003b30 ); +PROVIDE ( wepkey_128 = 0x4000bc40 ); +PROVIDE ( wepkey_64 = 0x4000bb3c ); +PROVIDE ( xthal_bcopy = 0x40000688 ); +PROVIDE ( xthal_copy123 = 0x4000074c ); +PROVIDE ( xthal_get_ccompare = 0x4000dd4c ); +PROVIDE ( xthal_get_ccount = 0x4000dd38 ); +PROVIDE ( xthal_get_interrupt = 0x4000dd58 ); +PROVIDE ( xthal_get_intread = 0x4000dd58 ); +PROVIDE ( xthal_memcpy = 0x400006c4 ); +PROVIDE ( xthal_set_ccompare = 0x4000dd40 ); +PROVIDE ( xthal_set_intclear = 0x4000dd60 ); +PROVIDE ( xthal_spill_registers_into_stack_nw = 0x4000e320 ); +PROVIDE ( xthal_window_spill = 0x4000e324 ); +PROVIDE ( xthal_window_spill_nw = 0x4000e320 ); + +PROVIDE ( Te0 = 0x3fffccf0 ); +PROVIDE ( Td0 = 0x3fffd100 ); +PROVIDE ( Td4s = 0x3fffd500); +PROVIDE ( rcons = 0x3fffd0f0); +PROVIDE ( UartDev = 0x3fffde10 ); +PROVIDE ( flashchip = 0x3fffc714); From ec899817aa84c07faba4f9eb2df9a2e96ce72f0b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 1 Apr 2020 14:05:30 +0200 Subject: [PATCH 47/56] Change some deepsleep wake messages - Change remove MQTT Info messages on restart for DeepSleep Wake (#8044) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) --- RELEASENOTES.md | 3 +++ tasmota/CHANGELOG.md | 4 ++- tasmota/settings.h | 2 +- tasmota/xdrv_02_mqtt.ino | 55 ++++++++++++++++++++++------------------ 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 23bd31fef..864a562e1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,12 +56,15 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change HM-10 sensor type detection and add features (#7962) - Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) +- Change remove floating point libs from IRAM +- Change remove MQTT Info messages on restart for DeepSleep Wake (#8044) - Fix possible Relay toggle on (OTA) restart - Fix Zigbee sending wrong Sat value with Hue emulation - Add Zigbee command ``ZbRestore`` to restore device configuration dumped with ``ZbStatus 2`` - Add Zigbee command ``ZbUnbind`` - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) +- Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index cf6941a6d..0b4f503bd 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,10 +3,12 @@ ### 8.2.0.3 20200329 - Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) +- Change remove floating point libs from IRAM +- Change remove MQTT Info messages on restart for DeepSleep Wake (#8044) - Add support for longer template names - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) -- Change remove floating point libs from IRAM +- Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) ### 8.2.0.2 20200328 diff --git a/tasmota/settings.h b/tasmota/settings.h index 95b4779e6..18bd7f1c6 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -109,7 +109,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - PWM Dimmer Turn red LED on when powered off uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - PWM Dimmer Buttons control remote devices uint32_t zigbee_distinct_topics : 1; // bit 7 (v8.1.0.10) - SetOption89 - Distinct MQTT topics per device for Zigbee (#7835) - uint32_t spare08 : 1; + uint32_t only_json_message : 1; // bit 8 (v8.2.0.3) - SetOption90 - Disable non-json MQTT response uint32_t spare09 : 1; uint32_t spare10 : 1; uint32_t spare11 : 1; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index ac3065fe8..912e7c929 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -440,9 +440,11 @@ void MqttPublishPowerState(uint32_t device) Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); MqttPublish(stopic); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(GetStateText(bitRead(power, device -1))); - MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN + if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(GetStateText(bitRead(power, device -1))); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN + } #ifdef USE_SONOFF_IFAN } #endif // USE_SONOFF_IFAN @@ -503,9 +505,11 @@ void MqttConnected(void) Response_P(PSTR(D_ONLINE)); MqttPublish(stopic, true); - // Satisfy iobroker (#299) - mqtt_data[0] = '\0'; - MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); + if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response + // Satisfy iobroker (#299) + mqtt_data[0] = '\0'; + MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); + } GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); @@ -526,30 +530,33 @@ void MqttConnected(void) } if (Mqtt.initial_connection_state) { - char stopic2[TOPSZ]; - Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); + if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) { + char stopic2[TOPSZ]; + Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), + ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER - if (Settings.webserver) { + if (Settings.webserver) { #if LWIP_IPV6 - Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str(),WifiGetIPv6().c_str()); + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str(),WifiGetIPv6().c_str()); #else - Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), - (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); #endif // LWIP_IPV6 = 1 - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); - } + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); + } #endif // USE_WEBSERVER - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); - if (CrashFlag()) { - CrashDump(); - } else { - ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); + if (CrashFlag()) { + CrashDump(); + } else { + ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); + } + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); } - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); + MqttPublishAllPowerState(); if (Settings.tele_period) { tele_period = Settings.tele_period -5; // Enable TelePeriod in 5 seconds From caff54da7ccadf437a1d5e4bc72599cdc0f530dc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 1 Apr 2020 14:39:43 +0200 Subject: [PATCH 48/56] Fix unquoted non-json data Fix unquoted non-json data (#8040) --- tasmota/support_tasmota.ino | 4 ++-- tasmota/xdrv_08_serial_bridge.ino | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 23a4caad7..ed0355a88 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1286,9 +1286,9 @@ void SerialInput(void) char hex_char[(serial_in_byte_counter * 2) + 2]; bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s%s%s}"), - (assume_json) ? "" : """", + (assume_json) ? "" : "\"", (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer, - (assume_json) ? "" : """"); + (assume_json) ? "" : "\""); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); XdrvRulesProcess(); serial_in_byte_counter = 0; diff --git a/tasmota/xdrv_08_serial_bridge.ino b/tasmota/xdrv_08_serial_bridge.ino index c4f530a21..990bf9c32 100644 --- a/tasmota/xdrv_08_serial_bridge.ino +++ b/tasmota/xdrv_08_serial_bridge.ino @@ -73,9 +73,9 @@ void SerialBridgeInput(void) char hex_char[(serial_bridge_in_byte_counter * 2) + 2]; bool assume_json = (!serial_bridge_raw && (serial_bridge_buffer[0] == '{')); Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":%s%s%s}"), - (assume_json) ? "" : """", + (assume_json) ? "" : "\"", (serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer, - (assume_json) ? "" : """"); + (assume_json) ? "" : "\""); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); XdrvRulesProcess(); serial_bridge_in_byte_counter = 0; From 4b09af8a36924324cd99cef91085221a0dbd3fdf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 1 Apr 2020 16:46:12 +0200 Subject: [PATCH 49/56] Add BH1750 resolution control Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 3 +- tasmota/xsns_10_bh1750.ino | 103 +++++++++++++++++++++++++++---------- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 864a562e1..44162fb7d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -65,6 +65,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) +- Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0b4f503bd..ab18b9a3e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,7 @@ - Add Zigbee command ``ZbBindState`` and ``manuf``attribute - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) +- Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) ### 8.2.0.2 20200328 diff --git a/tasmota/settings.h b/tasmota/settings.h index 18bd7f1c6..44c2e061a 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -205,8 +205,7 @@ typedef union { uint8_t spare1 : 1; uint8_t spare2 : 1; uint8_t spare3 : 1; - uint8_t spare4 : 1; - uint8_t spare5 : 1; + uint8_t bh1750_resolution : 2; // Sensor10 1,2,3 uint8_t hx711_json_weight_change : 1; // Sensor34 8,x - Enable JSON message on weight change uint8_t mhz19b_abc_disable : 1; // Disable ABC (Automatic Baseline Correction for MHZ19(B) (0 = Enabled (default), 1 = Disabled with Sensor15 command) }; diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino index 044089368..47bc6953a 100644 --- a/tasmota/xsns_10_bh1750.ino +++ b/tasmota/xsns_10_bh1750.ino @@ -31,24 +31,41 @@ #define BH1750_ADDR1 0x23 #define BH1750_ADDR2 0x5C -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms. +#define BH1750_CONTINUOUS_HIGH_RES_MODE2 0x11 // Start measurement at 0.5 lx resolution. Measurement time is approx 120ms. +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1 lx resolution. Measurement time is approx 120ms. +#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 // Start measurement at 4 lx resolution. Measurement time is approx 16ms. -uint8_t bh1750_address; -uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; -uint8_t bh1750_type = 0; -uint8_t bh1750_valid = 0; -uint16_t bh1750_illuminance = 0; -char bh1750_types[] = "BH1750"; +const char kBhMessages[] PROGMEM = "Resolution High|Resolution High2|Resolution Low"; + +struct BH1750DATA { + uint8_t address; + uint8_t addresses[2] = { BH1750_ADDR1, BH1750_ADDR2 }; + uint8_t resolution[3] = { BH1750_CONTINUOUS_HIGH_RES_MODE, BH1750_CONTINUOUS_HIGH_RES_MODE2, BH1750_CONTINUOUS_LOW_RES_MODE }; + uint8_t type = 0; + uint8_t valid = 0; + uint16_t illuminance = 0; + char types[7] = "BH1750"; +} Bh1750; + +/*********************************************************************************************/ + +bool Bh1750SetResolution(void) +{ + Wire.beginTransmission(Bh1750.address); + Wire.write(Bh1750.resolution[Settings.SensorBits1.bh1750_resolution]); + return (!Wire.endTransmission()); +} bool Bh1750Read(void) { - if (bh1750_valid) { bh1750_valid--; } + if (Bh1750.valid) { Bh1750.valid--; } - if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } - uint8_t msb = Wire.read(); - uint8_t lsb = Wire.read(); - bh1750_illuminance = ((msb << 8) | lsb) / 1.2; - bh1750_valid = SENSOR_MAX_MISS; + if (2 != Wire.requestFrom(Bh1750.address, (uint8_t)2)) { return false; } + Bh1750.illuminance = (Wire.read() << 8) | Wire.read(); + if (1 == Settings.SensorBits1.bh1750_resolution) { Bh1750.illuminance >>= 1; } + Bh1750.illuminance /= 1.2; + + Bh1750.valid = SENSOR_MAX_MISS; return true; } @@ -56,14 +73,13 @@ bool Bh1750Read(void) void Bh1750Detect(void) { - for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { - bh1750_address = bh1750_addresses[i]; - if (I2cActive(bh1750_address)) { continue; } - Wire.beginTransmission(bh1750_address); - Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); - if (!Wire.endTransmission()) { - I2cSetActiveFound(bh1750_address, bh1750_types); - bh1750_type = 1; + for (uint32_t i = 0; i < sizeof(Bh1750.addresses); i++) { + Bh1750.address = Bh1750.addresses[i]; + if (I2cActive(Bh1750.address)) { continue; } + + if (Bh1750SetResolution()) { + I2cSetActiveFound(Bh1750.address, Bh1750.types); + Bh1750.type = 1; break; } } @@ -73,23 +89,51 @@ void Bh1750EverySecond(void) { // 1mS if (!Bh1750Read()) { - AddLogMissed(bh1750_types, bh1750_valid); + AddLogMissed(Bh1750.types, Bh1750.valid); } } +/*********************************************************************************************\ + * Command Sensor10 + * + * 0 - High resolution mode (default) + * 1 - High resolution mode 2 + * 2 - Low resolution mode +\*********************************************************************************************/ + +bool Bh1750CommandSensor(void) +{ + uint32_t message_index = Settings.SensorBits1.bh1750_resolution; + if (XdrvMailbox.data_len) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + case 2: + Settings.SensorBits1.bh1750_resolution = XdrvMailbox.payload; + Bh1750SetResolution(); + message_index = Settings.SensorBits1.bh1750_resolution; + break; + } + } + char res_text[64]; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_10, GetTextIndexed(res_text, sizeof(res_text), message_index, kBhMessages)); + + return true; +} + void Bh1750Show(bool json) { - if (bh1750_valid) { + if (Bh1750.valid) { if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); + ResponseAppend_P(JSON_SNS_ILLUMINANCE, Bh1750.types, Bh1750.illuminance); #ifdef USE_DOMOTICZ if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); + DomoticzSensor(DZ_ILLUMINANCE, Bh1750.illuminance); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, Bh1750.types, Bh1750.illuminance); #endif // USE_WEBSERVER } } @@ -108,11 +152,16 @@ bool Xsns10(uint8_t function) if (FUNC_INIT == function) { Bh1750Detect(); } - else if (bh1750_type) { + else if (Bh1750.type) { switch (function) { case FUNC_EVERY_SECOND: Bh1750EverySecond(); break; + case FUNC_COMMAND_SENSOR: + if (XSNS_10 == XdrvMailbox.index) { + result = Bh1750CommandSensor(); + } + break; case FUNC_JSON_APPEND: Bh1750Show(1); break; From 49febe4a54310b5e128a16403a2f769d1182a573 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 2 Apr 2020 15:17:54 +0200 Subject: [PATCH 50/56] Add BH1750 Measurement Time control Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/xsns_10_bh1750.ino | 65 +++++++++++++++++++++++--------------- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 44162fb7d..ec242c079 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -66,6 +66,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) - Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) +- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016) - Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa - Add support for 64x48 SSD1306 OLED (#6740) - Add support for up to four MQTT GroupTopics using the same optional Device Group names (#8014) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ab18b9a3e..7dbbf3290 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -10,6 +10,7 @@ - Add commands ``CounterDebounceLow`` and ``CounterDebounceHigh`` to control debouncing (#8021) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) - Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) +- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016) ### 8.2.0.2 20200328 diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino index 47bc6953a..1ba00b46e 100644 --- a/tasmota/xsns_10_bh1750.ino +++ b/tasmota/xsns_10_bh1750.ino @@ -25,17 +25,18 @@ * I2C Address: 0x23 or 0x5C \*********************************************************************************************/ -#define XSNS_10 10 -#define XI2C_11 11 // See I2CDEVICES.md +#define XSNS_10 10 +#define XI2C_11 11 // See I2CDEVICES.md -#define BH1750_ADDR1 0x23 -#define BH1750_ADDR2 0x5C +#define BH1750_ADDR1 0x23 +#define BH1750_ADDR2 0x5C -#define BH1750_CONTINUOUS_HIGH_RES_MODE2 0x11 // Start measurement at 0.5 lx resolution. Measurement time is approx 120ms. -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1 lx resolution. Measurement time is approx 120ms. -#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 // Start measurement at 4 lx resolution. Measurement time is approx 16ms. +#define BH1750_CONTINUOUS_HIGH_RES_MODE2 0x11 // Start measurement at 0.5 lx resolution. Measurement time is approx 120ms. +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1 lx resolution. Measurement time is approx 120ms. +#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 // Start measurement at 4 lx resolution. Measurement time is approx 16ms. -const char kBhMessages[] PROGMEM = "Resolution High|Resolution High2|Resolution Low"; +#define BH1750_MEASUREMENT_TIME_HIGH 0x40 // Measurement Time register high 3 bits +#define BH1750_MEASUREMENT_TIME_LOW 0x60 // Measurement Time register low 5 bits struct BH1750DATA { uint8_t address; @@ -43,6 +44,7 @@ struct BH1750DATA { uint8_t resolution[3] = { BH1750_CONTINUOUS_HIGH_RES_MODE, BH1750_CONTINUOUS_HIGH_RES_MODE2, BH1750_CONTINUOUS_LOW_RES_MODE }; uint8_t type = 0; uint8_t valid = 0; + uint8_t mtreg = 69; // Default Measurement Time uint16_t illuminance = 0; char types[7] = "BH1750"; } Bh1750; @@ -56,14 +58,29 @@ bool Bh1750SetResolution(void) return (!Wire.endTransmission()); } +bool Bh1750SetMTreg(void) +{ + Wire.beginTransmission(Bh1750.address); + uint8_t data = BH1750_MEASUREMENT_TIME_HIGH | ((Bh1750.mtreg >> 5) & 0x07); + Wire.write(data); + if (Wire.endTransmission()) { return false; } + Wire.beginTransmission(Bh1750.address); + data = BH1750_MEASUREMENT_TIME_LOW | (Bh1750.mtreg & 0x1F); + Wire.write(data); + if (Wire.endTransmission()) { return false; } + return Bh1750SetResolution(); +} + bool Bh1750Read(void) { if (Bh1750.valid) { Bh1750.valid--; } if (2 != Wire.requestFrom(Bh1750.address, (uint8_t)2)) { return false; } Bh1750.illuminance = (Wire.read() << 8) | Wire.read(); - if (1 == Settings.SensorBits1.bh1750_resolution) { Bh1750.illuminance >>= 1; } - Bh1750.illuminance /= 1.2; + Bh1750.illuminance /= (1.2 * (69 / Bh1750.mtreg)); + if (1 == Settings.SensorBits1.bh1750_resolution) { + Bh1750.illuminance >>= 1; + } Bh1750.valid = SENSOR_MAX_MISS; return true; @@ -77,7 +94,7 @@ void Bh1750Detect(void) Bh1750.address = Bh1750.addresses[i]; if (I2cActive(Bh1750.address)) { continue; } - if (Bh1750SetResolution()) { + if (Bh1750SetMTreg()) { I2cSetActiveFound(Bh1750.address, Bh1750.types); Bh1750.type = 1; break; @@ -96,27 +113,25 @@ void Bh1750EverySecond(void) /*********************************************************************************************\ * Command Sensor10 * - * 0 - High resolution mode (default) - * 1 - High resolution mode 2 - * 2 - Low resolution mode + * 0 - High resolution mode (default) + * 1 - High resolution mode 2 + * 2 - Low resolution mode + * 31..254 - Measurement Time value (not persistent, default is 69) \*********************************************************************************************/ bool Bh1750CommandSensor(void) { - uint32_t message_index = Settings.SensorBits1.bh1750_resolution; if (XdrvMailbox.data_len) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - case 2: - Settings.SensorBits1.bh1750_resolution = XdrvMailbox.payload; - Bh1750SetResolution(); - message_index = Settings.SensorBits1.bh1750_resolution; - break; + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + Settings.SensorBits1.bh1750_resolution = XdrvMailbox.payload; + Bh1750SetResolution(); + } + else if ((XdrvMailbox.payload > 30) && (XdrvMailbox.payload < 255)) { + Bh1750.mtreg = XdrvMailbox.payload; + Bh1750SetMTreg(); } } - char res_text[64]; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_10, GetTextIndexed(res_text, sizeof(res_text), message_index, kBhMessages)); + Response_P(PSTR("{\"" D_CMND_SENSOR "10\":{\"Resolution\":%d,\"MTime\":%d}}"), Settings.SensorBits1.bh1750_resolution, Bh1750.mtreg); return true; } From c066b0c8e2245645952c9836045fad0e7b0de8d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:34:02 +0200 Subject: [PATCH 51/56] Fix compile error if no USE_LIGHT --- tasmota/xsns_15_mhz19.ino | 2 ++ tasmota/xsns_17_senseair.ino | 2 ++ tasmota/xsns_38_az7798.ino | 2 ++ 3 files changed, 6 insertions(+) diff --git a/tasmota/xsns_15_mhz19.ino b/tasmota/xsns_15_mhz19.ino index 860eec8ce..633ca3f59 100644 --- a/tasmota/xsns_15_mhz19.ino +++ b/tasmota/xsns_15_mhz19.ino @@ -230,7 +230,9 @@ void MhzEverySecond(void) mhz_type = (s) ? 1 : 2; if (MhzCheckAndApplyFilter(ppm, s)) { mhz_retry = MHZ19_RETRY_COUNT; +#ifdef USE_LIGHT LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); +#endif // USE_LIGHT if (0 == s || 64 == s) { // Reading is stable. if (mhz_abc_must_apply) { diff --git a/tasmota/xsns_17_senseair.ino b/tasmota/xsns_17_senseair.ino index dee516dff..60614b4c7 100644 --- a/tasmota/xsns_17_senseair.ino +++ b/tasmota/xsns_17_senseair.ino @@ -84,7 +84,9 @@ void Senseair250ms(void) // Every 250 mSec break; case 2: // 0x03 (3) READ_CO2 - fe 04 02 06 2c af 59 senseair_co2 = value; +#ifdef USE_LIGHT LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); +#endif // USE_LIGHT break; case 3: // 0x04 (4) READ_TEMPERATURE - S8: fe 84 02 f2 f1 - Illegal Data Address senseair_temperature = ConvertTemp((float)value / 100); diff --git a/tasmota/xsns_38_az7798.ino b/tasmota/xsns_38_az7798.ino index 18705dce5..b6b1dffbe 100644 --- a/tasmota/xsns_38_az7798.ino +++ b/tasmota/xsns_38_az7798.ino @@ -215,7 +215,9 @@ void AzEverySecond(void) } response_substr[j] = 0; // add null terminator az_co2 = atoi((char*)response_substr); +#ifdef USE_LIGHT LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); +#endif // USE_LIGHT i += 3; // advance to second delimiter if(az_response[i] != ':') { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); From f393e2ade45cefb69da6096b1cbfa6900433a39c Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Fri, 3 Apr 2020 11:49:01 -0500 Subject: [PATCH 52/56] Use SetOption32 for hold time, Use SendKey to process ButtonTopic/Rules and ignore handled button presses/holds. --- PWM_Dimmer.md | 6 +- tasmota/xdrv_35_pwm_dimmer.ino | 533 ++++++++++++++++----------------- 2 files changed, 253 insertions(+), 286 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index 7254a5da2..af6f7abe7 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -25,9 +25,9 @@ Holding the power button, tapping the down button and then tapping or holding th Holding the power button, tapping the up button and then tapping or holding the down or up button publishes an MQTT Event command. The command is sent/value is adjusted once every .5 seconds for as long as the button is held. The MQTT topic is as described above. The MQTT payload is Trigger#, where # is 3 if the down button is held or 4 if the up button is held. -Holding the down or up button alone for over 10 seconds executes the WiFiConfig 2 command. +Holding any button alone for over 10 seconds executes the WiFiConfig 2 command. -Pressing and releasing any button publishes an MQTT TOGGLE command for the button. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released. +SetOption32 defines the button hold time. When the PWM Dimmer module is initially selected, SetOption32 is set to 5 (1/2 second). Button presses and holds execute the normal ButtonTopic and Rule processing. If ButtonTopic is set and SetOption61 is 0 or a the button press/hold matches a rule, the button press/hold is ignored by PWM Dimmer. When Device Groups are enabled, the PWM Dimmer brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. @@ -81,7 +81,7 @@ When Device Groups are enabled, the PWM Dimmer brightness presets are kept in sy Remote device mode allows PWM Dimmer switches to control remote devices. With remote device mode enabled, each button controls a different device. Note that dimmer switches with toggle-style down/up buttons have limited functionality as remote device mode switches because you can not push the down and up buttons simultaneously. -To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 0.7K to the code size in addition to the code size required for device groups support. +To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 1.2K to the code size in addition to the code size required for device groups support. To enable remote device mode, execute the command SetOption88 1 (the device will restart). Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches. diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 54f270c4c..0e0594a8b 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -50,37 +50,42 @@ struct remote_pwm_dimmer { }; #endif // USE_PWM_DIMMER_REMOTE -uint32_t led_timeout_time = 0; -uint32_t turn_off_brightness_leds_time = 0; -uint32_t button_press_time; +uint32_t last_button_press_time; uint32_t button_hold_time[3]; -uint8_t restore_powered_off_led = 0; +uint8_t led_timeout_seconds = 0; +uint8_t restore_powered_off_led_counter = 0; uint8_t power_button_index = 0; uint8_t down_button_index = 1; -uint8_t up_button_index = 2; uint8_t buttons_pressed = 0; uint8_t tap_count = 0; -bool ignore_power_button_hold; -bool ignore_power_button_release; bool down_button_tapped = false; -bool button_was_held = false; bool power_button_increases_bri = true; bool invert_power_button_bri_direction = false; bool restore_brightness_leds = false; -bool button_hold_sent[3]; bool button_pressed[3] = { false, false, false }; +bool button_hold_sent[3]; +bool button_hold_processed[3]; #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer * remote_pwm_dimmers; struct remote_pwm_dimmer * active_remote_pwm_dimmer; bool active_device_is_local; #endif // USE_PWM_DIMMER_REMOTE -void PWMModulePreInit() +void PWMModulePreInit(void) { Settings.seriallog_level = 0; Settings.flag.mqtt_serial = 0; // Disable serial logging Settings.ledstate = 0; // Disable LED usage + // If the module was just changed to PWM Dimmer, set the defaults. + if (Settings.last_module != Settings.module) { + Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL + Settings.param[P_HOLD_TIME] = 5; // SetOption32 - Button held for factor times longer + Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0; + Settings.last_module = Settings.module; + } + + // Make sure the brightness level settings are sensible. if (!Settings.bri_power_on) Settings.bri_power_on = 128; if (!Settings.bri_preset_low) Settings.bri_preset_low = 10; if (Settings.bri_preset_high < Settings.bri_preset_low) Settings.bri_preset_high = 255; @@ -142,7 +147,7 @@ void PWMDimmerSetBrightnessLeds(int32_t operation) } // If enabled, set the LED timeout. - if (!operation) led_timeout_time = (current_bri && Settings.flag4.led_timeout ? millis() + 5000 : 0); + if (!operation) led_timeout_seconds = (current_bri && Settings.flag4.led_timeout ? 5 : 0); } } @@ -164,9 +169,9 @@ void PWMDimmerSetPower(void) } #ifdef USE_DEVICE_GROUPS -void PWMDimmerHandleDeviceGroupItem() +void PWMDimmerHandleDeviceGroupItem(void) { - uint8_t value = XdrvMailbox.payload; + uint32_t value = XdrvMailbox.payload; #ifdef USE_PWM_DIMMER_REMOTE uint8_t device_group_index = XdrvMailbox.index >> 16 & 0xff; bool device_is_local = device_groups[device_group_index].local; @@ -178,6 +183,12 @@ void PWMDimmerHandleDeviceGroupItem() case DGR_ITEM_LIGHT_BRI: if (!device_is_local) remote_pwm_dimmer->bri = value; break; + case DGR_ITEM_POWER: + if (!device_is_local) { + remote_pwm_dimmer->power = value; + remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128); + } + break; case DGR_ITEM_LIGHT_FIXED_COLOR: if (!device_is_local) remote_pwm_dimmer->fixed_color_index = value; break; @@ -217,7 +228,7 @@ void PWMDimmerHandleDeviceGroupItem() } #endif // USE_DEVICE_GROUPS -void PWMDimmerHandleButton() +void PWMDimmerHandleButton(void) { /* * Power Button Up/Down Buttons State Remote Mode Action @@ -251,16 +262,16 @@ void PWMDimmerHandleButton() // If the button is not pressed and was not just released (the most common case), ... if (XdrvMailbox.payload && !button_pressed[XdrvMailbox.index]) { - // If no buttons have been pressed for 250ms, reset the button press counts. - if (button_press_time && !buttons_pressed && millis() - button_press_time > 400) { - button_was_held = false; + // If no buttons have been pressed for 400ms, reset the button press counts. + if (last_button_press_time && !buttons_pressed && millis() - last_button_press_time > 400) { + last_button_press_time = 0; tap_count = 0; } - return; } bool state_updated = false; + int8_t bri_offset = 0; uint8_t power_on_bri = 0; uint8_t dgr_item = 0; uint8_t dgr_value; @@ -268,265 +279,192 @@ void PWMDimmerHandleButton() uint32_t button_index = XdrvMailbox.index; uint32_t now = millis(); - // Set a bool indicating if the power is on. + // Initialize some variables. #ifdef USE_PWM_DIMMER_REMOTE bool power_is_on = (!active_device_is_local ? active_remote_pwm_dimmer->power : power); + bool is_power_button = (button_index == power_button_index); #else // USE_PWM_DIMMER_REMOTE bool power_is_on = power; + bool is_power_button = !button_index; #endif // USE_PWM_DIMMER_REMOTE + bool is_down_button = (button_index == down_button_index); // If the button is pressed, ... if (!XdrvMailbox.payload) { - int8_t bri_direction = 0; // If the button was just pressed, flag the button as pressed, clear the hold sent flag and // increment the buttons pressed count. if (!button_pressed[button_index]) { - button_press_time = now; + last_button_press_time = now; button_pressed[button_index] = true; + button_hold_time[button_index] = now + Settings.param[P_HOLD_TIME] * 100; button_hold_sent[button_index] = false; buttons_pressed++; -#ifdef USE_PWM_DIMMER_REMOTE +#ifdef USE_PWM_DIMMER_REMOTE // If there are no other buttons pressed right now and remote mode is enabled, make the device // associated with this button the device we're going to control. if (buttons_pressed == 1 && Settings.flag4.remote_device_mode) { power_button_index = button_index; - up_button_index = (button_index == 2 ? 1 : 2); down_button_index = (button_index ? 0 : 1); active_device_is_local = device_groups[power_button_index].local; if (!active_device_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index - 1]; } - if (button_index == power_button_index) { -#else // USE_PWM_DIMMER_REMOTE - // If this is about the power button, initialize some variables. - if (!button_index) { #endif // USE_PWM_DIMMER_REMOTE - button_hold_time[button_index] = now + 500; - ignore_power_button_hold = false; - ignore_power_button_release = false; + + return; + } + + // If the button is being held, ... + if (button_hold_time[button_index] < now) { + + // If the power button is not also pressed and the button has been held for over 10 seconds, + // execute the WiFiConfig 2 command. + if (!button_pressed[power_button_index] && now - button_hold_time[button_index] > 10000) { + button_hold_time[button_index] = now + 90000; + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); + ExecuteCommand(scmnd, SRC_BUTTON); return; } - // If this is not about the power button, load the new hold time. Note that the hold time for - // the power button is longer than the hold time for the other buttons. - button_hold_time[button_index] = now + (tap_count ? 0 : 250); - } - - // If the button is being held, send a button hold. - else if (button_hold_time[button_index] < now) { + // Send a button hold if we haven't already. If it is handled (by the button topic or by a + // rule), ignore the this button until it's released. if (!button_hold_sent[button_index]) { button_hold_sent[button_index] = true; - SendKey(KEY_BUTTON, button_index + 1, POWER_HOLD); + button_hold_processed[button_index] = (!is_power_button && tap_count ? false : SendKey(KEY_BUTTON, button_index + 1, POWER_HOLD)); } - } + if (!button_hold_processed[button_index]) { - // If this is about the power button, ... + // If this is about the power button, ... + if (is_power_button) { + + // If no other buttons are pressed, ... + if (buttons_pressed == 1) { + + // If the power is on, adjust the brightness. Set the direction based on the current + // direction for the device and then invert the direction when the power button is + // released. The new brightness will be calculated below. + if (power_is_on) { #ifdef USE_PWM_DIMMER_REMOTE - if (button_index == power_button_index) { + bri_offset = (!active_device_is_local ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); #else // USE_PWM_DIMMER_REMOTE - if (!button_index) { + bri_offset = (power_button_increases_bri ? 1 : -1); #endif // USE_PWM_DIMMER_REMOTE - - // If the power button has been held with no other buttons pressed, ... - if (!ignore_power_button_hold && button_hold_time[button_index] < now) { - ignore_power_button_release = true; - - // If the power is on, adjust the brightness. Set the direction based on the current - // direction for the device and then invert the direction when the power button is released. - // The new brightness will be calculated below. - if (power_is_on) { -#ifdef USE_PWM_DIMMER_REMOTE - bri_direction = (!active_device_is_local ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); -#else // USE_PWM_DIMMER_REMOTE - bri_direction = (power_button_increases_bri ? 1 : -1); -#endif // USE_PWM_DIMMER_REMOTE - invert_power_button_bri_direction = true; - } - - // If the power is not on, turn it on using an initial brightness of bri_preset_low, set the - // power button hold dimmer direction to true so holding the power switch increases the - // brightness and the power button hold time to delay before we start increasing the - // brightness. - else { -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) { - power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; - active_remote_pwm_dimmer->power_button_increases_bri = true; - button_hold_time[button_index] = now + 1000; - } - else { -#endif // USE_PWM_DIMMER_REMOTE - power_on_bri = Settings.bri_preset_low; - power_button_increases_bri = true; - button_hold_time[button_index] = now + 500; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif // USE_PWM_DIMMER_REMOTE - } - } - } - - // If this is about the down or up buttons, ... - else { - bool is_down_button = (button_index == down_button_index); - - // If the power button is also pressed, set flags to ignore the power button being held and - // the next power button release. - if (button_pressed[power_button_index]) { - ignore_power_button_release = ignore_power_button_hold = true; - } - - // If the button is being held, ... - if (button_hold_time[button_index] < now) { - uint8_t mqtt_trigger = 0; - - // If the up or down button was tapped while holding the power button before this, handle - // the operation. - if (tap_count) { - - // Send a device group update to select the previous/next fixed color. - if (down_button_tapped) { -#ifdef USE_DEVICE_GROUPS - uint8_t uint8_value; -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - uint8_value = active_remote_pwm_dimmer->fixed_color_index; - else -#endif // USE_PWM_DIMMER_REMOTE - uint8_value = Light.fixed_color_index; - if (is_down_button) { - if (uint8_value) - uint8_value--; - else - uint8_value = MAX_FIXED_COLOR; + invert_power_button_bri_direction = true; } + + // If the power is not on, turn it on using an initial brightness of bri_preset_low and + // set the power button hold time to delay before we start increasing the brightness. else { - if (uint8_value < MAX_FIXED_COLOR) - uint8_value++; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; else - uint8_value = 0; +#endif // USE_PWM_DIMMER_REMOTE + power_on_bri = Settings.bri_preset_low; + button_hold_time[button_index] = now + 500; } -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - active_remote_pwm_dimmer->fixed_color_index = uint8_value; - else -#endif // USE_PWM_DIMMER_REMOTE - Light.fixed_color_index = uint8_value; - dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR; - dgr_value = uint8_value; - dgr_more_to_come = true; -#endif // USE_DEVICE_GROUPS - ; - } - - // Publish MQTT Event Trigger#. - else { - mqtt_trigger = (is_down_button ? 3 : 4); } } - // If the power button is not also pressed and the button has been held for over 10 seconds, - // execute the WiFiConfig 2 command. - else if (!button_pressed[power_button_index] && now - button_hold_time[button_index] > 10000) { - button_hold_time[button_index] = now + 90000; - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - - // If the power is not on, publish MQTT Event Trigger#. - else if (!power_is_on) { - mqtt_trigger = (is_down_button ? 1 : 2); - } - - button_was_held = true; - button_hold_time[button_index] = now + 500; - - // If we need to publish an MQTT trigger, do it. - if (mqtt_trigger) { - char topic[TOPSZ]; - sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) { - snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/Event"), device_groups[power_button_index].group_name); - MqttPublish(topic); - } - else -#endif // USE_PWM_DIMMER_REMOTE - MqttPublishPrefixTopic_P(CMND, PSTR("Event")); - } - } - - // If the power is on and the up or down button was not tapped while holding the power button - // before this, adjust the brightness. Set the direction based on which button is pressed. The - // new brightness will be calculated below. - if (power_is_on && !tap_count) { - bri_direction = (is_down_button ? -1 : 1); - } - } - - // If we need to adjust the brightness, do it. - if (bri_direction) { - int32_t bri; -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - bri = active_remote_pwm_dimmer->bri; - else -#endif // USE_PWM_DIMMER_REMOTE - bri = light_state.getBri(); - int32_t new_bri; - int32_t offset = (Settings.light_correction ? 4 : bri / 16 + 1); - if (bri_direction > 0) { - new_bri = bri + offset; - if (new_bri > 255) new_bri = 255; - } - else { - new_bri = bri - offset; - if (new_bri < 1) new_bri = 1; - } - if (new_bri != bri) { -#ifdef USE_DEVICE_GROUPS - SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_ITEM_LIGHT_BRI, new_bri); -#endif // USE_DEVICE_GROUPS -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; + // If this is about the down or up buttons, ... else { -#endif // USE_PWM_DIMMER_REMOTE - skip_light_fade = true; - light_state.setBri(new_bri); - LightAnimate(); - skip_light_fade = false; - Settings.bri_power_on = new_bri; + + // If the power is on and the up or down button was not tapped while holding the power + // button before this, adjust the brightness. Set the direction based on which button is + // pressed. The new brightness will be calculated below. + if (power_is_on && !tap_count) { + bri_offset = (is_down_button ? -1 : 1); + } + + else { + uint8_t mqtt_trigger = 0; + + // If the up or down button was tapped while holding the power button before this, + // handle the operation. + if (tap_count) { + + // Send a device group update to select the previous/next fixed color. + if (down_button_tapped) { +#ifdef USE_DEVICE_GROUPS + uint8_t uint8_value; #ifdef USE_PWM_DIMMER_REMOTE - } + if (!active_device_is_local) + uint8_value = active_remote_pwm_dimmer->fixed_color_index; + else #endif // USE_PWM_DIMMER_REMOTE - } - else { - PWMDimmerSetBrightnessLeds(0); + uint8_value = Light.fixed_color_index; + if (is_down_button) { + if (uint8_value) + uint8_value--; + else + uint8_value = MAX_FIXED_COLOR; + } + else { + if (uint8_value < MAX_FIXED_COLOR) + uint8_value++; + else + uint8_value = 0; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->fixed_color_index = uint8_value; + else +#endif // USE_PWM_DIMMER_REMOTE + Light.fixed_color_index = uint8_value; + dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR; + dgr_value = uint8_value; + dgr_more_to_come = true; +#endif // USE_DEVICE_GROUPS + ; + } + + // Publish MQTT Event Trigger#. + else { + mqtt_trigger = (is_down_button ? 3 : 4); + } + } + + // If the power is not on, publish MQTT Event Trigger#. + else if (!power_is_on) { + mqtt_trigger = (is_down_button ? 1 : 2); + } + + // If we need to publish an MQTT trigger, do it. + if (mqtt_trigger) { + char topic[TOPSZ]; + sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/Event"), device_groups[power_button_index].group_name); + MqttPublish(topic); + } + else +#endif // USE_PWM_DIMMER_REMOTE + MqttPublishPrefixTopic_P(CMND, PSTR("Event")); + } + + button_hold_time[button_index] = now + 500; + } + } } } } // If the button was just released, ... else { -// if (now - button_press_time > Settings.button_debounce) { + bool button_was_held = button_hold_sent[button_index]; - // If the button was held, send a button off; otherwise, send a button toggle. - SendKey(KEY_BUTTON, button_index + 1, (button_hold_sent[button_index] ? POWER_OFF : POWER_TOGGLE)); + // If the button was not held, send a button toggle. If the button was held but not processes by + // support_button or support_buttondoesn't process the toggle (is not handled by a rule), ... + if (!(button_hold_sent[button_index] ? button_hold_processed[button_index] : SendKey(KEY_BUTTON, button_index + 1, POWER_TOGGLE))) { // If this is about the power button, ... -#ifdef USE_PWM_DIMMER_REMOTE - if (button_index == power_button_index) { -#else // USE_PWM_DIMMER_REMOTE - if (!button_index) { -#endif // USE_PWM_DIMMER_REMOTE + if (is_power_button) { - // If we're ignoring the next power button released, ... - if (ignore_power_button_release) { - ignore_power_button_release = false; + // If the power button was held, ... + if (button_was_held) { // If the power button was held with no other buttons pressed, we changed the brightness // so invert the bri direction for the next time and send a final update. @@ -544,7 +482,7 @@ void PWMDimmerHandleButton() #endif // USE_PWM_DIMMER_REMOTE } - // If the up or down button was tapped while the power button was pressed, ... + // If the up or down button was tapped while the power button was held, ... else if (tap_count) { // If the button was tapped but not held, handle the operation based on which button was @@ -579,93 +517,116 @@ void PWMDimmerHandleButton() } } - // If we're not ignoring the power button until it's released, toggle the power. + // If the power button was not held, toggle the power. else { #ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) { + if (!active_device_is_local) power_on_bri = active_remote_pwm_dimmer->bri_power_on; - if (active_remote_pwm_dimmer->bri > 251) - active_remote_pwm_dimmer->power_button_increases_bri = false; - else if (active_remote_pwm_dimmer->bri < 4) - active_remote_pwm_dimmer->power_button_increases_bri = true; - } - else { + else #endif // USE_PWM_DIMMER_REMOTE power_on_bri = Settings.bri_power_on; - if (power_on_bri > 251) - power_button_increases_bri = false; - else if (power_on_bri < 4) - power_button_increases_bri = true; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif // USE_PWM_DIMMER_REMOTE } } // If this is about the up or down buttons, ... else { - bool is_down_button = (button_index == down_button_index); if (restore_brightness_leds) { restore_brightness_leds = false; PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? -1 : 0); } - // If the power is on and the up or down button was not tapped while holding the power - // button before this, we changed the brightness and sent updates with the more-to-come - // message type. Send a final update. - if (power_is_on && !tap_count) { - dgr_item = 255; - state_updated = true; - - // If the power button is also pressed, set the power button hold dimmer direction so - // holding the power switch adjusts the brightness away from the brightness we just set. -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local && button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = is_down_button; -#endif // USE_PWM_DIMMER_REMOTE + // If the button was not held and the power button is also pressed, increment the count of + // how many times the button has been tapped. + if (!button_was_held && button_pressed[power_button_index]) { + down_button_tapped = is_down_button; + tap_count++; } - // If the button was not held, ... - if (!button_was_held) { + // If the button wasn't tapped while the power button was pressed, ... + if (!tap_count) { - // If the power button is also pressed, increment the count of how many times a button has - // been tapped. - if (button_pressed[power_button_index]) { - down_button_tapped = (button_index == down_button_index); - tap_count++; + // If the power is on, ... + if (power_is_on) { + + // If the button was not held, adjust the brightness. Set the direction based on which + // button is pressed. The new brightness will be calculated below. + if (button_hold_time[button_index] >= now) { + bri_offset = (is_down_button ? -10 : 10); + dgr_item = 255; + } + + // If the button was held and the hold was not processed by a rule, we changed the + // brightness and sent updates with the more-to-come message type while the button was + // held. Send a final update. + else if (!button_hold_processed[button_index]) { + dgr_item = 255; + state_updated = true; + } } // If the power is off, turn it on using a temporary brightness of bri_preset_low if the // down button is pressed or bri_preset_low if the up button is pressed. + else { #ifdef USE_PWM_DIMMER_REMOTE - else if ((!active_device_is_local ? !active_remote_pwm_dimmer->power : !power)) { -#else // USE_PWM_DIMMER_REMOTE - else if (!power) { -#endif // USE_PWM_DIMMER_REMOTE -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) { + if (!active_device_is_local) power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); - active_remote_pwm_dimmer->power_button_increases_bri = is_down_button; - } - else { + else #endif // USE_PWM_DIMMER_REMOTE power_on_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); - power_button_increases_bri = is_down_button; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif // USE_PWM_DIMMER_REMOTE - button_hold_time[button_index] = now + 500; } } } -// } + } // Flag the button as released. button_pressed[button_index] = false; buttons_pressed--; } - if (power_on_bri) { + // If we need to adjust the brightness, do it. + if (bri_offset) { + int32_t bri; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + bri = active_remote_pwm_dimmer->bri; + else +#endif // USE_PWM_DIMMER_REMOTE + bri = light_state.getBri(); + int32_t new_bri; + bri_offset *= (Settings.light_correction ? 4 : bri / 16 + 1); + new_bri = bri + bri_offset; + if (bri_offset > 0) { + if (new_bri > 255) new_bri = 255; + } + else { + if (new_bri < 1) new_bri = 1; + } + if (new_bri != bri) { +#ifdef USE_DEVICE_GROUPS + SendDeviceGroupMessage(power_button_index, (dgr_item ? DGR_MSGTYP_UPDATE : DGR_MSGTYP_UPDATE_MORE_TO_COME), DGR_ITEM_LIGHT_BRI, new_bri); +#endif // USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; + else { +#endif // USE_PWM_DIMMER_REMOTE + skip_light_fade = true; + light_state.setBri(new_bri); + LightAnimate(); + skip_light_fade = false; + Settings.bri_power_on = new_bri; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + } + else { + PWMDimmerSetBrightnessLeds(0); + } + } + + // If we're supposed to toggle the power on, do it. + else if (power_on_bri) { power_t new_power; #ifdef USE_DEVICE_GROUPS #ifdef USE_PWM_DIMMER_REMOTE @@ -686,16 +647,19 @@ void PWMDimmerHandleButton() #endif // USE_DEVICE_GROUPS #ifdef USE_PWM_DIMMER_REMOTE - if (active_device_is_local) { + if (!active_device_is_local) + active_remote_pwm_dimmer->power_button_increases_bri = (power_on_bri < 128); + else { #endif // USE_PWM_DIMMER_REMOTE - ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); light_state.setBri(power_on_bri); + ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE } - // If we're not toggling the power and we made changes, send a group update. + // If we're not changing the brightness or toggling the power and we made changes, send a group + // update. else if (dgr_item) { #ifdef USE_DEVICE_GROUPS if (dgr_item == 255) dgr_item = 0; @@ -776,8 +740,7 @@ bool Xdrv35(uint8_t function) switch (function) { case FUNC_EVERY_SECOND: // Turn off the brightness LED's if it's time. - if (led_timeout_time && led_timeout_time < millis()) { - led_timeout_time = 0; + if (led_timeout_seconds && !led_timeout_seconds--) { PWMDimmerSetBrightnessLeds(-1); } @@ -786,10 +749,10 @@ bool Xdrv35(uint8_t function) // restored. If the state is blinking now, set a flag so we know that we need to restore it // when it stops blinking. if (global_state.data) - restore_powered_off_led = 5; - else if (restore_powered_off_led) { + restore_powered_off_led_counter = 5; + else if (restore_powered_off_led_counter) { PWMDimmerSetPoweredOffLed(); - restore_powered_off_led--; + restore_powered_off_led_counter--; } break; @@ -811,9 +774,13 @@ bool Xdrv35(uint8_t function) case FUNC_SET_DEVICE_POWER: // If we're turning the power on, turn the relay and the brightness LEDs on and turn the // powered-off LED off. - if (XdrvMailbox.index) + if (XdrvMailbox.index) { PWMDimmerSetPower(); + // Set the power button hold dimmer direction based on the current brightness. + power_button_increases_bri = (light_state.getBri() < 128); + } + // If we're turning the power off, return true so SetDevicePower doesn't turn the relay off. // It will be turned off in LightApplyFade when the fade is done. else From 1e1fd7aece3251554714083883c01aaf90e2d546 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Fri, 3 Apr 2020 18:24:48 -0500 Subject: [PATCH 53/56] Handle schemes shared in device groups --- tasmota/xdrv_04_light.ino | 59 ++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a3f7a6be5..348835ca4 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -273,6 +273,9 @@ struct LIGHT { bool fade_initialized = false; // dont't fade at startup bool fade_running = false; +#ifdef USE_DEVICE_GROUPS + bool devgrp_no_channels_out = false; // don't share channels with device group (e.g. if scheme set by other device) +#endif // USE_DEVICE_GROUPS uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; uint16_t fade_cur_10[LST_MAX]; uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values @@ -1429,6 +1432,9 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Light signal %d"), signal); light_controller.changeRGB(signal, 255 - signal, 0, true); // keep bri Settings.light_scheme = 0; +#ifdef USE_DEVICE_GROUPS + LightUpdateScheme(); +#endif // USE_DEVICE_GROUPS if (0 == light_state.getBri()) { light_controller.changeBri(50); } @@ -1742,6 +1748,9 @@ void LightAnimate(void) Light.wakeup_active = 0; Settings.light_scheme = LS_POWER; +#ifdef USE_DEVICE_GROUPS + LightUpdateScheme(); +#endif // USE_DEVICE_GROUPS } } break; @@ -1775,7 +1784,7 @@ void LightAnimate(void) } if (Light.update) { #ifdef USE_DEVICE_GROUPS - if (Light.power) LightSendDeviceGroupStatus(); + if (Light.power) LightSendDeviceGroupStatus(false); #endif // USE_DEVICE_GROUPS uint16_t cur_col_10[LST_MAX]; // 10 bits resolution @@ -2097,18 +2106,29 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) { } #ifdef USE_DEVICE_GROUPS -void LightSendDeviceGroupStatus() +void LightSendDeviceGroupStatus(bool force) { - if (Light.subtype > LST_SINGLE) { + static uint8_t last_channels[LST_MAX]; + static uint8_t last_bri; + + uint8_t bri = light_state.getBri(); + bool send_bri_update = (force || bri != last_bri); + + if (Light.subtype > LST_SINGLE && !Light.devgrp_no_channels_out) { uint8_t channels[LST_MAX]; light_state.getChannels(channels); - SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_CHANNELS, channels); + if (force || memcmp(last_channels, channels, LST_MAX)) { + memcpy(last_channels, channels, LST_MAX); + SendLocalDeviceGroupMessage((send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels); + } + } + if (send_bri_update) { + last_bri = bri; + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, light_state.getBri()); } - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme, - DGR_ITEM_LIGHT_BRI, light_state.getBri()); } -void LightHandleDeviceGroupItem() +void LightHandleDeviceGroupItem(void) { static bool send_state = false; static bool restore_power = false; @@ -2144,6 +2164,7 @@ void LightHandleDeviceGroupItem() case DGR_ITEM_LIGHT_SCHEME: if (Settings.light_scheme != value) { Settings.light_scheme = value; + Light.devgrp_no_channels_out = (value != 0); send_state = true; } break; @@ -2162,6 +2183,7 @@ void LightHandleDeviceGroupItem() light_controller.changeChannels(Light.entry_color); light_controller.changeBri(old_bri); Settings.light_scheme = 0; + Light.devgrp_no_channels_out = false; } else { light_state.setColorMode(LCM_CT); @@ -2188,11 +2210,22 @@ void LightHandleDeviceGroupItem() break; case DGR_ITEM_STATUS: SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, - DGR_ITEM_LIGHT_SPEED, Settings.light_speed); - LightSendDeviceGroupStatus(); + DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); + LightSendDeviceGroupStatus(true); break; } } + +void LightUpdateScheme(void) +{ + static uint8_t last_scheme; + + if (Settings.light_scheme != last_scheme) { + last_scheme = Settings.light_scheme; + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); + } + Light.devgrp_no_channels_out = false; +} #endif // USE_DEVICE_GROUPS /*********************************************************************************************\ @@ -2291,6 +2324,9 @@ void CmndSupportColor(void) } Settings.light_scheme = 0; +#ifdef USE_DEVICE_GROUPS + LightUpdateScheme(); +#endif // USE_DEVICE_GROUPS coldim = true; } else { // Color3, 4, 5 and 6 for (uint32_t i = 0; i < LST_RGB; i++) { @@ -2458,7 +2494,7 @@ void CmndScheme(void) } Settings.light_scheme = XdrvMailbox.payload; #ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); + LightUpdateScheme(); #endif // USE_DEVICE_GROUPS if (LS_WAKEUP == Settings.light_scheme) { Light.wakeup_active = 3; @@ -2483,6 +2519,9 @@ void CmndWakeup(void) } Light.wakeup_active = 3; Settings.light_scheme = LS_WAKEUP; +#ifdef USE_DEVICE_GROUPS + LightUpdateScheme(); +#endif // USE_DEVICE_GROUPS LightPowerOn(); ResponseCmndChar(D_JSON_STARTED); } From cca5b8e35b9b5f2cc06ff539891fb7c9234f7773 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sat, 4 Apr 2020 10:27:40 -0500 Subject: [PATCH 54/56] Call XdrvCall even for power. Fix devgrp index mask in xdrv_04_light --- tasmota/support_device_groups.ino | 4 +--- tasmota/xdrv_04_light.ino | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index f88bc5c93..4e8b48041 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -601,9 +601,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) } } } - else { - XdrvCall(FUNC_DEVICE_GROUP_ITEM); - } + XdrvCall(FUNC_DEVICE_GROUP_ITEM); } } diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a3f7a6be5..bcbfba042 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2115,7 +2115,7 @@ void LightHandleDeviceGroupItem() bool more_to_come; uint32_t value = XdrvMailbox.payload; #ifdef USE_PWM_DIMMER_REMOTE - if (XdrvMailbox.index & 0xff00) return; // Ignore updates from other device groups + if (XdrvMailbox.index & 0xff0000) return; // Ignore updates from other device groups #endif // USE_PWM_DIMMER_REMOTE switch (XdrvMailbox.command_code) { case DGR_ITEM_EOL: From b33fa68c0101c79f3d06b70903c72573a8f03323 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 5 Apr 2020 11:52:02 +0200 Subject: [PATCH 55/56] Fix BH1750 MT lux calculation Fix BH1750 MT lux calculation (#8057) --- tasmota/xsns_10_bh1750.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino index 1ba00b46e..a098166df 100644 --- a/tasmota/xsns_10_bh1750.ino +++ b/tasmota/xsns_10_bh1750.ino @@ -76,11 +76,12 @@ bool Bh1750Read(void) if (Bh1750.valid) { Bh1750.valid--; } if (2 != Wire.requestFrom(Bh1750.address, (uint8_t)2)) { return false; } - Bh1750.illuminance = (Wire.read() << 8) | Wire.read(); - Bh1750.illuminance /= (1.2 * (69 / Bh1750.mtreg)); + float illuminance = (Wire.read() << 8) | Wire.read(); + illuminance /= (1.2 * (69 / (float)Bh1750.mtreg)); if (1 == Settings.SensorBits1.bh1750_resolution) { - Bh1750.illuminance >>= 1; + illuminance /= 2; } + Bh1750.illuminance = illuminance; Bh1750.valid = SENSOR_MAX_MISS; return true; From 17c605ac6a1d26056db02d3af85d2b60c9b793b1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 5 Apr 2020 14:11:49 +0200 Subject: [PATCH 56/56] Make checkbox and radiobox label clickable Make checkbox and radio label clickable (#8066) --- tasmota/xdrv_01_webserver.ino | 12 ++++++------ tasmota/xdrv_02_mqtt.ino | 2 +- tasmota/xdrv_09_timers.ino | 18 +++++++++++------- tasmota/xdrv_10_scripter.ino | 2 +- tasmota/xdrv_11_knx.ino | 6 +++--- tasmota/xdrv_28_pcf8574.ino | 2 +- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 3521c0adb..1a45434a3 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -413,7 +413,7 @@ const char HTTP_FORM_TEMPLATE[] PROGMEM = const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = "

" // Keep close so do not use
"
 " D_TEMPLATE_FLAGS " 

" -// "" D_OPTION_TEXT "
" +// "
" "

"; const char HTTP_FORM_MODULE[] PROGMEM = @@ -426,9 +426,9 @@ const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "
" "

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" + "


" "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" + "


" "

" D_HOSTNAME " (%s)

" "

" D_CORS_DOMAIN "

"; @@ -446,12 +446,12 @@ const char HTTP_FORM_OTHER[] PROGMEM = "

" "
 " D_TEMPLATE " " "

" - "

" D_ACTIVATE "

" + "

" "
" "
" - "" D_WEB_ADMIN_PASSWORD "

" + "

" "
" - "" D_MQTT_ENABLE "
" + "
" "
"; const char HTTP_FORM_END[] PROGMEM = diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 912e7c929..7c8f0b29a 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1242,7 +1242,7 @@ const char HTTP_FORM_MQTT1[] PROGMEM = "

" D_CLIENT " (%s)

"; const char HTTP_FORM_MQTT2[] PROGMEM = "

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" + "


" "

" D_TOPIC " = %%topic%% (%s)

" "

" D_FULL_TOPIC " (%s)

"; diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index 0804ce286..f751d853f 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -648,7 +648,11 @@ const char HTTP_TIMER_SCRIPT6[] PROGMEM = "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options "o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" // Create outputs "var a='" D_DAY3LIST "';" - "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" + +// "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" +// "s='';for(i=0;i<7;i++){s+=\" \"}" + "s='';for(i=0;i<7;i++){s+=\" \"}" + "eb('ds').innerHTML=s;" // Create weekdays "eb('dP').click();" // Get the element with id='dP' and click on it "}" @@ -659,22 +663,22 @@ const char HTTP_FORM_TIMER1[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " "" - "
" D_TIMER_ENABLE "


" + "



" "



" "

" "
" - "" D_TIMER_ARM " " - "" D_TIMER_REPEAT "" + " " + "" "

" "
"; #ifdef USE_SUNRISE const char HTTP_FORM_TIMER3[] PROGMEM = "
" - "" D_TIMER_TIME "
" - "" D_SUNRISE " (%s)
" - "" D_SUNSET " (%s)
" + "
" + "
" + "
" "
" "

" "" diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 330512c9d..6f43229a9 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -3106,7 +3106,7 @@ const char HTTP_FORM_SCRIPT[] PROGMEM = const char HTTP_FORM_SCRIPT1[] PROGMEM = "
" - "" D_SCRIPT_ENABLE "
" + "
" "