2023-12-07 23:51:43 +03:00
|
|
|
#include "esp32_presense.h"
|
|
|
|
|
|
|
|
namespace esphome
|
|
|
|
{
|
2023-12-10 09:08:23 +03:00
|
|
|
namespace esp32_presense
|
2023-12-07 23:51:43 +03:00
|
|
|
{
|
|
|
|
unsigned int totalSeen = 0;
|
|
|
|
unsigned int totalFpSeen = 0;
|
|
|
|
unsigned int totalFpQueried = 0;
|
|
|
|
unsigned int totalFpReported = 0;
|
2023-12-10 10:29:34 +03:00
|
|
|
|
|
|
|
TimerHandle_t reconnectTimer;
|
|
|
|
TaskHandle_t scanTaskHandle;
|
2023-12-07 23:51:43 +03:00
|
|
|
|
2023-12-10 10:29:34 +03:00
|
|
|
unsigned long updateStartedMillis = 0;
|
|
|
|
unsigned long lastTeleMillis = 0;
|
|
|
|
int reconnectTries = 0;
|
|
|
|
int teleFails = 0;
|
|
|
|
int reportFailed = 0;
|
|
|
|
bool online = false; // Have we successfully sent status=online
|
|
|
|
bool sentDiscovery = false; // Have we successfully sent discovery
|
|
|
|
UBaseType_t bleStack = 0;
|
2023-12-07 23:51:43 +03:00
|
|
|
|
2023-12-10 12:57:27 +03:00
|
|
|
DynamicJsonDocument doc(1024);
|
|
|
|
std::string _id, roomsTopic;
|
|
|
|
|
2023-12-10 10:29:34 +03:00
|
|
|
bool discovery, publishTele, publishRooms, publishDevices;
|
|
|
|
|
|
|
|
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
|
|
|
|
void onResult(BLEAdvertisedDevice *advertisedDevice) {
|
|
|
|
bleStack = uxTaskGetStackHighWaterMark(nullptr);
|
|
|
|
BleFingerprintCollection::Seen(advertisedDevice);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void scanTask(void *parameter) {
|
|
|
|
NimBLEDevice::init("ESPresense");
|
|
|
|
// Enrollment::Setup();
|
|
|
|
NimBLEDevice::setMTU(23);
|
|
|
|
|
|
|
|
auto pBLEScan = NimBLEDevice::getScan();
|
|
|
|
pBLEScan->setInterval(BLE_SCAN_INTERVAL);
|
|
|
|
pBLEScan->setWindow(BLE_SCAN_WINDOW);
|
|
|
|
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), true);
|
|
|
|
pBLEScan->setActiveScan(false);
|
|
|
|
pBLEScan->setDuplicateFilter(false);
|
|
|
|
pBLEScan->setMaxResults(0);
|
|
|
|
if (!pBLEScan->start(0, nullptr, false))
|
|
|
|
ESP_LOGE(TAG, "Error starting continuous ble scan");
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
for (auto &f : BleFingerprintCollection::fingerprints)
|
|
|
|
if (f->query())
|
|
|
|
totalFpQueried++;
|
|
|
|
|
|
|
|
// Enrollment::Loop();
|
|
|
|
|
|
|
|
if (!pBLEScan->isScanning()) {
|
|
|
|
if (!pBLEScan->start(0, nullptr, true))
|
|
|
|
ESP_LOGE(TAG, "Error re-starting continuous ble scan");
|
|
|
|
delay(3000); // If we stopped scanning, don't query for 3 seconds in order for us to catch any missed broadcasts
|
|
|
|
} else {
|
|
|
|
delay(100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-10 12:57:27 +03:00
|
|
|
void ESP32Presense::set_room(std::string room) {
|
|
|
|
_id = slugify(room);
|
|
|
|
roomsTopic = std::string(CHANNEL) + std::string("/rooms/") + _id;
|
|
|
|
}
|
2023-12-10 13:07:05 +03:00
|
|
|
|
|
|
|
void ESP32Presense::set_max_distance(float maxDistance) {
|
|
|
|
BleFingerprintCollection::maxDistance = maxDistance;
|
|
|
|
}
|
2023-12-10 12:57:27 +03:00
|
|
|
|
2023-12-10 10:29:34 +03:00
|
|
|
void ESP32Presense::setup()
|
|
|
|
{
|
|
|
|
BleFingerprintCollection::Setup();
|
|
|
|
xTaskCreatePinnedToCore(scanTask, "scanTask", SCAN_TASK_STACK_SIZE, nullptr, 1, &scanTaskHandle, CONFIG_BT_NIMBLE_PINNED_TO_CORE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ESP32Presense::loop()
|
|
|
|
{
|
|
|
|
reportLoop();
|
2023-12-10 12:57:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ESP32Presense::reportBuffer(BleFingerprint *f) {
|
|
|
|
auto report = f->getReport();
|
|
|
|
std::string topic = Sprintf(CHANNEL "/devices/%s/%s/%s", f->getId().c_str(), _id.c_str(), report.getId().c_str());
|
|
|
|
return this->publish(topic, report.getPayload());
|
2023-12-10 10:29:34 +03:00
|
|
|
}
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
void ESP32Presense::reportLoop()
|
|
|
|
{
|
|
|
|
auto copy = BleFingerprintCollection::GetCopy();
|
|
|
|
unsigned int count = 0;
|
2023-12-10 10:29:34 +03:00
|
|
|
|
2023-12-07 23:51:43 +03:00
|
|
|
for (auto &i : copy)
|
|
|
|
if (i->shouldCount())
|
|
|
|
count++;
|
2023-12-10 10:29:34 +03:00
|
|
|
|
|
|
|
yield();
|
2023-12-07 23:51:43 +03:00
|
|
|
sendTelemetry(totalSeen, totalFpSeen, totalFpQueried, totalFpReported, count);
|
2023-12-10 10:29:34 +03:00
|
|
|
yield();
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
auto reported = 0;
|
|
|
|
for (auto &f : copy) {
|
|
|
|
auto seen = f->getSeenCount();
|
|
|
|
if (seen) {
|
|
|
|
totalSeen += seen;
|
|
|
|
totalFpSeen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->hasReport()) {
|
|
|
|
if (reportBuffer(f))
|
|
|
|
f->clearReport();
|
|
|
|
}
|
|
|
|
|
2023-12-10 12:57:27 +03:00
|
|
|
|
|
|
|
if (this->reportDevice(f)) {
|
2023-12-07 23:51:43 +03:00
|
|
|
totalFpReported++;
|
|
|
|
reported++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-10 12:57:27 +03:00
|
|
|
bool ESP32Presense::reportDevice(BleFingerprint *f) {
|
|
|
|
doc.clear();
|
|
|
|
JsonObject obj = doc.to<JsonObject>();
|
|
|
|
if (!f->report(&obj))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::string buffer;
|
|
|
|
serializeJson(doc, buffer);
|
|
|
|
std::string devicesTopic = Sprintf(CHANNEL "/devices/%s/%s", f->getId().c_str(), _id.c_str());
|
|
|
|
|
|
|
|
bool p1 = false, p2 = false;
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
if (!p1 && (!publishRooms || this->publish(roomsTopic.c_str(), buffer.c_str())))
|
|
|
|
p1 = true;
|
|
|
|
|
|
|
|
if (!p2 && (!publishDevices || this->publish(devicesTopic.c_str(), buffer.c_str())))
|
|
|
|
p2 = true;
|
|
|
|
|
|
|
|
if (p1 && p2)
|
|
|
|
return true;
|
|
|
|
delay(20);
|
|
|
|
}
|
|
|
|
|
|
|
|
reportFailed++;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-07 23:51:43 +03:00
|
|
|
bool ESP32Presense::sendTelemetry(
|
|
|
|
unsigned int totalSeen,
|
|
|
|
unsigned int totalFpSeen,
|
|
|
|
unsigned int totalFpQueried,
|
|
|
|
unsigned int totalFpReported,
|
|
|
|
unsigned int count
|
|
|
|
) {
|
2023-12-10 12:57:27 +03:00
|
|
|
this->publish(roomsTopic + "/status", "online");
|
|
|
|
this->publish(roomsTopic + "/max_distance", BleFingerprintCollection::maxDistance);
|
|
|
|
this->publish(roomsTopic + "/absorption", BleFingerprintCollection::absorption);
|
|
|
|
this->publish(roomsTopic + "/tx_ref_rssi", BleFingerprintCollection::txRefRssi);
|
|
|
|
this->publish(roomsTopic + "/rx_adj_rssi", BleFingerprintCollection::rxAdjRssi);
|
|
|
|
this->publish(roomsTopic + "/query", BleFingerprintCollection::query);
|
|
|
|
this->publish(roomsTopic + "/include", BleFingerprintCollection::include);
|
|
|
|
this->publish(roomsTopic + "/exclude", BleFingerprintCollection::exclude);
|
|
|
|
this->publish(roomsTopic + "/known_macs", BleFingerprintCollection::knownMacs);
|
|
|
|
this->publish(roomsTopic + "/known_irks", BleFingerprintCollection::knownIrks);
|
|
|
|
this->publish(roomsTopic + "/count_ids", BleFingerprintCollection::countIds);
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
void ESP32NimbleMQTTRoom::on_result(nimble_distance_custom::NimbleDistanceCustomResult& result)
|
|
|
|
{
|
|
|
|
auto address = result.address.toString();
|
|
|
|
|
|
|
|
this->publish_json(
|
|
|
|
this->base_topic_ + "/devices/" + address + "/" + this->room_,
|
|
|
|
[=](ArduinoJson::JsonObject root) -> void {
|
|
|
|
root["id"] = address;
|
|
|
|
root["distance"] = result.distance;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
} // namespace esp32_nimble_tracker
|
|
|
|
} // namespace esphome
|