diff --git a/platformio.ini b/platformio.ini index 13914cc..e51533c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,7 +30,8 @@ lib_deps = ; https://github.com/thorrak/ESPAsyncWebServer.git https://github.com/thorrak/Arduino-Log.git ; // Need this until ArduinoLog merges https://github.com/thijse/Arduino-Log/pull/21 lib_deps_bluetooth = - h2zero/NimBLE-Arduino @ ^1.4.1 ; https://github.com/h2zero/NimBLE-Arduino.git + https://github.com/h2zero/NimBLE-Arduino.git#master ; Need this until this gets merged: https://github.com/h2zero/NimBLE-Arduino/commit/c7ce2892280f5eb9bcfe541ff9765d527472a6da + ; h2zero/NimBLE-Arduino @ ^2.1.0 ; https://github.com/h2zero/NimBLE-Arduino.git ; Let's also include some other common build flags for ease-of-use build_flags = diff --git a/src/DeviceManager.cpp b/src/DeviceManager.cpp index 98b2810..06b5e9f 100644 --- a/src/DeviceManager.cpp +++ b/src/DeviceManager.cpp @@ -388,8 +388,11 @@ DeviceDefinition DeviceManager::readJsonIntoDeviceDef(const JsonDocument& doc) { break; #ifdef HAS_BLUETOOTH case DEVICE_HARDWARE_BLUETOOTH_INKBIRD: + dev.btAddress = NimBLEAddress(doc[DeviceDefinitionKeys::address].as(), 0); + break; case DEVICE_HARDWARE_BLUETOOTH_TILT: - dev.btAddress = NimBLEAddress(doc[DeviceDefinitionKeys::address].as()); + // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) + dev.btAddress = NimBLEAddress(doc[DeviceDefinitionKeys::address].as(), 1); break; #endif #ifdef EXTERN_SENSOR_ACTUATOR_SUPPORT diff --git a/src/DeviceManagerFiles.cpp b/src/DeviceManagerFiles.cpp index ad35abd..ce48c26 100644 --- a/src/DeviceManagerFiles.cpp +++ b/src/DeviceManagerFiles.cpp @@ -105,8 +105,12 @@ void DeviceConfig::fromJson(JsonDocument json_doc) { parseBytes(hw.address, json_doc[DeviceDefinitionKeys::address].as(), 8); copyArray(json_doc[DeviceDefinitionKeys::address], hw.address); #ifdef HAS_BLUETOOTH - } else if(json_doc[DeviceDefinitionKeys::address].is() && (deviceHardware == DEVICE_HARDWARE_BLUETOOTH_INKBIRD || deviceHardware == DEVICE_HARDWARE_BLUETOOTH_TILT)) { - hw.btAddress = NimBLEAddress(json_doc[DeviceDefinitionKeys::address].as()); + } else if(json_doc[DeviceDefinitionKeys::address].is() && (deviceHardware == DEVICE_HARDWARE_BLUETOOTH_INKBIRD)) { + // Inkbirds use address type 0 ("public") which (incorrectly!) indicates they bought a MAC block + hw.btAddress = NimBLEAddress(json_doc[DeviceDefinitionKeys::address].as(), 0); + } else if(json_doc[DeviceDefinitionKeys::address].is() && (deviceHardware == DEVICE_HARDWARE_BLUETOOTH_TILT)) { + // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) + hw.btAddress = NimBLEAddress(json_doc[DeviceDefinitionKeys::address].as(), 1); #endif #ifdef EXTERN_SENSOR_ACTUATOR_SUPPORT } else if(json_doc[DeviceDefinitionKeys::address].is() && json_doc[DeviceDefinitionKeys::child_id].is() && (deviceHardware == DEVICE_HARDWARE_TPLINK_SWITCH)) { diff --git a/src/EepromStructs.cpp b/src/EepromStructs.cpp index 3a69bba..53488fa 100644 --- a/src/EepromStructs.cpp +++ b/src/EepromStructs.cpp @@ -18,7 +18,8 @@ #include "Display.h" #ifdef HAS_BLUETOOTH -NimBLEAddress NoTiltDevice = NimBLEAddress("00:00:00:00:00:00"); +// Tilts have address type 1, so replicating that here (even though this is wrong based on the address) +NimBLEAddress NoTiltDevice = NimBLEAddress("00:00:00:00:00:00", 1); #endif @@ -338,7 +339,8 @@ void ExtendedSettings::loadFromSpiffs() { if(json_doc[ExtendedSettingsKeys::glycol].is()) glycol = json_doc[ExtendedSettingsKeys::glycol]; if(json_doc[ExtendedSettingsKeys::largeTFT].is()) largeTFT = json_doc[ExtendedSettingsKeys::largeTFT]; #ifdef HAS_BLUETOOTH - if(json_doc[ExtendedSettingsKeys::tiltGravSensor].is()) tiltGravSensor = NimBLEAddress(json_doc[ExtendedSettingsKeys::tiltGravSensor].as()); + // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) + if(json_doc[ExtendedSettingsKeys::tiltGravSensor].is()) tiltGravSensor = NimBLEAddress(json_doc[ExtendedSettingsKeys::tiltGravSensor].as(), 1); #endif } @@ -367,7 +369,8 @@ void ExtendedSettings::processSettingKeypair(JsonPair kv) { } #ifdef HAS_BLUETOOTH else if (kv.key() == ExtendedSettingsKeys::tiltGravSensor) { - NimBLEAddress addr = NimBLEAddress(kv.value().as()); + // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) + NimBLEAddress addr = NimBLEAddress(kv.value().as(), 1); setTiltGravSensor(addr); } #endif diff --git a/src/http_server.cpp b/src/http_server.cpp index a005472..7718112 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -309,8 +309,9 @@ uint8_t processExtendedSettingsJson(const JsonDocument& json, bool triggerUpstre // Tilt Gravity Sensor if(json[ExtendedSettingsKeys::tiltGravSensor].is()) { // Validate that it's valid - if(extendedSettings.tiltGravSensor != json[ExtendedSettingsKeys::tiltGravSensor].as()) { - extendedSettings.setTiltGravSensor(NimBLEAddress(json[ExtendedSettingsKeys::tiltGravSensor].as())); + if(extendedSettings.tiltGravSensor != NimBLEAddress(json[ExtendedSettingsKeys::tiltGravSensor].as(), 1)) { + // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) + extendedSettings.setTiltGravSensor(NimBLEAddress(json[ExtendedSettingsKeys::tiltGravSensor].as(), 1)); saveSettings = true; } } diff --git a/src/wireless/BTScanner.cpp b/src/wireless/BTScanner.cpp index 7de5815..f7836e2 100644 --- a/src/wireless/BTScanner.cpp +++ b/src/wireless/BTScanner.cpp @@ -27,12 +27,12 @@ std::list lTilts; //////////////////////////// -void load_inkbird_from_advert(NimBLEAdvertisedDevice* advertisedDevice); -void load_tilt_from_advert(NimBLEAdvertisedDevice* advertisedDevice); +void load_inkbird_from_advert(const NimBLEAdvertisedDevice* advertisedDevice); +void load_tilt_from_advert(const NimBLEAdvertisedDevice* advertisedDevice); /** Handles callbacks when advertisments are received */ -class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks { - void onResult(NimBLEAdvertisedDevice* advertisedDevice) { +class ScanCallbacks: public NimBLEScanCallbacks { + void onResult(const NimBLEAdvertisedDevice* advertisedDevice) { bt_scanner.last_detected_device_at = esp_timer_get_time(); // Inkbird IBS-TH2 (sps) and Inkbird IBS-TH1 (tps) if((advertisedDevice->getName().rfind("sps",0) == 0 || advertisedDevice->getName().rfind("tps",0) == 0) && advertisedDevice->getManufacturerData().length() == 9) { @@ -55,7 +55,7 @@ class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks { }; -void load_inkbird_from_advert(NimBLEAdvertisedDevice* advertisedDevice) +void load_inkbird_from_advert(const NimBLEAdvertisedDevice* advertisedDevice) { // The advertisement string is the "manufacturer data" part of the following: // example: f208361300f28b6408 @@ -95,7 +95,8 @@ void load_inkbird_from_advert(NimBLEAdvertisedDevice* advertisedDevice) // Since we need to fake one of the MAC addresses and the internal sensor will ALWAYS be connected/reported, what we can do // is fake the address of the EXTERNAL sensor. This way, the true MAC address will always be present (and always report the // internal sensor's temperature) and in the case of failure of the probe, the external sensor will just stop reporting. - inkbird *ib_external = bt_scanner.get_or_create_inkbird(NimBLEAddress(advertisedDevice->getAddress() + 0x010000000000)); + // NOTE - Technically address type 0 here is wrong, but it matches what Inkbird uses otherwise + inkbird *ib_external = bt_scanner.get_or_create_inkbird(NimBLEAddress(advertisedDevice->getAddress() + 0x010000000000, 0)); ib->update(alt_temp, hum, bat, advertisedDevice->getRSSI()); ib_external->update(temp, hum, bat, advertisedDevice->getRSSI()); } else { @@ -105,7 +106,7 @@ void load_inkbird_from_advert(NimBLEAdvertisedDevice* advertisedDevice) return; } -void load_tilt_from_advert(NimBLEAdvertisedDevice* advertisedDevice) +void load_tilt_from_advert(const NimBLEAdvertisedDevice* advertisedDevice) { // The advertisement string is the "manufacturer data" part of the following: //Advertised Device: Name: Tilt, Address: 88:c2:55:ac:26:81, manufacturer data: 4c000215a495bb40c5b14b44b5121370f02d74de005004d9c5 @@ -174,11 +175,11 @@ void btScanner::init() NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */ NimBLEScan* pBLEScan = NimBLEDevice::getScan(); // Create/get the scan // NOTE - The below probably creates a memory leak with deinit (but deinit is never called in our code). - pBLEScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks()); // Initialize the callbacks + pBLEScan->setScanCallbacks(new ScanCallbacks()); // Initialize the callbacks pBLEScan->setMaxResults(0); pBLEScan->setActiveScan(true); // Required for some devices (including Inkbird sensors) - active scan actively queries devices for more info following detection. - pBLEScan->setInterval(97); // Select prime numbers to reduce risk of frequency beat pattern with ibeacon advertisement interval - pBLEScan->setWindow(37); // Set to less or equal setInterval value. Leave reasonable gap to allow WiFi some time. + // pBLEScan->setInterval(97); // Select prime numbers to reduce risk of frequency beat pattern with ibeacon advertisement interval + // pBLEScan->setWindow(37); // Set to less or equal setInterval value. Leave reasonable gap to allow WiFi some time. } @@ -188,8 +189,8 @@ bool btScanner::scan() return false; if (NimBLEDevice::getScan()->isScanning()) return false; - delay(400); - if (NimBLEDevice::getScan()->start(BLE_SCAN_TIME, nullptr, false)) + delay(200); + if (NimBLEDevice::getScan()->start(BLE_SCAN_TIME, false, true)) return true; //Scan successfully started. return false; //Scan failed to start } diff --git a/src/wireless/BTScanner.h b/src/wireless/BTScanner.h index c83739c..87cc0b4 100644 --- a/src/wireless/BTScanner.h +++ b/src/wireless/BTScanner.h @@ -5,8 +5,9 @@ #include "Inkbird.h" #include "Tilt.h" +#include -#define BLE_SCAN_TIME 60 // Seconds to scan (0=continuous scanning) +#define BLE_SCAN_TIME 60*1000 // Milliseconds to scan (0=continuous scanning) #define SCAN_FAIL_THRESHHOLD (2*60*1000*1000) // If we don't detect anything in 2 minutes, then the scanner failed. class btScanner