diff --git a/tasmota/xdrv_79_esp32_ble.ino b/tasmota/xdrv_79_esp32_ble.ino index 6656dada5..5e4c2b70c 100644 --- a/tasmota/xdrv_79_esp32_ble.ino +++ b/tasmota/xdrv_79_esp32_ble.ino @@ -1078,6 +1078,10 @@ void setDetails(ble_advertisment_t *ad){ maxlen -= len; *(p++) = '\"'; maxlen--; + sprintf(p, ",\"RSSI\":%d", ad->RSSI); + len = strlen(p); + p += len; + if (BLEAdvertismentDetailsJsonLost){ BLEAdvertismentDetailsJsonLost = 0; strcpy(p, ",\"lost\":true"); @@ -1598,16 +1602,18 @@ int BLETaskStartScan(int time){ if (BLEMode == BLEModeDisabled) return -4; // don't scan whilst OTA in progress if (BLEOtaStallBLE) return -5; - if (currentOperations.size()) return -3; + //if (currentOperations.size()) return -3; if (BLERunningScan) { + // if we hit 2, wait one more time before starting if (BLERunningScan == 2){ - // wait 100ms - vTaskDelay(100/ portTICK_PERIOD_MS); + // wait 10ms + vTaskDelay(10/ portTICK_PERIOD_MS); BLERunningScan = 0; + } else { + return -2; } - return -2; } #ifdef BLE_ESP32_DEBUG @@ -1753,6 +1759,9 @@ static void BLETaskRunCurrentOperation(BLE_ESP32::generic_sensor_t** pCurrentOpe if (pClient->connect(op->addr, true)) { + // as soon as connected, start another scan if possible + BLE_ESP32::BLETaskStartScan(20); + #ifdef BLE_ESP32_DEBUG if (BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: connected %s -> getservice"), ((std::string)op->addr).c_str()); #endif @@ -1951,7 +1960,7 @@ static void BLETaskRunCurrentOperation(BLE_ESP32::generic_sensor_t** pCurrentOpe // failed to connect #ifdef BLE_ESP32_DEBUG - AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: failed to connect to device %d"), rc); + AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: failed to connect to device")); #endif } op->state = newstate; diff --git a/tasmota/xsns_52_esp32_ibeacon_ble.ino b/tasmota/xsns_52_esp32_ibeacon_ble.ino index d509332c5..432455924 100644 --- a/tasmota/xsns_52_esp32_ibeacon_ble.ino +++ b/tasmota/xsns_52_esp32_ibeacon_ble.ino @@ -1,11 +1,8 @@ /* xsns_52_esp32_ibeacon_ble.ino - if (!USE_IBEACON_ESP32 && USE_BLE_ESP32) - - Support for HM17 BLE Module + ibeacon reader on Tasmota (untested?) - if (USE_IBEACON_ESP32 && USE_BLE_ESP32) - Support for BLE_ESP32 ibeacon reader on Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2020 Gerhard Mutz and Theo Arends and Simon Hailes This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,14 +18,38 @@ along with this program. If not, see . */ +//////////////////////////////////////// +// Commands: +// iBeacon 0/1 - Enable +// iBeaconOnlyAliased 0/1/2 - +// 0 = all BLE devices, +// 1 = only devices with any BLEAlias +// 2 = only devices which have BLEAlias starting "iB" +// iBeaconClear - clear list NOW +// iBeaconPeriod (sec) - update period - default 10s +// iBeaconTimeout (sec) - timeout period - default 30s +// +// posts MQTT about each beacon every iBeaconPeriod (default 10s) +// MQTT like +// tele/tasmota_E89E98/SENSOR = {"Time":"2021-02-04T23:20:22","IBEACON":{"MAC":"FFFFA0003B19","NAME":"iB1","RSSI":-81,"STATE":"ON","PERSEC":10}} +// Always present: +// Time: time of MQTT send +// IBEACON.MAC +// IBEACON.RSSI +// IBEACON.STATE - ON - present, OFF - last MQTT you will get for now (device removed) +// Optional: +// IBEACON.NAME - name if in scan, or BLEAlias if set - only present if NAME present +// IBEACON.PERSEC - count of adverts per sec. USeful for detecting button press? +// IBEACON.MAJOR - some iBeacon related term? - only present for some +// IBEACON.MINOR - some iBeacon related term? - only present for some +//////////////////////////////////////// + + // for testing of BLE_ESP32, we remove xsns_52_ibeacon.ino completely, and instead add this modified xsns_52_ibeacon_BLE_ESP32.ino // in the future this may be more fine-grained, e.g. to allow hm17 for this, and BLE-ESP32 for other +#if CONFIG_IDF_TARGET_ESP32 #ifdef USE_BLE_ESP32 -#ifdef USE_IBEACON_ESP32 - -#ifdef USE_IBEACON - #define XSNS_52 52 // keyfob expires after N seconds @@ -37,64 +58,20 @@ #define IB_UPDATE_TIME_INTERVAL 10 // should be in Settings -#if 1 - uint8_t ib_upd_interval,ib_tout_interval; - #define IB_UPDATE_TIME ib_upd_interval - #define IB_TIMEOUT_TIME ib_tout_interval -#else - #undef IB_UPDATE_TIME - #undef IB_TIMEOUT_TIME - #define IB_UPDATE_TIME Settings.ib_upd_interval - #define IB_TIMEOUT_TIME Settings.ib_tout_interval -#endif +//#if 1 +uint8_t ib_upd_interval,ib_tout_interval; +//#undef IB_UPDATE_TIME +//#undef IB_TIMEOUT_TIME +#define IB_UPDATE_TIME ib_upd_interval +#define IB_TIMEOUT_TIME ib_tout_interval +//#else +//#undef IB_UPDATE_TIME +//#undef IB_TIMEOUT_TIME +//#define IB_UPDATE_TIME Settings.ib_upd_interval +//#define IB_TIMEOUT_TIME Settings.ib_tout_interval +//#endif -char ib_mac[14]; - - - struct { - union { - struct { - uint32_t init:1; - }; - uint32_t all = 0; - } mode; - } ESP32BLE; - - void *beaconmutex = nullptr; - - #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8)) - -#else - - #include - - #define TMSBSIZ52 512 - - #define HM17_BAUDRATE 9600 - - #define IBEACON_DEBUG - - // use this for Version 110 - #define HM17_V110 - - TasmotaSerial *IBEACON_Serial = nullptr; - - uint8_t hm17_found,hm17_cmd,hm17_flag; - - #ifdef IBEACON_DEBUG - uint8_t hm17_debug=0; - #endif - - // 78 is max serial response - #define HM17_BSIZ 128 - char hm17_sbuffer[HM17_BSIZ]; - uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; - uint32_t hm17_lastms; - - enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; - #define HM17_SUCESS 99 - -#endif +#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8)) struct IBEACON { char FACID[8]; @@ -104,16 +81,10 @@ struct IBEACON { char PWR[2]; char MAC[12]; char RSSI[4]; -#ifdef USE_IBEACON_ESP32 char NAME[16]; -#endif }; -#ifdef USE_IBEACON_ESP32 - #define MAX_IBEACONS 32 -#else - #define MAX_IBEACONS 16 -#endif +#define MAX_IBEACONS 32 struct IBEACON_UID { char MAC[12]; @@ -123,14 +94,78 @@ struct IBEACON_UID { char MINOR[4]; uint8_t FLAGS; uint8_t TIME; -#ifdef USE_IBEACON_ESP32 uint8_t REPORTED; uint8_t REPTIME; + uint8_t count; // count of adverts in REPTIME (reptime default = 10s) + uint32_t lastmqtt; // last time we sent something char NAME[16]; -#endif } ibeacons[MAX_IBEACONS]; -#ifdef USE_IBEACON_ESP32 + +void CmndiBeacon(void); +void CmndiBeaconOnlyAliased(void); +void CmndiBeaconClear(void); +void CmndiBeaconPeriod(void); +void CmndiBeaconTimeout(void); + +#define D_CMND_IBEACON "IBEACON" + +const char kiBeacon_Commands[] PROGMEM = D_CMND_IBEACON "|" + "|" + "onlyaliased|" + "clear|" + "period|" + "timeout"; + +void (*const iBeacon_Commands[])(void) PROGMEM = { + &CmndiBeacon, + &CmndiBeaconOnlyAliased, + &CmndiBeaconClear, + &CmndiBeaconPeriod, + &CmndiBeaconTimeout +}; + +uint8_t iBeaconOnlyAliased = 0; +uint8_t iBeaconEnable = 0; + + +void CmndiBeacon(void){ + if (XdrvMailbox.data_len > 0) { + iBeaconEnable = XdrvMailbox.payload; + } + ResponseCmndNumber(iBeaconEnable); +} + +void CmndiBeaconOnlyAliased(void){ + if (XdrvMailbox.data_len > 0) { + iBeaconOnlyAliased = XdrvMailbox.payload; + } + ResponseCmndNumber(iBeaconOnlyAliased); +} + +void CmndiBeaconClear(void){ + uint32_t count = 0; + for (uint32_t cnt=0; cnt 0) { + IB_UPDATE_TIME = XdrvMailbox.payload; + } + ResponseCmndNumber(IB_UPDATE_TIME); +} + +void CmndiBeaconTimeout(void){ + if (XdrvMailbox.data_len > 0) { + IB_TIMEOUT_TIME = XdrvMailbox.payload; + } + ResponseCmndNumber(IB_TIMEOUT_TIME); +} + uint32_t ibeacon_add(struct IBEACON *ib); @@ -156,12 +191,29 @@ void DumpHex(const unsigned char * in, size_t insz, char * out) int advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) { struct IBEACON ib; + if (!iBeaconEnable) return 0; + BLEAdvertisedDevice *advertisedDevice = pStruct->advertisedDevice; char sRSSI[6]; itoa(pStruct->RSSI,sRSSI,10); const uint8_t *MAC = pStruct->addr; + const char *alias = BLE_ESP32::getAlias(MAC); + if (iBeaconOnlyAliased){ + // ignore unless we have an alias. + if (!alias || !(*alias)){ + return 0; + } + } + if (!alias) alias = ""; + + if (iBeaconOnlyAliased == 2){ + if (strncmp(alias, "iB", 2)){ + return 0; + } + } + int manufacturerDataLen = 0; std::string data; if (advertisedDevice->haveManufacturerData()){ @@ -192,6 +244,9 @@ int advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) DumpHex((const unsigned char*)MAC,6,ib.MAC); memcpy(ib.RSSI,sRSSI,4); memset(ib.NAME,0x0,16); + if (*alias){ + strncpy(ib.NAME, alias, 16); + } // if we added it if (ibeacon_add(&ib) == 1){ @@ -221,52 +276,22 @@ int advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct) memset(ib.NAME,0x0,16); } + if (*alias){ + strncpy(ib.NAME, alias,16); + } + ibeacon_add(&ib); return 0; } -void ESP32Init() { - - if (!ESP32BLE.mode.init) { - ESP32BLE.mode.init = 1; - IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; - IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; - } -} - - -#endif void IBEACON_Init() { - - -#ifdef USE_IBEACON_ESP32 + AddLog(LOG_LEVEL_INFO, PSTR("iBeacon register for advert callbacks")); BLE_ESP32::registerForAdvertismentCallbacks((const char *)"iBeacon", advertismentCallback); -#else - - hm17_found=0; - -// actually doesnt work reliably with software serial - if (PinUsed(GPIO_IBEACON_RX) && PinUsed(GPIO_IBEACON_TX)) { - IBEACON_Serial = new TasmotaSerial(Pin(GPIO_IBEACON_RX), Pin(GPIO_IBEACON_TX),1,0,TMSBSIZ52); - if (IBEACON_Serial->begin(HM17_BAUDRATE)) { - if (IBEACON_Serial->hardwareSerial()) { - ClaimSerial(); - } - hm17_sendcmd(HM17_TEST); - hm17_lastms=millis(); - // in case of using Settings this has to be moved - IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; - IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; - } - } - -#endif - + IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; + IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; } -#ifdef USE_IBEACON_ESP32 - void esp32_every_second(void) { for (uint32_t cnt=0; cnt < MAX_IBEACONS; cnt++) { if (ibeacons[cnt].FLAGS) { @@ -279,11 +304,16 @@ void esp32_every_second(void) { uint32_t ageS = BLE_ESP32::devicePresent(mac); - // if device not present at all. - if (!ageS){ + // if device not present at all or past local timeout. + if (!ageS || (ageS > IB_TIMEOUT_TIME)){ //AddLog(LOG_LEVEL_INFO, PSTR("iBeacon no device %s %02x%02x%02x%02x%02x%02x"),tmp, mac[0],mac[1], mac[2],mac[3], mac[4],mac[5]); ibeacons[cnt].FLAGS=0; - ibeacon_mqtt(ibeacons[cnt].MAC,"0000",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR,ibeacons[cnt].NAME); + uint64_t now = esp_timer_get_time(); + uint32_t nowms = now/1000; + float countspermssec = ((float)ibeacons[cnt].count)/(((float)(nowms - ibeacons[cnt].lastmqtt))/1000.0); + ibeacon_mqtt(ibeacons[cnt].MAC,"0000",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR,ibeacons[cnt].NAME, (int)(countspermssec)); + ibeacons[cnt].count = 0; + ibeacons[cnt].lastmqtt = nowms; } else { //AddLog(LOG_LEVEL_INFO, PSTR("iBeacon device %s %02x%02x%02x%02x%02x%02x"),tmp, mac[0],mac[1], mac[2],mac[3], mac[4],mac[5]); } @@ -293,90 +323,6 @@ void esp32_every_second(void) { } } -#else - -void hm17_every_second(void) { - if (!IBEACON_Serial) return; - - if (hm17_found) { - if (IB_UPDATE_TIME && (TasmotaGlobal.uptime%IB_UPDATE_TIME==0)) { - if (hm17_cmd!=99) { - if (hm17_flag&2) { - ib_sendbeep(); - } else { - if (!hm17_connecting) { - hm17_sendcmd(HM17_DISI); - } - } - } - } - for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { - ibeacons[cnt].FLAGS=0; - ibeacon_mqtt(ibeacons[cnt].MAC,"0000",ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR); - } - } - } - } else { - if (TasmotaGlobal.uptime%20==0) { - hm17_sendcmd(HM17_TEST); - } - } -} - -void hm17_sbclr(void) { - memset(hm17_sbuffer,0,HM17_BSIZ); - hm17_sindex=0; - //IBEACON_Serial->flush(); -} - -void hm17_sendcmd(uint8_t cmd) { - hm17_sbclr(); - hm17_cmd=cmd; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); -#endif - switch (cmd) { - case HM17_TEST: - IBEACON_Serial->write("AT"); - break; - case HM17_ROLE: - IBEACON_Serial->write("AT+ROLE1"); - break; - case HM17_IMME: - IBEACON_Serial->write("AT+IMME1"); - break; - case HM17_DISI: - IBEACON_Serial->write("AT+DISI?"); - hm17_scanning=1; - break; - case HM17_IBEA: - IBEACON_Serial->write("AT+IBEA1"); - break; - case HM17_RESET: - IBEACON_Serial->write("AT+RESET"); - break; - case HM17_RENEW: - IBEACON_Serial->write("AT+RENEW"); - break; - case HM17_SCAN: - IBEACON_Serial->write("AT+SCAN5"); - break; - case HM17_DISC: - IBEACON_Serial->write("AT+DISC?"); - hm17_scanning=1; - break; - case HM17_CON: - IBEACON_Serial->write((const uint8_t*)"AT+CON",6); - IBEACON_Serial->write((const uint8_t*)ib_mac,12); - hm17_connecting=1; - break; - } -} - -#endif uint32_t ibeacon_add(struct IBEACON *ib) { /* if (!strncmp(ib->MAJOR,"4B1C",4)) { @@ -387,9 +333,6 @@ uint32_t ibeacon_add(struct IBEACON *ib) { return 0; } - // don't bother protecting this. - //TasAutoMutex localmutex(&beaconmutex, "iBeacAdd"); - // keyfob starts with ffff, ibeacon has valid facid if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { for (uint32_t cnt=0;cntUID,PSTR("00000000000000000000000000000000"),32)) { if (!strncmp(ibeacons[cnt].MAC,ib->MAC,12)) { // exists + strncpy(ibeacons[cnt].NAME,ib->NAME,sizeof(ibeacons[cnt].NAME)); memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); ibeacons[cnt].TIME=0; -#ifdef USE_IBEACON_ESP32 if (ibeacons[cnt].REPTIME >= IB_UPDATE_TIME) { ibeacons[cnt].REPTIME = 0; ibeacons[cnt].REPORTED = 0; } -#endif + ibeacons[cnt].count++; return 2; } } else { if (!strncmp(ibeacons[cnt].UID,ib->UID,32)) { // exists + strncpy(ibeacons[cnt].NAME,ib->NAME,sizeof(ibeacons[cnt].NAME)); memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); ibeacons[cnt].TIME=0; -#ifdef USE_IBEACON_ESP32 if (ibeacons[cnt].REPTIME >= IB_UPDATE_TIME) { ibeacons[cnt].REPTIME = 0; ibeacons[cnt].REPORTED = 0; } -#endif + ibeacons[cnt].count++; return 2; } } @@ -425,6 +368,7 @@ uint32_t ibeacon_add(struct IBEACON *ib) { } for (uint32_t cnt=0;cntNAME,sizeof(ibeacons[cnt].NAME)); memcpy(ibeacons[cnt].MAC,ib->MAC,12); memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); memcpy(ibeacons[cnt].UID,ib->UID,32); @@ -432,11 +376,13 @@ uint32_t ibeacon_add(struct IBEACON *ib) { memcpy(ibeacons[cnt].MINOR,ib->MINOR,4); ibeacons[cnt].FLAGS=1; ibeacons[cnt].TIME=0; -#ifdef USE_IBEACON_ESP32 memcpy(ibeacons[cnt].NAME,ib->NAME,16); ibeacons[cnt].REPTIME = 0; ibeacons[cnt].REPORTED = 0; -#endif + ibeacons[cnt].count = 0; + uint64_t now = esp_timer_get_time(); + uint32_t nowms = now/1000; + ibeacons[cnt].lastmqtt = nowms; return 1; } } @@ -444,245 +390,23 @@ uint32_t ibeacon_add(struct IBEACON *ib) { return 0; } -#ifndef USE_IBEACON_ESP32 - -void hm17_decode(void) { - struct IBEACON ib; - switch (hm17_cmd) { - case HM17_TEST: - if (!strncmp(hm17_sbuffer,"OK",2)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("AT OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - hm17_found=1; - } - break; - case HM17_ROLE: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("ROLE OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IMME: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("IMME OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IBEA: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("IBEA OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_SCAN: - if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("SCAN OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RESET: - if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("RESET OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RENEW: - if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("RENEW OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_CON: - if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("CONNA OK")); -#endif - hm17_connecting=2; - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); -#endif - break; - } - if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("CONN OK")); -#endif - hm17_connecting=3; - hm17_sendcmd(HM17_TEST); - hm17_connecting=0; - break; - } - break; - - case HM17_DISI: - case HM17_DISC: - if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("DISCS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISIS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("DISIS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { - hm17_sbclr(); - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR("DISCE OK")); -#endif - hm17_scanning=0; - break; - } - if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { - if (hm17_sbuffer[hm17_sindex-1]=='\n') { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog(LOG_LEVEL_INFO, PSTR("NAME OK")); - AddLog(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { - if (hm17_cmd==HM17_DISI) { -#ifdef HM17_V110 - goto hm17_v110; -#endif - } else { - if (hm17_sindex==20) { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog(LOG_LEVEL_INFO, PSTR("DIS0 OK")); - AddLog(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { -hm17_v110: - if (hm17_cmd==HM17_DISI) { - if (hm17_sindex==78) { -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog(LOG_LEVEL_INFO, PSTR("DISC: OK")); - //OK+DISC:4C 000C0E:003 A9144081A8 3B16849611 862EC1005: 0B1CE7485D :4DB4E940F C0E:-078 - AddLog(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - memcpy(ib.FACID,&hm17_sbuffer[8],8); - memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); - memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); - memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); - memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); - memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); - memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); - - if (ibeacon_add(&ib)) { - ibeacon_mqtt(ib.MAC,ib.RSSI,ib.UID,ib.MAJOR,ib.MINOR); - } - hm17_sbclr(); - hm17_result=1; - } - } else { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog(LOG_LEVEL_INFO, PSTR(">->%s"),&hm17_sbuffer[8]); -#endif - } - break; - } - } -} - -#endif void IBEACON_loop() { - -#ifdef USE_IBEACON_ESP32 //TasAutoMutex localmutex(&beaconmutex, "iBeacLoop"); - for (uint32_t cnt=0;cnt 10)) { + uint64_t now = esp_timer_get_time(); + uint32_t nowms = now/1000; + float countspermssec = ((float)ibeacons[cnt].count)/(((float)(nowms - ibeacons[cnt].lastmqtt))/1000.0); + // squash if it only just appeared + if (ibeacons[cnt].count < 2) countspermssec = 0.0; + ibeacon_mqtt(ibeacons[cnt].MAC,ibeacons[cnt].RSSI,ibeacons[cnt].UID,ibeacons[cnt].MAJOR,ibeacons[cnt].MINOR,ibeacons[cnt].NAME, (int)(countspermssec)); + ibeacons[cnt].count = 0; + ibeacons[cnt].lastmqtt = nowms; ibeacons[cnt].REPORTED=1; + ibeacons[cnt].REPTIME = 0; } } - -#else - - if (!IBEACON_Serial) return; - - uint32_t difftime=millis()-hm17_lastms; - - while (IBEACON_Serial->available()) { - hm17_lastms=millis(); - // shift in - if (hm17_sindexread(); - hm17_sindex++; - hm17_decode(); - } else { - hm17_sindex=0; - break; - } - } - - if (hm17_cmd==99) { - if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { - AddLog(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); - hm17_sbclr(); - } - } - -#endif - } #ifdef USE_WEBSERVER @@ -691,18 +415,14 @@ const char HTTP_IBEACON_mac[] PROGMEM = "{s}IBEACON-MAC : %s" " {m} RSSI : %s" "{e}"; const char HTTP_IBEACON_uid[] PROGMEM = "{s}IBEACON-UID : %s" " {m} RSSI : %s" "{e}"; -#ifdef USE_IBEACON_ESP32 const char HTTP_IBEACON_name[] PROGMEM = "{s}IBEACON-NAME : %s (%s)" " {m} RSSI : %s" "{e}"; -#endif void IBEACON_Show(void) { char mac[14]; char rssi[6]; char uid[34]; -#ifdef USE_IBEACON_ESP32 char name[18]; //TasAutoMutex localmutex(&beaconmutex, "iBeacShow"); -#endif int total = 0; for (uint32_t cnt=0;cnt='0' && *cp<='8') { - hm17_sendcmd(*cp&7); - Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); - } else if (*cp=='s') { - cp++; - len--; - while (*cp==' ') { - len--; - cp++; - } - IBEACON_Serial->write((uint8_t*)cp,len); - hm17_cmd=99; - Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); - } -#endif -#ifdef IBEACON_DEBUG - else if (*cp=='d') { - cp++; - hm17_debug=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"debug",hm17_debug); - } -#endif } else { serviced=false; } return serviced; } -#define D_CMND_IBEACON "IBEACON" - -#ifndef USE_IBEACON_ESP32 -//"IBEACON_FFFF3D1B1E9D_RSSI", Data "99" causes TAG to beep -bool ibeacon_cmd(void) { - ib_mac[0]=0; - int16_t rssi=0; - const char S_JSON_IBEACON[] = "{\"" D_CMND_IBEACON "_%s_RSSI\":%d}"; - uint8_t cmd_len = strlen(D_CMND_IBEACON); - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_IBEACON), cmd_len)) { - // IBEACON prefix - rssi = XdrvMailbox.payload; - if (rssi==99) { - memcpy(ib_mac,XdrvMailbox.topic+cmd_len+1,12); - ib_mac[12]=0; - if (hm17_scanning) { - // postpone sendbeep - hm17_flag|=2; - } else { - ib_sendbeep(); - } - } - Response_P(S_JSON_IBEACON,ib_mac,rssi); - return true; - } - return false; -} - -void ib_sendbeep(void) { - hm17_flag=0; - hm17_sendcmd(HM17_CON); -} - -#endif - -#ifdef USE_IBEACON_ESP32 -void ibeacon_mqtt(const char *mac,const char *rssi,const char *uid,const char *major,const char *minor, const char *name) { -#else -void ibeacon_mqtt(const char *mac,const char *rssi,const char *uid,const char *major,const char *minor) { -#endif +void ibeacon_mqtt(const char *mac,const char *rssi,const char *uid,const char *major,const char *minor, const char *name, int count) { char s_mac[14]; char s_uid[34]; char s_major[6]; char s_minor[6]; char s_rssi[6]; -#ifdef USE_IBEACON_ESP32 char *s_state; -#endif char s_name[18]; memcpy(s_mac,mac,12); s_mac[12]=0; @@ -867,32 +510,27 @@ void ibeacon_mqtt(const char *mac,const char *rssi,const char *uid,const char *m memcpy(s_rssi,rssi,4); s_rssi[4]=0; int16_t n_rssi=atoi(s_rssi); -#ifdef USE_IBEACON_ESP32 if (n_rssi) { s_state=(char *)"ON"; } else { s_state=(char *)"OFF"; } -#endif + memcpy(s_name,name,16); + s_name[16]=0; + // if uid == all zeros, take mac if (!strncmp_P(s_uid,PSTR("00000000000000000000000000000000"),32)) { -#ifdef USE_IBEACON_ESP32 if (name[0]) { - memcpy(s_name,name,16); - s_name[16]=0; - ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"NAME\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\"}}"),s_mac,s_name,n_rssi,s_state); + ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"NAME\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\",\"PERSEC\":%d}}"),s_mac,s_name,n_rssi,s_state, count); } else { - ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\"}}"),s_mac,n_rssi,s_state); + ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\",\"PERSEC\":%d}}"),s_mac,n_rssi,s_state, count); } -#else - ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"UID\":\"%s\",\"MAJOR\":\"%s\",\"MINOR\":\"%s\",\"RSSI\":%d}}"),s_mac,s_uid,s_major,s_minor,n_rssi); -#endif } else { -#ifdef USE_IBEACON_ESP32 - ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"UID\":\"%s\",\"MAJOR\":\"%s\",\"MINOR\":\"%s\",\"MAC\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\"}}"),s_uid,s_major,s_minor,s_mac,n_rssi,s_state); -#else - ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"UID\":\"%s\",\"MAJOR\":\"%s\",\"MINOR\":\"%s\",\"MAC\":\"%s\",\"RSSI\":%d}}"),s_uid,s_major,s_minor,s_mac,n_rssi); -#endif + if (name[0]) { + ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"MAC\":\"%s\",\"NAME\":\"%s\",\"MAJOR\":\"%s\",\"MINOR\":\"%s\",\"MAC\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\",\"PERSEC\":%d}}"),s_uid,s_name,s_major,s_minor,s_mac,n_rssi,s_state,count); + } else { + ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "\":{\"UID\":\"%s\",\"MAJOR\":\"%s\",\"MINOR\":\"%s\",\"MAC\":\"%s\",\"RSSI\":%d,\"STATE\":\"%s\",\"PERSEC\":%d}}"),s_uid,s_major,s_minor,s_mac,n_rssi,s_state,count); + } } MqttPublishTeleSensor(); @@ -911,46 +549,29 @@ bool Xsns52(byte function) case FUNC_INIT: IBEACON_Init(); break; -#ifdef USE_IBEACON_ESP32 - case FUNC_EVERY_250_MSECOND: - if (!ESP32BLE.mode.init) { - ESP32Init(); - } - break; -#endif case FUNC_LOOP: - IBEACON_loop(); + if (iBeaconEnable) IBEACON_loop(); break; case FUNC_EVERY_SECOND: -#ifdef USE_IBEACON_ESP32 - esp32_every_second(); -#else - hm17_every_second(); -#endif + if (iBeaconEnable) esp32_every_second(); break; + case FUNC_COMMAND: + result = DecodeCommand(kiBeacon_Commands, iBeacon_Commands); + break; + case FUNC_COMMAND_SENSOR: if (XSNS_52 == XdrvMailbox.index) { result = xsns52_cmd(); } break; -#ifndef USE_IBEACON_ESP32 - case FUNC_COMMAND: - result=ibeacon_cmd(); - break; -#endif #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: -#ifndef USE_IBEACON_ESP32 - if (hm17_found) IBEACON_Show(); -#else - IBEACON_Show(); -#endif + if (iBeaconEnable) IBEACON_Show(); break; #endif // USE_WEBSERVER } return result; } -#endif // USE_IBEACON - -#endif \ No newline at end of file +#endif // USE_BLE_ESP32 +#endif // CONFIG_IDF_TARGET_ESP32 diff --git a/tasmota/xsns_52_ibeacon.ino b/tasmota/xsns_52_ibeacon.ino index 188ed2941..93cce5eb8 100755 --- a/tasmota/xsns_52_ibeacon.ino +++ b/tasmota/xsns_52_ibeacon.ino @@ -31,16 +31,18 @@ #define IB_UPDATE_TIME_INTERVAL 10 // should be in Settings -#if 1 +//#if 1 uint8_t ib_upd_interval,ib_tout_interval; +//#undef IB_UPDATE_TIME +//#undef IB_TIMEOUT_TIME #define IB_UPDATE_TIME ib_upd_interval #define IB_TIMEOUT_TIME ib_tout_interval -#else -#undef IB_UPDATE_TIME -#undef IB_TIMEOUT_TIME -#define IB_UPDATE_TIME Settings.ib_upd_interval -#define IB_TIMEOUT_TIME Settings.ib_tout_interval -#endif +//#else +//#undef IB_UPDATE_TIME +//#undef IB_TIMEOUT_TIME +//#define IB_UPDATE_TIME Settings.ib_upd_interval +//#define IB_TIMEOUT_TIME Settings.ib_tout_interval +//#endif char ib_mac[14]; diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino index 403a2e938..cfa81b5ca 100644 --- a/tasmota/xsns_62_esp32_mi_ble.ino +++ b/tasmota/xsns_62_esp32_mi_ble.ino @@ -2649,28 +2649,31 @@ void MI32DiscoveryOneMISensor(){ p->nextDiscoveryData = 0; } + char DiscoveryTopic[80]; + const char *host = NetworkHostname(); + const char *devtype = kMI32DeviceType[p->type-1]; + char idstr[32]; + const char *alias = BLE_ESP32::getAlias(p->MAC); + const char *id = idstr; + if (alias && *alias){ + id = alias; + } else { + sprintf(idstr, PSTR("%s%02x%02x%02x"), + devtype, + p->MAC[3], p->MAC[4], p->MAC[5]); + } + + char SensorTopic[60]; + sprintf(SensorTopic, "tele/tasmota_ble/%s", + id); + + //int i = p->nextDiscoveryData*3; for (int i = 0; i < datacount*3; i += 3){ if (!classes[i] || !classes[i+1] || !classes[i+2]){ return; } - char idstr[32]; - const char *alias = BLE_ESP32::getAlias(p->MAC); - const char *id = idstr; - if (alias && *alias){ - id = alias; - } else { - sprintf(idstr, PSTR("%s%02x%02x%02x"), - kMI32DeviceType[p->type-1], - p->MAC[3], p->MAC[4], p->MAC[5]); - } - - char SensorTopic[60]; - sprintf(SensorTopic, "tele/tasmota_ble/%s", - id); - - ResponseClear(); /* @@ -2689,9 +2692,9 @@ void MI32DiscoveryOneMISensor(){ //"\"name\":\"%s\"}," id, //\"model\":\"%s\", - kMI32DeviceType[p->type-1], + devtype, //\"via_device\":\"%s\" - NetworkHostname(), + host, //"\"dev_cla\":\"%s\"," classes[i], //"\"json_attr_t\":\"%s\"," - the topic the sensor publishes on @@ -2709,7 +2712,6 @@ void MI32DiscoveryOneMISensor(){ // ); - char DiscoveryTopic[80]; sprintf(DiscoveryTopic, "homeassistant/sensor/%s/%s/config", id, classes[i+1]);