From 621beadb5ce69b98283ea16160801acdaf2faa9e Mon Sep 17 00:00:00 2001 From: geeksville Date: Sun, 23 Feb 2020 16:41:27 -0800 Subject: [PATCH] btle leak per sleep now down to about 500 bytes. --- .vscode/settings.json | 3 +- TODO.md | 2 + .../src/BluetoothSoftwareUpdate.cpp | 12 +++-- lib/BluetoothOTA/src/BluetoothUtil.cpp | 53 +++++++++++++++---- lib/BluetoothOTA/src/BluetoothUtil.h | 6 +++ src/MeshBluetoothService.cpp | 24 +++++---- 6 files changed, 74 insertions(+), 26 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6e6c96436..b797d0fe7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -44,6 +44,7 @@ "*.xbm": "cpp" }, "cSpell.words": [ - "Meshtastic" + "Meshtastic", + "descs" ] } \ No newline at end of file diff --git a/TODO.md b/TODO.md index 976089585..914579e53 100644 --- a/TODO.md +++ b/TODO.md @@ -3,6 +3,8 @@ Items to complete before the first alpha release. * the BLE stack is leaking about 7KB each time we go to light sleep +* manually delete characteristics/descs +* sync sleep windows to gps time * have state machine properly enter deep sleep based on loss of mesh and phone comms * default to enter deep sleep if no LORA received for two hours (indicates user has probably left the meshS) * implement CustomRF95::canSleep diff --git a/lib/BluetoothOTA/src/BluetoothSoftwareUpdate.cpp b/lib/BluetoothOTA/src/BluetoothSoftwareUpdate.cpp index a648364c7..d39397950 100644 --- a/lib/BluetoothOTA/src/BluetoothSoftwareUpdate.cpp +++ b/lib/BluetoothOTA/src/BluetoothSoftwareUpdate.cpp @@ -124,18 +124,20 @@ BLEService *createUpdateService(BLEServer *server) BLEService *service = server->createService("cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30"); assert(!resultC); - resultC = new (btPool) BLECharacteristic("5e134862-7411-4424-ac4a-210937432c77", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); + resultC = new BLECharacteristic("5e134862-7411-4424-ac4a-210937432c77", BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); - addWithDesc(service, new (btPool) TotalSizeCharacteristic, "total image size"); - addWithDesc(service, new (btPool) DataCharacteristic, "data"); - addWithDesc(service, new (btPool) CRC32Characteristic, "crc32"); + addWithDesc(service, new TotalSizeCharacteristic, "total image size"); + addWithDesc(service, new DataCharacteristic, "data"); + addWithDesc(service, new CRC32Characteristic, "crc32"); addWithDesc(service, resultC, "result code"); - resultC->addDescriptor(new (btPool) BLE2902()); // Needed so clients can request notification + resultC->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification return service; } void destroyUpdateService() { + assert(resultC); + resultC = NULL; } \ No newline at end of file diff --git a/lib/BluetoothOTA/src/BluetoothUtil.cpp b/lib/BluetoothOTA/src/BluetoothUtil.cpp index 6a16ad9db..f10abe1a1 100644 --- a/lib/BluetoothOTA/src/BluetoothUtil.cpp +++ b/lib/BluetoothOTA/src/BluetoothUtil.cpp @@ -16,8 +16,8 @@ BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendo { BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC)); - BLECharacteristic *swC = new (btPool) BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ); - BLECharacteristic *mfC = new (btPool) BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ); + BLECharacteristic *swC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ); + BLECharacteristic *mfC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ); // BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR), BLECharacteristic::PROPERTY_READ); /* @@ -30,14 +30,14 @@ BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendo m_pnpCharacteristic->setValue(pnp, sizeof(pnp)); */ swC->setValue(swVersion); - deviceInfoService->addCharacteristic(swC); + deviceInfoService->addCharacteristic(addBLECharacteristic(swC)); mfC->setValue(hwVendor); - deviceInfoService->addCharacteristic(mfC); + deviceInfoService->addCharacteristic(addBLECharacteristic(mfC)); if (!hwVersion.empty()) { - BLECharacteristic *hwvC = new (btPool) BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_HW_VERSION_STR), BLECharacteristic::PROPERTY_READ); + BLECharacteristic *hwvC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_HW_VERSION_STR), BLECharacteristic::PROPERTY_READ); hwvC->setValue(hwVersion); - deviceInfoService->addCharacteristic(hwvC); + deviceInfoService->addCharacteristic(addBLECharacteristic(hwvC)); } //SerialNumberCharacteristic.setValue("FIXME"); //deviceInfoService->addCharacteristic(&SerialNumberCharacteristic); @@ -68,18 +68,45 @@ class MyServerCallbacks : public BLEServerCallbacks } }; +#define MAX_DESCRIPTORS 32 +#define MAX_CHARACTERISTICS 32 + +static BLECharacteristic *chars[MAX_CHARACTERISTICS]; +static size_t numChars; +static BLEDescriptor *descs[MAX_DESCRIPTORS]; +static size_t numDescs; + +/// Add a characteristic that we will delete when we restart +BLECharacteristic *addBLECharacteristic(BLECharacteristic *c) +{ + assert(numChars < MAX_CHARACTERISTICS); + chars[numChars++] = c; + return c; +} + +/// Add a characteristic that we will delete when we restart +BLEDescriptor *addBLEDescriptor(BLEDescriptor *c) +{ + assert(numDescs < MAX_DESCRIPTORS); + descs[numDescs++] = c; + + return c; +} + // Help routine to add a description to any BLECharacteristic and add it to the service // We default to require an encrypted BOND for all these these characterstics void addWithDesc(BLEService *service, BLECharacteristic *c, const char *description) { c->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED); - BLEDescriptor *desc = new (btPool) BLEDescriptor(BLEUUID((uint16_t)ESP_GATT_UUID_CHAR_DESCRIPTION), strlen(description) + 1); + BLEDescriptor *desc = new BLEDescriptor(BLEUUID((uint16_t)ESP_GATT_UUID_CHAR_DESCRIPTION), strlen(description) + 1); assert(desc); desc->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED); desc->setValue(description); c->addDescriptor(desc); service->addCharacteristic(c); + addBLECharacteristic(c); + addBLEDescriptor(desc); } static BLECharacteristic *batteryLevelC; @@ -92,10 +119,10 @@ BLEService *createBatteryService(BLEServer *server) // Create the BLE Service BLEService *pBattery = server->createService(BLEUUID((uint16_t)0x180F)); - batteryLevelC = new (btPool) BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_BATTERY_LEVEL), BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); + batteryLevelC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_BATTERY_LEVEL), BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY); addWithDesc(pBattery, batteryLevelC, "Percentage 0 - 100"); - batteryLevelC->addDescriptor(new (btPool) BLE2902()); // Needed so clients can request notification + batteryLevelC->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification // I don't think we need to advertise this // server->getAdvertising()->addServiceUUID(pBattery->getUUID()); @@ -210,6 +237,14 @@ void deinitBLE() batteryLevelC = NULL; // Don't let anyone generate bogus notifies destroyUpdateService(); + for (int i = 0; i < numChars; i++) + delete chars[i]; + numChars = 0; + + for (int i = 0; i < numDescs; i++) + delete descs[i]; + numDescs = 0; + btPool.reset(); } diff --git a/lib/BluetoothOTA/src/BluetoothUtil.h b/lib/BluetoothOTA/src/BluetoothUtil.h index d86d81a08..72920aec8 100644 --- a/lib/BluetoothOTA/src/BluetoothUtil.h +++ b/lib/BluetoothOTA/src/BluetoothUtil.h @@ -21,5 +21,11 @@ void loopBLE(); BLEServer *initBLE(std::string devName, std::string hwVendor, std::string swVersion, std::string hwVersion = ""); void deinitBLE(); +/// Add a characteristic that we will delete when we restart +BLECharacteristic *addBLECharacteristic(BLECharacteristic *c); + +/// Add a characteristic that we will delete when we restart +BLEDescriptor *addBLEDescriptor(BLEDescriptor *c); + /// Any bluetooth objects you allocate _must_ come from this pool if you want to be able to call deinitBLE() extern SimpleAllocator btPool; diff --git a/src/MeshBluetoothService.cpp b/src/MeshBluetoothService.cpp index 625676952..a5db6ca25 100644 --- a/src/MeshBluetoothService.cpp +++ b/src/MeshBluetoothService.cpp @@ -300,24 +300,25 @@ BLEService *createMeshBluetoothService(BLEServer *server) BLEService *service = server->createService(BLEUUID("6ba1b218-15a8-461f-9fa8-5dcae273eafd"), 25, 0); assert(!meshFromNumCharacteristic); - meshFromNumCharacteristic = new (btPool) FromNumCharacteristic; + meshFromNumCharacteristic = new FromNumCharacteristic; addWithDesc(service, meshFromNumCharacteristic, "fromRadio"); - addWithDesc(service, new (btPool) ToRadioCharacteristic, "toRadio"); - addWithDesc(service, new (btPool) FromRadioCharacteristic, "fromNum"); + addWithDesc(service, new ToRadioCharacteristic, "toRadio"); + addWithDesc(service, new FromRadioCharacteristic, "fromNum"); - addWithDesc(service, new (btPool) ProtobufCharacteristic("ea9f3f82-8dc4-4733-9452-1f6da28892a2", BLECharacteristic::PROPERTY_READ, MyNodeInfo_fields, &myNodeInfo), "myNode"); - addWithDesc(service, new (btPool) RadioCharacteristic, "radio"); - addWithDesc(service, new (btPool) OwnerCharacteristic, "owner"); - addWithDesc(service, new (btPool) NodeInfoCharacteristic, "nodeinfo"); + addWithDesc(service, new ProtobufCharacteristic("ea9f3f82-8dc4-4733-9452-1f6da28892a2", BLECharacteristic::PROPERTY_READ, MyNodeInfo_fields, &myNodeInfo), "myNode"); + addWithDesc(service, new RadioCharacteristic, "radio"); + addWithDesc(service, new OwnerCharacteristic, "owner"); + addWithDesc(service, new NodeInfoCharacteristic, "nodeinfo"); - meshFromNumCharacteristic->addDescriptor(new (btPool) BLE2902()); // Needed so clients can request notification + meshFromNumCharacteristic->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification service->start(); // We only add to advertisting once, because the ESP32 arduino code is dumb and that object never dies static bool firstTime = true; - if(firstTime) { + if (firstTime) + { firstTime = false; server->getAdvertising()->addServiceUUID(service->getUUID()); } @@ -329,9 +330,10 @@ BLEService *createMeshBluetoothService(BLEServer *server) return service; } -void destroyMeshBluetoothService() { +void destroyMeshBluetoothService() +{ assert(meshService); delete meshService; - + meshFromNumCharacteristic = NULL; } \ No newline at end of file