#include "PresenceDetection.h" #include "PreferencesKeys.h" #include "Logger.h" #include "CharBuffer.h" #include #include #include "NimBLEBeacon.h" #include "NukiUtils.h" PresenceDetection::PresenceDetection(Preferences* preferences, BleScanner::Scanner *bleScanner, char* buffer, size_t bufferSize) : _preferences(preferences), _bleScanner(bleScanner), _csv(buffer), _bufferSize(bufferSize) { _timeout = _preferences->getInt(preference_presence_detection_timeout, 0) * 1000; if(_timeout == 0) { _timeout = 60000; _preferences->putInt(preference_presence_detection_timeout, 60); } Log->print(F("Presence detection timeout (ms): ")); Log->println(_timeout); } PresenceDetection::~PresenceDetection() { _bleScanner->unsubscribe(this); _bleScanner = nullptr; delete _csv; _csv = nullptr; } void PresenceDetection::initialize() { _bleScanner->subscribe(this); } char* PresenceDetection::generateCsv() { if(!enabled()) return nullptr; memset(_csv, 0, _bufferSize); _csvIndex = 0; int64_t ts = esp_timer_get_time() / 1000; { std::lock_guard lock(mtx); for (auto it: _devices) { if (ts - _timeout < it.second->timestamp) { buildCsv(it.second); } // Prevent csv buffer overflow if (_csvIndex > _bufferSize - (sizeof(it.second->name) + sizeof(it.second->address) + 10)) { break; } } } if(_csvIndex == 0) { strcpy(_csv, ";;"); return _csv; } _csv[_csvIndex-1] = 0x00; return _csv; } void PresenceDetection::buildCsv(const std::shared_ptr& device) { for(int i = 0; i < 17; i++) { _csv[_csvIndex] = device->address[i]; ++_csvIndex; } _csv[_csvIndex] = ';'; ++_csvIndex; int i=0; while(device->name[i] != 0x00 && i < sizeof(device->name)) { _csv[_csvIndex] = device->name[i]; ++_csvIndex; ++i; } _csv[_csvIndex] = ';'; ++_csvIndex; char rssiStr[20] = {0}; itoa(device->rssi, rssiStr, 10); int j=0; while(rssiStr[j] != 0x00 && j < 20) { _csv[_csvIndex] = rssiStr[j]; ++_csvIndex; ++j; } _csv[_csvIndex] = '\n'; _csvIndex++; } void PresenceDetection::onResult(NimBLEAdvertisedDevice *device) { std::string addressStr = device->getAddress().toString(); char addrArrComp[13] = {0}; // Log->println(addressStr.c_str()); 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); int64_t addr = strtoll(addrArrComp, nullptr, 16); bool found; { std::lock_guard lock(mtx); auto it = _devices.find(addr); found = (it != _devices.end()); if(found) { it->second->timestamp = esp_timer_get_time() / 1000; it->second->rssi = device->getRSSI(); } } if(!found) { std::shared_ptr pdDevice = std::make_shared(); int i=0; size_t len = addressStr.length(); while(i < len) { pdDevice->address[i] = addressStr.at(i); ++i; } pdDevice->rssi = device->getRSSI(); std::string nameStr = "-"; if(device->haveName()) { std::string nameStr = device->getName(); i=0; len = nameStr.length(); while(i < len && i < sizeof(pdDevice->name)-1) { pdDevice->name[i] = nameStr.at(i); ++i; } pdDevice->timestamp = esp_timer_get_time() / 1000; { std::lock_guard lock(mtx); _devices[addr] = pdDevice; } } else if (device->haveManufacturerData()) { std::string strManufacturerData = device->getManufacturerData(); uint8_t cManufacturerData[100]; strManufacturerData.copy((char *)cManufacturerData, std::min(strManufacturerData.length(), sizeof(cManufacturerData)), 0); if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) { BLEBeacon oBeacon = BLEBeacon(); oBeacon.setData(strManufacturerData); // if(ENDIAN_CHANGE_U16(oBeacon.getMinor()) == 40004) // { pdDevice->timestamp = esp_timer_get_time() / 1000; strcpy(pdDevice->name, oBeacon.getProximityUUID().toString().c_str()); { std::lock_guard lock(mtx); _devices[addr] = pdDevice; } // } } } else { std::string nameStr = "-"; i=0; len = nameStr.length(); while(i < len && i < sizeof(pdDevice->name)-1) { pdDevice->name[i] = nameStr.at(i); ++i; } pdDevice->timestamp = esp_timer_get_time() / 1000; { std::lock_guard lock(mtx); _devices[addr] = pdDevice; } } } // if(device->haveName()) // { // Log->print(" | "); // Log->print(device->getName().c_str()); // if(device->haveRSSI()) // { // Log->print(" | "); // Log->print(device->getRSSI()); // } // } // Log->println(); } bool PresenceDetection::enabled() { return _timeout > 0; }