diff --git a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino index 2c5aa816dd12..d4058c880317 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_79_esp32_ble.ino @@ -84,7 +84,8 @@ performs a manual scan or set passive/active *BLEScan0 0 - set passive scan BLEScan0 1 - set active scan (you may get names) - BLEScan1 nn - start a manula scan for nn seconds + BLEScan1 nn - start a manual scan for nn seconds + BLEScan2 nn - start a manual scan for nn seconds and publish on tele when at least one device is found BLEAlias = = - set one or more aliases for addresses BLEName @@ -108,6 +109,9 @@ BLEEnableUnsaved *0/1 - if BLE is disabled, this can be used to enable BLE without it being saved - useful as the last command in autoexec.bat + BLEFilterNames + BLEFilterNames0 - clear filter list + BLEFilterNames1 - , - set one or more device names Other drivers can add callbacks to receive advertisements Other drivers can add 'operations' to be performed and receive callbacks from the operation's success or failure @@ -134,6 +138,8 @@ i.e. the Bluetooth of the ESP can be shared without conflict. */ #define BLE_ESP32_ALIASES +#define BLE_ESP32_FILTER_BY_NAME +#define BLE_ESP32_FILTER_BY_RSSI // uncomment for more diagnostic/information messages - + more flash use. //#define BLE_ESP32_DEBUG @@ -472,6 +478,12 @@ std::deque scancompleteCallbacks; std::deque aliases; #endif +#ifdef BLE_ESP32_FILTER_BY_NAME +std::vector bleFilterNames; +#endif +#ifdef BLE_ESP32_FILTER_BY_RSSI +int minRSSI = -100; +#endif /*********************************************************************************************\ * constants @@ -480,7 +492,7 @@ std::deque aliases; #define D_CMND_BLE "BLE" const char kBLE_Commands[] PROGMEM = D_CMND_BLE "|" - "Period|Adv|Op|Mode|Details|Scan|Alias|Name|Debug|Devices|MaxAge|AddrFilter|EnableUnsaved"; + "Period|Adv|Op|Mode|Details|Scan|Alias|Name|Debug|Devices|MaxAge|AddrFilter|EnableUnsaved|FilterNames|MinRssiLevel"; static void CmndBLEPeriod(void); static void CmndBLEAdv(void); @@ -495,6 +507,8 @@ static void CmndBLEDevices(void); static void CmndBLEMaxAge(void); static void CmndBLEAddrFilter(void); static void CmndBLEEnableUnsaved(void); +static void CmndBleFilterNames(void); +static void CmndSetMinRSSI(void); void (*const BLE_Commands[])(void) PROGMEM = { &BLE_ESP32::CmndBLEPeriod, @@ -509,7 +523,9 @@ void (*const BLE_Commands[])(void) PROGMEM = { &BLE_ESP32::CmndBLEDevices, &BLE_ESP32::CmndBLEMaxAge, &BLE_ESP32::CmndBLEAddrFilter, - &BLE_ESP32::CmndBLEEnableUnsaved + &BLE_ESP32::CmndBLEEnableUnsaved, + &BLE_ESP32::CmndBleFilterNames, + &BLE_ESP32::CmndSetMinRSSI }; const char *successStates[] PROGMEM = { @@ -588,6 +604,7 @@ uint8_t BLEMode = BLEModeRegularScan; uint8_t BLETriggerScan = 0; uint8_t BLEAdvertMode = BLE_ADV_TELE; uint8_t BLEdeviceLimitReached = 0; +uint8_t BLEpostWhenFound = 0; uint8_t BLEStop = 0; uint64_t BLEStopAt = 0; @@ -1128,7 +1145,24 @@ void ReverseMAC(uint8_t _mac[]){ } - +/** + * @brief Search for device name in filer list + * + * @param deviceName device name string + */ +#ifdef BLE_ESP32_FILTER_BY_NAME +bool isDeviceInFilter(const String& deviceName) { +#ifdef BLE_ESP32_DEBUG + if (BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Device chcked in filter %s"), deviceName); +#endif + for (const auto& filterName : bleFilterNames) { + if (deviceName == filterName) { + return true; + } + } + return false; +} +#endif /*********************************************************************************************\ * Advertisment details @@ -1372,9 +1406,24 @@ class BLEAdvCallbacks: public NimBLEScanCallbacks { BLEAdvertisment.name[sizeof(BLEAdvertisment.name)-1] = 0; } + int filter = 0; +#ifdef BLE_ESP32_FILTER_BY_NAME + if (!bleFilterNames.empty()) { + if (!advertisedDevice->haveName() || !isDeviceInFilter(namestr)) + { + filter = 1; + } + } +#endif + +#ifdef BLE_ESP32_FILTER_BY_RSSI + if (advertisedDevice->getRSSI() < minRSSI) { + filter = 1; + } +#endif // log this device safely - if (BLEAdvertisment.addrtype <= BLEAddressFilter){ + if ((BLEAdvertisment.addrtype <= BLEAddressFilter) && (0 == filter) ){ addSeenDevice(BLEAdvertisment.addr, BLEAdvertisment.addrtype, BLEAdvertisment.name, BLEAdvertisment.RSSI); } @@ -2300,6 +2349,12 @@ static void BLEEverySecond(bool restart){ BLE_ESP32::BLEPostMQTT(false); // show all operations, not just completed } + if ((BLEpostWhenFound == 1) && (seenDevices.size() > 0)) + { + BLEPublishDevices = 2; // mqtt publish as 'STAT' + BLEpostWhenFound = 0; + } + if (BLEPublishDevices){ BLEPostMQTTSeenDevices(BLEPublishDevices); BLEShowStats(); @@ -2678,6 +2733,8 @@ void CmndBLEScan(void){ } } break; + case 2: // post on tele when at leat one device is found + BLEpostWhenFound = 1; case 1: // do a manual scan now switch (BLEMode){ case BLEModeScanByCommand: { @@ -2833,6 +2890,58 @@ void CmndBLEDetails(void){ } +void CmndBleFilterNames(void) { +#ifdef BLE_ESP32_FILTER_BY_NAME + int op = XdrvMailbox.index; +#ifdef BLE_ESP32_DEBUG + if (BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("BLE: Name %d %s"), op, XdrvMailbox.data); +#endif + + switch(op){ + case 0:{ + bleFilterNames.clear(); + ResponseCmndDone(); + } break; + case 1:{ + if (XdrvMailbox.data_len) { + String filters = XdrvMailbox.data; + bleFilterNames.clear(); + + int start = 0; + int end = filters.indexOf(','); + while (end != -1) { + bleFilterNames.push_back(filters.substring(start, end)); + start = end + 1; + end = filters.indexOf(',', start); + } + bleFilterNames.push_back(filters.substring(start)); + + Response_P(PSTR("{\"BLEFilterNames\":\"%s\"}"), filters.c_str()); + } else { + String filterList; + for (const auto& name : bleFilterNames) { + if (!filterList.isEmpty()) { + filterList += ", "; + } + filterList += name; + } + + Response_P(PSTR("{\"BLEFilterNames\":\"%s\"}"), filterList.c_str()); + } + } break; + } +#endif +} + +void CmndSetMinRSSI(void) { +#ifdef BLE_ESP32_FILTER_BY_RSSI + if (XdrvMailbox.data_len) { + minRSSI = atoi(XdrvMailbox.data); + } + Response_P(PSTR("{\"MinRSSI\":\"%d\"}"), minRSSI); +#endif +} + void CmndBLEAlias(void){ #ifdef BLE_ESP32_ALIASES int op = XdrvMailbox.index;