From 4616b5e0204bde57ed0a6e8d01f30100de111a3d Mon Sep 17 00:00:00 2001 From: technyon Date: Tue, 5 Apr 2022 21:35:21 +0200 Subject: [PATCH] add code for presence detection --- CMakeLists.txt | 1 + NukiWrapper.cpp | 24 ++++++++--- NukiWrapper.h | 5 ++- PresenceDetection.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++ PresenceDetection.h | 28 +++++++++++++ lib/nuki_ble | 2 +- main.cpp | 16 +++++++- 7 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 PresenceDetection.cpp create mode 100644 PresenceDetection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e04476..18ad99c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ file(GLOB SRCFILES NukiWrapper.cpp MqttTopics.h WebCfgServer.cpp + PresenceDetection.cpp PreferencesKeys.h lib/ESP32_BLE_Arduino-1.0.1/src/*.cpp lib/ESP32_BLE_Arduino-1.0.1/src/*.h diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 5bec582..286b075 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -19,12 +19,21 @@ NukiWrapper::NukiWrapper(const std::string& name, uint32_t id, Network* network, network->setLockActionReceived(nukiInst->onLockActionReceived); } + +NukiWrapper::~NukiWrapper() +{ + delete _bleScanner; + _bleScanner = nullptr; +} + + void NukiWrapper::initialize() { - _bleScanner.initialize(); - _bleScanner.setScanDuration(30); + _bleScanner = new BleScanner(); + _bleScanner->initialize(); + _bleScanner->setScanDuration(30); _nukiBle.initialize(); - _nukiBle.registerBleScanner(&_bleScanner); + _nukiBle.registerBleScanner(_bleScanner); _intervalLockstate = _preferences->getInt(preference_query_interval_lockstate); _intervalBattery = _preferences->getInt(preference_query_interval_battery); @@ -53,7 +62,7 @@ void NukiWrapper::update() if (!_paired) { Serial.println(F("Nuki start pairing")); - _bleScanner.update(); + _bleScanner->update(); vTaskDelay( 5000 / portTICK_PERIOD_MS); if (_nukiBle.pairNuki()) { Serial.println(F("Nuki paired")); @@ -67,7 +76,7 @@ void NukiWrapper::update() } vTaskDelay( 20 / portTICK_PERIOD_MS); - _bleScanner.update(); + _bleScanner->update(); unsigned long ts = millis(); @@ -149,6 +158,11 @@ const bool NukiWrapper::isPaired() return _paired; } +BleScanner *NukiWrapper::bleScanner() +{ + return _bleScanner; +} + void NukiWrapper::notify(Nuki::EventType eventType) { if(eventType == Nuki::EventType::KeyTurnerStatusUpdated) diff --git a/NukiWrapper.h b/NukiWrapper.h index a46671f..c019cf8 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -9,12 +9,15 @@ class NukiWrapper : public Nuki::SmartlockEventHandler { public: NukiWrapper(const std::string& name, uint32_t id, Network* network, Preferences* preferences); + virtual ~NukiWrapper(); void initialize(); void update(); const bool isPaired(); + BleScanner* bleScanner(); + void notify(Nuki::EventType eventType) override; private: @@ -26,7 +29,7 @@ private: Nuki::LockAction lockActionToEnum(const char* str); // char array at least 14 characters Nuki::NukiBle _nukiBle; - BleScanner _bleScanner; + BleScanner* _bleScanner; Network* _network; Preferences* _preferences; int _intervalLockstate = 0; // seconds diff --git a/PresenceDetection.cpp b/PresenceDetection.cpp new file mode 100644 index 0000000..74716dc --- /dev/null +++ b/PresenceDetection.cpp @@ -0,0 +1,94 @@ +#include "PresenceDetection.h" + +PresenceDetection::PresenceDetection(BleScanner *bleScanner) +: _bleScanner(bleScanner) +{} + +PresenceDetection::~PresenceDetection() +{ + _bleScanner->unsubscribe(this); + _bleScanner = nullptr; +} + +void PresenceDetection::initialize() +{ + _bleScanner->subscribe(this); +} + +void PresenceDetection::update() +{ + vTaskDelay( 10000 / portTICK_PERIOD_MS); + + long ts = millis(); + for(auto it : _devices) + { + if(ts - 20000 < it.second.timestamp) + { + // TODO: publish to mqtt + } + } +} + +void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) +{ + std::string addressStr = device->getAddress().toString(); + char addrArrComp[13] = {0}; +// aa:bb:cc:dd:ee:ff + addrArrComp[0] = addressStr.at(0); + addrArrComp[1] = addressStr.at(1); + addrArrComp[2] = addressStr.at(3); + addrArrComp[3] = addressStr.at(4); + addrArrComp[4] = addressStr.at(6); + addrArrComp[5] = addressStr.at(7); + addrArrComp[6] = addressStr.at(9); + addrArrComp[7] = addressStr.at(10); + addrArrComp[8] = addressStr.at(12); + addrArrComp[9] = addressStr.at(13); + addrArrComp[10] = addressStr.at(15); + addrArrComp[11] = addressStr.at(16); + + long long addr = strtoll(addrArrComp, nullptr, 16); + + auto it = _devices.find(addr); + if(it == _devices.end()) + { + PdDevice pdDevice; + + int i=0; + size_t len = addressStr.length(); + while(i < len) + { + pdDevice.address[i] = addressStr.at(i); + ++i; + } + + if(device->haveName()) + { + std::string nameStr = device->getName(); + + int i=0; + size_t len = nameStr.length(); + while(i < len && i < sizeof(pdDevice.name)-1) + { + pdDevice.name[i] = nameStr.at(i); + ++i; + } + + pdDevice.timestamp = millis(); + + _devices[addr] = pdDevice; + } + } + else + { + it->second.timestamp = millis(); + } + +// if(device->haveName()) +// { +// Serial.print(" | "); +// Serial.print(device->getName().c_str()); +// } +// Serial.println(); + +} diff --git a/PresenceDetection.h b/PresenceDetection.h new file mode 100644 index 0000000..e2dc089 --- /dev/null +++ b/PresenceDetection.h @@ -0,0 +1,28 @@ +#pragma once + +#include "BleScanner.h" +#include "BleInterfaces.h" + +struct PdDevice +{ + char address[18] = {0}; + char name[30] = {0}; + unsigned long timestamp; +}; + +class PresenceDetection : public BLEScannerSubscriber +{ +public: + PresenceDetection(BleScanner* bleScanner); + virtual ~PresenceDetection(); + + void initialize(); + void update(); + + void onResult(NimBLEAdvertisedDevice* advertisedDevice) override; + +private: + BleScanner* _bleScanner; + std::map _devices; + uint _timeout = 20000; +}; diff --git a/lib/nuki_ble b/lib/nuki_ble index d2ca3c1..54c1247 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit d2ca3c1ae4f9a421865aaff92e86698da083cf33 +Subproject commit 54c124790b994696752c1a72daada5f72fe85a10 diff --git a/main.cpp b/main.cpp index 031aced..223bc46 100644 --- a/main.cpp +++ b/main.cpp @@ -4,12 +4,14 @@ #include "WebCfgServer.h" #include #include "PreferencesKeys.h" +#include "PresenceDetection.h" #define ESP32 Network* network; WebCfgServer* webCfgServer; NukiWrapper* nuki; +PresenceDetection* presenceDetection; Preferences* preferences; void networkTask(void *pvParameters) @@ -29,10 +31,19 @@ void nukiTask(void *pvParameters) } } +void presenceDetectionTask(void *pvParameters) +{ + while(true) + { + presenceDetection->update(); + } +} + void setupTasks() { xTaskCreate(networkTask, "ntw", 16384, NULL, 1, NULL); xTaskCreate(nukiTask, "nuki", 8192, NULL, 1, NULL); + xTaskCreate(presenceDetectionTask, "prdet", 1024, NULL, 1, NULL); } uint32_t getRandomId() @@ -66,8 +77,11 @@ void setup() nuki = new NukiWrapper("ESP", deviceId, network, preferences); webCfgServer = new WebCfgServer(nuki, network, preferences); webCfgServer->initialize(); - nuki->initialize(); + + presenceDetection = new PresenceDetection(nuki->bleScanner()); + presenceDetection->initialize(); + setupTasks(); }