feat(ble): replace blocking scan with advertisement observation

The one-shot scan kept only the top six devices by RSSI and dropped the
advertisement payload, so a distant beacon lost its slot to nearby phones
and its data was unreachable -- wrong on every axis for reading sensors
that broadcast in their adverts.

Replace it with a continuous observer: observe(filter)/observed()/
unobserve()/isObserving(). BleObservation carries the raw advertisement
bytes for Lua to parse, and BleFilter keeps only adverts matching a
service-data UUID or manufacturer id.
This commit is contained in:
2026-08-06 23:03:05 -04:00
parent eac4084f80
commit a09bcfaf06
5 changed files with 135 additions and 31 deletions
+20 -3
View File
@@ -246,10 +246,24 @@ public:
virtual Status forget() = 0;
};
struct BleDevice {
std::string name;
// One sighting of an advertising device, coalesced to its latest advert. The
// payload is the raw advertisement bytes; parsing the AD structures (and any
// beacon format inside them) is the caller's job, so a new sensor format never
// touches this seam.
struct BleObservation {
std::string address;
std::string name;
int32_t rssi;
std::string payload;
int32_t lastSeenMs;
};
// Kept adverts must carry one of these service-data UUIDs or one of these
// manufacturer ids; an empty filter keeps everything. Applied before an advert
// is buffered, so unwanted devices never occupy a slot.
struct BleFilter {
std::vector<std::string> services;
std::vector<int32_t> manufacturers;
};
class BleProvider {
@@ -258,7 +272,10 @@ public:
virtual Status init(const std::string* name) = 0;
virtual void deinit() = 0;
virtual bool isInitialized() const = 0;
virtual Status scan(int32_t durationMs, std::vector<BleDevice>& devices) = 0;
virtual Status observe(const BleFilter& filter) = 0;
virtual void unobserve() = 0;
virtual bool isObserving() const = 0;
virtual void observed(std::vector<BleObservation>& out) = 0;
virtual Status connect(const std::string& address) = 0;
virtual void disconnect() = 0;
virtual bool isConnected() const = 0;