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
+6 -2
View File
@@ -121,10 +121,14 @@ int main() {
run(state, "assert(not ble.isInitialized())\n"
"assert(ble.init())\n"
"assert(ble.isInitialized())\n"
"assert(ble.scan()[1].address == 'aa:bb')\n"
"assert(ble.observe({ services = { '181A' } }))\n"
"assert(ble.isObserving())\n"
"assert(ble.observed()[1].address == 'aa:bb')\n"
"assert(ble.observed()[1].payload == 'payload')\n"
"assert(#ble.read('svc', 'chr') == 3)\n"
"assert(ble.write('svc', 'chr', 'x\\0y'))");
assert(bench.ble.duration == 3000);
assert(bench.ble.filter.services.size() == 1);
assert(bench.ble.filter.services[0] == "181A");
assert(bench.ble.value.size() == 3);
run(state, "fired = 0\n"