WIP: Channel info
This commit is contained in:
parent
d523ac961e
commit
571e677a63
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(©);
|
||||
if (f->seen(©) && onAdd)
|
||||
if (f->seen(©, 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ChannelInfo {
|
||||
|
||||
uint8_t popChannelInfo(int8_t expectedRssi);
|
||||
|
||||
}
|
12
src/GUI.cpp
12
src/GUI.cpp
|
@ -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) {
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue