WIP: Channel info

This commit is contained in:
Gunnar Beutner 2023-12-06 11:17:09 +01:00
parent d523ac961e
commit 571e677a63
12 changed files with 223 additions and 60 deletions

View File

@ -16,22 +16,19 @@ class ClientCallbacks : public BLEClientCallbacks {
static ClientCallbacks clientCB;
BleFingerprint::BleFingerprint(BLEAdvertisedDevice *advertisedDevice, float fcmin, float beta, float dcutoff) : filteredDistance{FilteredDistance(fcmin, beta, dcutoff)} {
BleFingerprint::BleFingerprint(BLEAdvertisedDevice *advertisedDevice) {
firstSeenMillis = millis();
address = NimBLEAddress(advertisedDevice->getAddress());
addressType = advertisedDevice->getAddressType();
rssi = advertisedDevice->getRSSI();
raw = dist = pow(10, float(get1mRssi() - rssi) / (10.0f * BleFingerprintCollection::absorption));
for (auto& channel : channels)
channel.observe(firstSeenMillis, get1mRssi(), advertisedDevice->getRSSI());
seenCount = 1;
queryReport = nullptr;
fingerprintAddress();
}
void BleFingerprint::setInitial(const BleFingerprint &other) {
rssi = other.rssi;
dist = other.dist;
raw = other.raw;
filteredDistance = other.filteredDistance;
channels = other.channels;
}
bool BleFingerprint::shouldHide(const String &s) {
@ -66,10 +63,10 @@ bool BleFingerprint::setId(const String &newId, short newIdType, const String &n
allowQuery = newQuery;
if (allowQuery) {
qryAttempts = 0;
if (rssi < -80) {
if (getMaxObservedRssi() < -80) {
qryDelayMillis = 30000;
lastQryMillis = millis();
} else if (rssi < -70) {
} else if (getMaxObservedRssi() < -70) {
qryDelayMillis = 5000;
lastQryMillis = millis();
}
@ -408,8 +405,16 @@ void BleFingerprint::fingerprintManufactureData(NimBLEAdvertisedDevice *advertis
}
}
bool BleFingerprint::seen(BLEAdvertisedDevice *advertisedDevice) {
lastSeenMillis = millis();
void BleChannelObservation::observe(unsigned long timestamp, int rssi1m, int rssi) {
this->rssi = rssi;
raw = pow(10, float(rssi1m - rssi) / (10.0f * BleFingerprintCollection::absorption));
filter.addMeasurement(raw);
dist = filter.getDistance();
vari = filter.getVariance();
lastSeenMillis = timestamp;
}
bool BleFingerprint::seen(BLEAdvertisedDevice *advertisedDevice, uint8_t channel) {
reported = false;
seenCount++;
@ -418,11 +423,8 @@ bool BleFingerprint::seen(BLEAdvertisedDevice *advertisedDevice) {
if (ignore || hidden) return false;
rssi = advertisedDevice->getRSSI();
raw = pow(10, float(get1mRssi() - rssi) / (10.0f * BleFingerprintCollection::absorption));
filteredDistance.addMeasurement(raw);
dist = filteredDistance.getDistance();
vari = filteredDistance.getVariance();
lastChannel = channel;
channels[ble_channel_to_index(channel)].observe(millis(), get1mRssi(), advertisedDevice->getRSSI());
if (!added) {
added = true;
@ -439,11 +441,46 @@ bool BleFingerprint::fill(JsonObject *doc) {
if (idType) (*doc)[F("idType")] = idType;
(*doc)[F("rssi@1m")] = get1mRssi();
(*doc)[F("rssi")] = rssi;
(*doc)[F("rssi")] = getMaxObservedRssi();
switch (lastChannel) {
case 37:
(*doc)[F("rssi37")] = channels[0].rssi;
(*doc)[F("raw37")] = serialized(String(channels[0].raw, 2));
(*doc)[F("distance37")] = serialized(String(channels[0].dist, 2));
(*doc)[F("var37")] = serialized(String(channels[0].vari, 2));
break;
case 38:
(*doc)[F("rssi38")] = channels[1].rssi;
(*doc)[F("raw38")] = serialized(String(channels[1].raw, 2));
(*doc)[F("distance38")] = serialized(String(channels[1].dist, 2));
(*doc)[F("var38")] = serialized(String(channels[1].vari, 2));
break;
case 39:
(*doc)[F("rssi39")] = channels[2].rssi;
(*doc)[F("raw39")] = serialized(String(channels[2].raw, 2));
(*doc)[F("distance39")] = serialized(String(channels[2].dist, 2));
(*doc)[F("var39")] = serialized(String(channels[2].vari, 2));
break;
}
(*doc)[F("channel")] = lastChannel;
if (isnormal(raw)) (*doc)[F("raw")] = serialized(String(raw, 2));
if (isnormal(dist)) (*doc)[F("distance")] = serialized(String(dist, 2));
if (isnormal(vari)) (*doc)[F("var")] = serialized(String(vari, 2));
float weightedDistances = 0;
float sumWeights = 0;
float sumVariances = 0;
// FIXME: weight channels by timestamp of last packet, so we can ignore stale values
for (const auto& channel : channels) {
float weight = 1 / std::max(channel.vari, 0.05f);
weightedDistances += channel.dist * weight;
sumWeights += weight;
sumVariances += channel.vari;
}
float fusedDistance = weightedDistances / sumWeights;
float fusedVariance = sumVariances / 3;
(*doc)[F("distance")] = serialized(String(fusedDistance, 2));
(*doc)[F("var")] = serialized(String(fusedVariance, 2));
auto minRaw = std::min_element(channels.begin(), channels.end(), [](const BleChannelObservation& a, const BleChannelObservation& b) { return a.raw < b.raw; })->raw;
(*doc)[F("raw")] = serialized(String(minRaw, 2));
if (close) (*doc)[F("close")] = true;
(*doc)[F("int")] = (millis() - firstSeenMillis) / seenCount;
@ -459,17 +496,19 @@ bool BleFingerprint::report(JsonObject *doc) {
if (ignore || idType <= ID_TYPE_RAND_MAC || hidden) return false;
if (reported) return false;
auto minObservedDistance = getMinObservedDistance();
auto maxDistance = BleFingerprintCollection::maxDistance;
if (maxDistance > 0 && dist > maxDistance)
if (maxDistance > 0 && minObservedDistance > maxDistance)
return false;
auto now = millis();
if ((abs(dist - lastReported) < BleFingerprintCollection::skipDistance) && (lastReportedMillis > 0) && (now - lastReportedMillis < BleFingerprintCollection::skipMs))
if ((abs(minObservedDistance - lastReported) < BleFingerprintCollection::skipDistance) && (lastReportedMillis > 0) && (now - lastReportedMillis < BleFingerprintCollection::skipMs))
return false;
if (fill(doc)) {
lastReportedMillis = now;
lastReported = dist;
lastReported = minObservedDistance;
reported = true;
return true;
}
@ -479,10 +518,10 @@ bool BleFingerprint::report(JsonObject *doc) {
bool BleFingerprint::query() {
if (!allowQuery || isQuerying) return false;
if (rssi < -90) return false; // Too far away
if (getMaxObservedRssi() < -90) return false; // Too far away
auto now = millis();
if (now - lastSeenMillis > 5) return false; // Haven't seen lately
if (now - getLastSeenMillis() > 5000) return false; // Haven't seen lately
if (now - lastQryMillis < qryDelayMillis) return false; // Too soon
isQuerying = true;
@ -490,7 +529,7 @@ bool BleFingerprint::query() {
bool success = false;
Serial.printf("%u Query | %s | %-58s%ddBm %lums\r\n", xPortGetCoreID(), getMac().c_str(), id.c_str(), rssi, now - lastSeenMillis);
Serial.printf("%u Query | %s | %-58s%ddBm %lums\r\n", xPortGetCoreID(), getMac().c_str(), id.c_str(), getMaxObservedRssi(), now - getLastSeenMillis());
NimBLEClient *pClient = NimBLEDevice::getClientListSize() ? NimBLEDevice::getClientByPeerAddress(address) : nullptr;
if (!pClient) pClient = NimBLEDevice::getDisconnectedClient();
@ -516,29 +555,31 @@ bool BleFingerprint::query() {
} else {
qryAttempts++;
qryDelayMillis = min(int(pow(10, qryAttempts)), 60000);
Serial.printf("%u QryErr | %s | %-58s%ddBm Try %d, retry after %dms\r\n", xPortGetCoreID(), getMac().c_str(), id.c_str(), rssi, qryAttempts, qryDelayMillis);
Serial.printf("%u QryErr | %s | %-58s%ddBm Try %d, retry after %dms\r\n", xPortGetCoreID(), getMac().c_str(), id.c_str(), getMaxObservedRssi(), qryAttempts, qryDelayMillis);
}
isQuerying = false;
return true;
}
bool BleFingerprint::shouldCount() {
if (!close && rssi > CLOSE_RSSI + BleFingerprintCollection::rxAdjRssi) {
if (!close && getMaxObservedRssi() > CLOSE_RSSI + BleFingerprintCollection::rxAdjRssi) {
BleFingerprintCollection::Close(this, true);
close = true;
} else if (close && rssi < LEFT_RSSI + BleFingerprintCollection::rxAdjRssi) {
} else if (close && getMaxObservedRssi() < LEFT_RSSI + BleFingerprintCollection::rxAdjRssi) {
BleFingerprintCollection::Close(this, false);
close = false;
}
auto minObservedDistance = getMinObservedDistance();
bool prevCounting = counting;
if (ignore || !countable)
counting = false;
else if (getMsSinceLastSeen() > BleFingerprintCollection::countMs)
counting = false;
else if (counting && dist > BleFingerprintCollection::countExit)
else if (counting && minObservedDistance > BleFingerprintCollection::countExit)
counting = false;
else if (!counting && dist <= BleFingerprintCollection::countEnter)
else if (!counting && minObservedDistance <= BleFingerprintCollection::countEnter)
counting = true;
if (prevCounting != counting) {
@ -549,5 +590,6 @@ bool BleFingerprint::shouldCount() {
}
void BleFingerprint::expire() {
lastSeenMillis = 0;
for (auto& channel : channels)
channel.lastSeenMillis = 0;
}

View File

@ -60,11 +60,42 @@
#define ID_TYPE_KNOWN_MAC short(210)
#define ID_TYPE_ALIAS short(250)
static inline uint8_t ble_channel_to_index(int8_t channel) {
auto index = channel - 37;
if (index < 0 || index > 2)
return 0;
return index;
}
enum class BleChannel {
Channel37 = 0,
Channel38 = 1,
Channel39 = 2,
Any
};
#define ONE_EURO_FCMIN 1e-1f
#define ONE_EURO_BETA 1e-3f
#define ONE_EURO_DCUTOFF 5e-3f
struct BleChannelObservation {
int rssi { NO_RSSI };
float raw { 0 };
float dist { 0 };
float vari { 0 };
unsigned long lastSeenMillis { 0 };
void observe(unsigned long timestamp, int rssi1m, int rssi);
private:
FilteredDistance filter { ONE_EURO_FCMIN, ONE_EURO_BETA, ONE_EURO_DCUTOFF };
};
class BleFingerprint {
public:
BleFingerprint(NimBLEAdvertisedDevice *advertisedDevice, float fcmin, float beta, float dcutoff);
BleFingerprint(NimBLEAdvertisedDevice *advertisedDevice);
bool seen(BLEAdvertisedDevice *advertisedDevice);
bool seen(BLEAdvertisedDevice *advertisedDevice, uint8_t channel);
bool fill(JsonObject *doc);
@ -86,17 +117,24 @@ class BleFingerprint {
const short getIdType() const { return idType; }
const float getDistance() const { return dist; }
const float getMinObservedDistance() const {
return std::min_element(channels.begin(), channels.end(), [](const BleChannelObservation& a, const BleChannelObservation& b) { return a.dist < b.dist; })->dist;
}
const int getRssi() const { return rssi; }
const int getRawRssi() const { return rssi; }
const int getMaxObservedRssi() const {
return std::max_element(channels.begin(), channels.end(), [](const BleChannelObservation& a, const BleChannelObservation& b) { return a.rssi < b.rssi; })->rssi;
}
const int get1mRssi() const;
void set1mRssi(int8_t rssi) { calRssi = rssi; }
const NimBLEAddress getAddress() const { return address; }
const unsigned long getMsSinceLastSeen() const { return lastSeenMillis ? millis() - lastSeenMillis : 4294967295; };
unsigned long getLastSeenMillis() const {
return std::max_element(channels.begin(), channels.end(), [](const BleChannelObservation& a, const BleChannelObservation& b) { return a.lastSeenMillis < b.lastSeenMillis; })->lastSeenMillis;
}
const unsigned long getMsSinceLastSeen() const { return millis() - getLastSeenMillis(); };
const unsigned long getMsSinceFirstSeen() const { return millis() - firstSeenMillis; };
@ -129,15 +167,15 @@ class BleFingerprint {
NimBLEAddress address;
String id, name;
short int idType = NO_ID_TYPE;
int rssi = NO_RSSI;
uint8_t lastChannel;
std::array<BleChannelObservation, 3> channels;
int8_t calRssi = NO_RSSI, bcnRssi = NO_RSSI, mdRssi = NO_RSSI, asRssi = NO_RSSI;
unsigned int qryAttempts = 0, qryDelayMillis = 0;
float raw = 0, dist = 0, vari = 0, lastReported = 0, temp = 0, humidity = 0;
unsigned long firstSeenMillis, lastSeenMillis = 0, lastReportedMillis = 0, lastQryMillis = 0;
float lastReported = 0, temp = 0, humidity = 0;
unsigned long firstSeenMillis, lastReportedMillis = 0, lastQryMillis = 0;
unsigned long seenCount = 1, lastSeenCount = 0;
uint16_t mv = 0;
uint8_t battery = 0xFF, addressType = 0xFF;
FilteredDistance filteredDistance;
std::unique_ptr<QueryReport> queryReport = nullptr;
static bool shouldHide(const String &s);

View File

@ -49,12 +49,12 @@ void Close(BleFingerprint *f, bool close) {
}
}
void Seen(BLEAdvertisedDevice *advertisedDevice) {
void Seen(BLEAdvertisedDevice *advertisedDevice, uint8_t channel) {
BLEAdvertisedDevice copy = *advertisedDevice;
if (onSeen) onSeen(true);
BleFingerprint *f = GetFingerprint(&copy);
if (f->seen(&copy) && onAdd)
if (f->seen(&copy, channel) && onAdd)
onAdd(f);
if (onSeen) onSeen(false);
}
@ -205,7 +205,7 @@ BleFingerprint *getFingerprintInternal(BLEAdvertisedDevice *advertisedDevice) {
if (it != fingerprints.rend())
return *it;
auto created = new BleFingerprint(advertisedDevice, ONE_EURO_FCMIN, ONE_EURO_BETA, ONE_EURO_DCUTOFF);
auto created = new BleFingerprint(advertisedDevice);
auto it2 = std::find_if(fingerprints.begin(), fingerprints.end(), [created](BleFingerprint *f) { return f->getId() == created->getId(); });
if (it2 != fingerprints.end()) {
auto found = *it2;

View File

@ -3,10 +3,6 @@
#include "BleFingerprint.h"
#define ONE_EURO_FCMIN 1e-1f
#define ONE_EURO_BETA 1e-3f
#define ONE_EURO_DCUTOFF 5e-3f
#ifndef ALLOW_BLE_CONTROLLER_RESTART_AFTER_SECS
#define ALLOW_BLE_CONTROLLER_RESTART_AFTER_SECS 1800
#endif
@ -30,7 +26,7 @@ bool Config(String &id, String &json);
void Close(BleFingerprint *f, bool close);
void Count(BleFingerprint *f, bool counting);
void Seen(BLEAdvertisedDevice *advertisedDevice);
void Seen(BLEAdvertisedDevice *advertisedDevice, uint8_t channel);
BleFingerprint *GetFingerprint(BLEAdvertisedDevice *advertisedDevice);
void CleanupOldFingerprints();
const std::vector<BleFingerprint *> GetCopy();

View File

@ -91,7 +91,7 @@ bool forceFloraServiceDataMode(BLERemoteService* floraService) { // Setting the
void fillDeviceData(DynamicJsonDocument* doc, BleFingerprint* f) {
(*doc)[F("id")] = f->getId();
(*doc)[F("mac")] = f->getMac();
(*doc)[F("rssi")] = f->getRssi();
(*doc)[F("rssi")] = f->getMaxObservedRssi();
}
bool getFloraData(DynamicJsonDocument* doc, BLERemoteService* floraService, BleFingerprint* f) {

View File

@ -7,14 +7,14 @@ bool requestData(NimBLEClient* pClient, BleFingerprint* f) {
std::string sName = pClient->getValue(genericAccessService, nameChar);
if (!sName.empty() && sMdl.find(sName) == std::string::npos && sName != "Apple Watch") {
if (f->setId(String("name:") + kebabify(sName).c_str(), ID_TYPE_QUERY_NAME, String(sName.c_str()))) {
Serial.printf("\u001b[38;5;104m%u Name | %s | %-58s%ddBm %s\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRssi(), sName.c_str());
Serial.printf("\u001b[38;5;104m%u Name | %s | %-58s%ddBm %s\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi(), sName.c_str());
}
return true;
}
if (!sMdl.empty()) {
if (f->setId(String("apple:") + kebabify(sMdl).c_str(), ID_TYPE_QUERY_MODEL, String(sMdl.c_str()))) {
Serial.printf("\u001b[38;5;136m%u Model | %s | %-58s%ddBm %s\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRssi(), sMdl.c_str());
Serial.printf("\u001b[38;5;136m%u Model | %s | %-58s%ddBm %s\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi(), sMdl.c_str());
}
return true;
}

View File

@ -27,6 +27,8 @@ build_flags =
-Wno-switch-unreachable
-Wno-stringop-overflow
-Wformat-truncation
-Wl,--wrap,r_lld_scan_process_pkt_rx_adv_rep
-Wl,--wrap,r_ke_msg_send
-D CONFIG_BT_NIMBLE_TASK_STACK_SIZE=5632
-D CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5632
-D SCAN_TASK_STACK_SIZE=2562

75
src/ChannelInfo.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "ChannelInfo.h"
#include <Arduino.h>
#include <atomic>
#include "esp_attr.h"
#define BLE_RXDESC_OFFSET 0x1000
extern "C" void *r_emi_get_mem_addr_by_offset(size_t offset);
extern "C" void __real_r_lld_scan_process_pkt_rx_adv_rep(int scan_index, unsigned long param_2,int rxdesc_index, void *param_4);
extern "C" void __real_r_ke_msg_send(void *msg);
struct BleRxDescriptor {
uint16_t a[3];
uint8_t rssi;
uint8_t channel;
uint16_t b[6];
};
#define BLE_CHANNEL_QUEUE_SIZE 64
static DRAM_ATTR std::atomic<uint16_t> bleChannelQueue[BLE_CHANNEL_QUEUE_SIZE];
static DRAM_ATTR uint32_t bleChannelQueueWriteIndex;
static DRAM_ATTR std::atomic<bool> bleChannelInfoTriggeredAtLeastOnce;
static DRAM_ATTR bool bleShouldSaveChannel;
static DRAM_ATTR std::atomic<unsigned long> bleDiscardedChannelInfo;
static uint32_t bleChannelQueueReadIndex;
extern "C" void IRAM_ATTR __wrap_r_ke_msg_send(void *msg) {
bleShouldSaveChannel = true;
__real_r_ke_msg_send(msg);
}
extern "C" void IRAM_ATTR __wrap_r_lld_scan_process_pkt_rx_adv_rep(int scan_index, unsigned long param_2,int rxdesc_index, void *param_4) {
bleChannelInfoTriggeredAtLeastOnce = true;
auto rxdesc = (const BleRxDescriptor*)r_emi_get_mem_addr_by_offset(BLE_RXDESC_OFFSET) + rxdesc_index;
uint16_t channelAndRssi = rxdesc->channel << 8 | rxdesc->rssi;
bleShouldSaveChannel = false;
__real_r_lld_scan_process_pkt_rx_adv_rep(scan_index, param_2, rxdesc_index, param_4);
if (!bleShouldSaveChannel) {
bleDiscardedChannelInfo++;
return;
}
bleChannelQueue[bleChannelQueueWriteIndex % BLE_CHANNEL_QUEUE_SIZE] = channelAndRssi;
bleChannelQueueWriteIndex++;
}
namespace ChannelInfo {
uint8_t popChannelInfo(int8_t expectedRssi) {
unsigned long discarded = bleDiscardedChannelInfo.exchange(0);
if (discarded)
Serial.printf("discarded %d rx pkts?\r\n", discarded);
// Ignore the queue if it hasn't been touched by the hook, e.g. due to
// unsupported hardware/firmware changes that would cause
// r_lld_scan_process_pkt_rx_adv_rep not to get called at all.
if (bleChannelInfoTriggeredAtLeastOnce) {
//Serial.printf("wr: %lu, rd: %lu\r\n", (uint32_t)bleChannelQueueWriteIndex, (uint32_t)bleChannelQueueReadIndex);
const auto initialReadIndex = bleChannelQueueReadIndex;
do {
uint16_t channelInfo = bleChannelQueue[bleChannelQueueReadIndex % BLE_CHANNEL_QUEUE_SIZE];
bleChannelQueueReadIndex++;
// The Bluetooth stack may have discarded some advertisements after
// we've captured the channel value, skip ahead until we find a
// matching RSSI value.
if ((int8_t)(channelInfo & 0xff) == expectedRssi)
return channelInfo >> 8;
} while (bleChannelQueueReadIndex % BLE_CHANNEL_QUEUE_SIZE != initialReadIndex % BLE_CHANNEL_QUEUE_SIZE);
}
// Either the hook isn't working or we probably received more than
// BLE_CHANNEL_QUEUE_SIZE packets since the last call to popChannelInfo(),
// i.e. the channel info we were looking for is gone.
return 37;
}
}

9
src/ChannelInfo.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <stdint.h>
namespace ChannelInfo {
uint8_t popChannelInfo(int8_t expectedRssi);
}

View File

@ -53,21 +53,21 @@ void Loop() {
void Added(BleFingerprint *f) {
if (f->getIgnore()) return;
Serial.printf("%u New %s | %s | %-58s%ddBm\r\n", xPortGetCoreID(), f->getAllowQuery() ? "Q" : " ", f->getMac().c_str(), f->getId().c_str(), f->getRssi());
Serial.printf("%u New %s | %s | %-58s%ddBm\r\n", xPortGetCoreID(), f->getAllowQuery() ? "Q" : " ", f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi());
}
void Removed(BleFingerprint *f) {
if (f->getIgnore() || !f->getAdded()) return;
Serial.printf("\u001b[38;5;236m%u Del | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRssi());
Serial.printf("\u001b[38;5;236m%u Del | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi());
}
void Close(BleFingerprint *f) {
Serial.printf("\u001b[32m%u Close | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRawRssi());
Serial.printf("\u001b[32m%u Close | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi());
Display::Status("C:%s\r\n", f->getId().c_str());
}
void Left(BleFingerprint *f) {
Serial.printf("\u001b[33m%u Left | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRawRssi());
Serial.printf("\u001b[33m%u Left | %s | %-58s%ddBm\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi());
Display::Status("L:%s\r\n", f->getId().c_str());
}
void Motion(bool pir, bool radar) {
@ -106,9 +106,9 @@ void Connected(bool wifi, bool mqtt) {
void Counting(BleFingerprint *f, bool add) {
if (add)
Serial.printf("\u001b[36m%u C# +1 | %s | %-58s%ddBm (%.2fm) %lums\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRssi(), f->getDistance(), f->getMsSinceLastSeen());
Serial.printf("\u001b[36m%u C# +1 | %s | %-58s%ddBm (%.2fm) %lums\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi(), f->getMinObservedDistance(), f->getMsSinceLastSeen());
else
Serial.printf("\u001b[35m%u C# -1 | %s | %-58s%ddBm (%.2fm) %lums\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getRssi(), f->getDistance(), f->getMsSinceLastSeen());
Serial.printf("\u001b[35m%u C# -1 | %s | %-58s%ddBm (%.2fm) %lums\u001b[0m\r\n", xPortGetCoreID(), f->getMac().c_str(), f->getId().c_str(), f->getMaxObservedRssi(), f->getMinObservedDistance(), f->getMsSinceLastSeen());
}
void Wifi(unsigned int percent) {

View File

@ -484,7 +484,7 @@ void reportLoop() {
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice *advertisedDevice) {
bleStack = uxTaskGetStackHighWaterMark(nullptr);
BleFingerprintCollection::Seen(advertisedDevice);
BleFingerprintCollection::Seen(advertisedDevice, ChannelInfo::popChannelInfo(advertisedDevice->getRSSI()));
}
};

View File

@ -13,6 +13,7 @@
#include "BleFingerprint.h"
#include "BleFingerprintCollection.h"
#include "CAN.h"
#include "ChannelInfo.h"
#include "Enrollment.h"
#include "GUI.h"
#include "HttpReleaseUpdate.h"