Tej
11/16/2024, 4:27 PMAdvertisementData is limited to 31 bytes in ble.toit. How does one get extended scan responses? I am unable to see the name or manufacturer-data of BLE beacons I am scanning. Here's a short code snippet I am using and the result.
toit
import ble
import encoding.hex
BEACON-SERVICE ::= ble.BleUuid "FEAA"
SCAN-DURATION ::= Duration --s=3
main:
adapter := ble.Adapter
central := adapter.central
while true:
addresses := Set
data := []
central.scan --duration=SCAN-DURATION: | device/ble.RemoteScannedDevice |
if device.data.service-classes.contains BEACON-SERVICE:
address := hex.encode device.address
addresses.add (address.to-ascii-upper.trim --left "00")
data.add device.data.manufacturer-data
print addresses
print data
sleep Duration/5
Result:
{BC5729059011}
[#[]]
Env:
bash
[tej@a1278 temperature_beacon]$ jag firmware
Device 'eloquent-fortune' is running Toit SDK v2.0.0-alpha.164
Running on ESP32-Wroom-32 (Olimex ESP32 Gateway)
What am I missing? I have looked through ble.toit and remote.toit and can't see any alternative scan methods nor any flags I can set.floitsch
11/16/2024, 4:29 PMTej
11/16/2024, 5:36 PMresources/ble_esp32.cc](https://github.com/toitlang/toit/blob/6a2f27006dd25601046c7c996bbc3e159b10842c/src/resources/ble_esp32.cc#L2444):
/**
* Perform a passive scan. I.e., don't send follow-up scan requests to
* each advertiser.
*/
disc_params.passive = 1;
I have been using Bluedroid - let me compile a working example in Nimble and share it tomorrow.floitsch
11/16/2024, 5:38 PMTej
11/17/2024, 8:23 AMdisc_params.passive = 0
https://github.com/tejpochiraju/nimble_beacon_scanner/blob/main/main/main.cfloitsch
11/17/2024, 9:13 AMTej
11/17/2024, 9:20 AMpassive as the default and exposing a flag instead - consumes less energy in passive. And keeps the defaults consistent with upstream Nimble configuration.
I was trying to do just that locally and build a custom envelope but am currently running into network issues while running git submodule init - will try again later.floitsch
11/17/2024, 9:24 AMTOIT_GIT_VERSION to the version Jaguar/Artemis use. Otherwise the tooling will complain that the versions don't match. (Normally that's not completely safe, but I don't remember any recent breaking changes that would make the bytecodes incompatible)Tej
11/18/2024, 6:39 PMname or advertisement data on the Toit side of things even after changing disc_params.passive = 0; in src/resources/ble_esp32.cc. I verified that the modified ble_esp32.cc is being compiled by adding a few ESP_LOGE statements. Specifically, I changed the BleCentralManagerResource::_on_discovery function to print the raw event data (see attached file and output below). To be clear, disc_params.passive = 0; is working but the extra data is not being used.
I can see that the data is received in this function but is not being passed further? Also, not sure how to handle the raw advertisement data on the Toit side of things - this is not manufacturer-data but raw bytes instead.
bash
E (7363) BLE: Discovery Event:
E (7363) BLE: Address: 11:90:05:29:57:bc
E (7363) BLE: RSSI: -61
E (7363) BLE: Event Type: 0
E (7363) BLE: Data Length: 29
E (7363) BLE: Advertisement Data:
02 01 06 03 03 aa fe 15 16 aa fe 21 04 0f 0b d4
18 f8 43 0c 00 d6 ff f0 03 c4 01 1a 2e
E (7373) BLE: Discovery Event:
E (7383) BLE: Address: 11:90:05:29:57:bc
E (7383) BLE: RSSI: -62
E (7383) BLE: Event Type: 4
E (7393) BLE: Data Length: 24
E (7393) BLE: Advertisement Data:
09 16 80 20 66 09 00 00 00 00 0d 09 42 4c 45 30
30 30 30 30 30 30 31 31
Steps:
TOIT_GIT_VERSION=v2.0.0-alpha.164 make esp32
# beacon.toit is the example code from the first post
toit compile --snapshot -o beacon.snapshot beacon.toit
toit tool firmware -e build/esp32/firmware.envelope container install beacon beacon.snapshot
toit tool firmware -e build/esp32/firmware.envelope flash --port /dev/ttyUSB0 --baud 921600
jag monitor
https://cdn.discordapp.com/attachments/1307381608537657415/1308139646815047790/ble_esp32.cc?ex=673cdb7b&is=673b89fb&hm=11a66ee06e29d2795dd0d4339417a08043ed11b68c47ad8a7feeb245ce073221&floitsch
11/18/2024, 7:17 PMfloitsch
11/19/2024, 9:44 AMDiscoveredPeripheral object and then put into a queue.
- the scan_next function (2480) then takes the next entry and passes it on to the Toit code.
- there is a ble_hs_adv_parse_fields (ble_esp32.cc:2502) that decomposes the received data into what is usually expected from advertisement packets.
If I understand you correctly, we shouldn't call ble_hs_adv_parse_fields for active-scan responses but pass the data directly to the Toit code. If that's the case I just need to store the event-type in the DiscoveredPerihperal object and then simply avoid the parsing-call.Tej
11/19/2024, 9:56 AMfloitsch
11/19/2024, 9:58 AMfloitsch
11/19/2024, 11:55 AM09 16 80 20 66 09 00 00 00 00 which seems to be a service data - 16-bit UUID. It seems like the 16-bit UUID is 0x2080 and the data is 66 09 00 00 00 00.
After that, the 0d 09 42 4c 45 30 30 30 30 30 30 30 31 31 decodes as name BLE000000011.
It looks like we don't copy these fields to the Toit side yet.
If the macos-side allows it I will probably just move the decoding of the frame into Toit code. That would give access to the raw data, and also make it easier to implement the missing fields.floitsch
11/19/2024, 1:22 PMTej
11/19/2024, 5:56 PMfloitsch
11/19/2024, 5:58 PMfloitsch
11/19/2024, 5:58 PMTej
11/19/2024, 5:58 PMfloitsch
11/19/2024, 6:00 PMfloitsch
11/19/2024, 6:00 PMfloitsch
11/19/2024, 6:01 PMTej
11/19/2024, 6:02 PMfloitsch
11/19/2024, 6:03 PMTej
11/19/2024, 6:03 PMfloitsch
11/19/2024, 6:03 PMfloitsch
11/19/2024, 6:04 PMTej
11/19/2024, 6:08 PMTej
11/20/2024, 3:23 PMfloitsch
11/20/2024, 3:25 PMTej
11/23/2024, 5:28 AMfloitsch
11/23/2024, 6:05 AMTej
11/23/2024, 7:10 AMfloitsch
11/24/2024, 6:31 PMfloitsch
11/24/2024, 6:31 PMTej
11/25/2024, 1:05 AMkasperl
11/26/2024, 1:36 PMkasperl
11/29/2024, 6:07 AMTej
11/30/2024, 2:13 PMTej
12/01/2024, 4:59 PMimport ble
import encoding.hex
BEACON-SERVICE ::= ble.BleUuid "FEAA"
SCAN-DURATION ::= Duration --s=-1
main:
adapter := ble.Adapter
central := adapter.central
while true:
addresses := Set
data := []
central.scan --duration=SCAN-DURATION
--active=true
--limited-only=false
--interval=160
--window=158:
| device/ble.RemoteScannedDevice |
if device.data.services.contains BEACON-SERVICE:
address := hex.encode device.address-bytes.stringify
print device.identifier
print device.address-bytes
print device.address-type
print device.data
sleep Duration/5
Output:
an instance with class-id 55
#[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
#[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
0
## Notes
1. --limited-only=true does not give a result at all - whereas this parameter did not seem to have any effect in my Nimble example.
2. Changing interval and window did not yield data either.
Tomorrow I will build from source and print logs from the C layer to dig deeper.floitsch
12/01/2024, 5:00 PMTej
12/02/2024, 4:56 PM// From C
E (6538) BLE: Discovery Event:
E (6538) BLE: Address: 11:90:05:29:57:bc
E (6538) BLE: RSSI: -89
E (6538) BLE: Event Type: 0
E (6538) BLE: Data Length: 29
E (6538) BLE: Advertisement Data:
02 01 06 03 03 aa fe 15 16 aa fe 21 04 0f 0b d4
17 29 45 b6 ff e1 ff d2 03 f2 01 29 db
E (6548) BLE: Discovery Event:
E (6558) BLE: Address: 11:90:05:29:57:bc
E (6558) BLE: RSSI: -86
E (6558) BLE: Event Type: 4
E (6568) BLE: Data Length: 24
E (6568) BLE: Advertisement Data:
09 16 80 20 66 09 00 00 00 00 0d 09 42 4c 45 30
30 30 30 30 30 30 31 31
// From Toit
ID: #[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address bytes: #[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address type: 0
Name: null
Data: #[0x02, 0x01, 0x06, 0x03, 0x03, 0xaa, 0xfe, 0x15, 0x16, 0xaa, 0xfe, 0x21, 0x04, 0x0f, 0x0b, 0xd4, 0x17, 0x29, 0x45, 0xb6, 0xff, 0xe1, 0xff, 0xd2, 0x03, 0xf2, 0x01, 0x29, 0xdb]
The ESP_LOGE statements are the same as my ble_esp32.cc attachment from earlier. The Toit code is:
print "ID: " + device.identifier.stringify
print "Address bytes: " + device.address-bytes.stringify
print "Address type: " + device.address-type.stringify
print "Name: " + device.data.name.stringify
print "Data: " + device.data.to-raw.stringify
Given the name comes from the second scan event (type 4), is it possible that the response from this event is not being copied over?floitsch
12/02/2024, 4:57 PMfloitsch
12/03/2024, 9:15 AMRemoteScannedDevice objects in Toit. It would be up to you to merge them.floitsch
12/03/2024, 9:16 AMis-scan-response to distinguish between the two: https://libs.toit.io/ble/remote/class-RemoteScannedDevice#is-scan-responsekasperl
12/03/2024, 10:03 AMprint "ID: $device.identifier" instead of the manual stringification and concatenation with + 🙂Tej
12/03/2024, 5:20 PMRemoteScannedDevice entries. i.e. a List? Or will the block get called on each response, i.e. once for the Discovery event and once for the Scan Response?
If it's the latter, I should have seen the data in my prints at least once but I didn't. I will refactor the code to do the merge and try again.floitsch
12/03/2024, 5:20 PMfloitsch
12/03/2024, 5:24 PMscanned-device1 := ...
scanned-device2 := ...
merged-blocks := scanned-device1.data.data-blocks + scanned-device2.data.data-blocks
merged-advertisement := Advertisement merged-blocks --no-check-size
print merged-advertisement.name
...floitsch
12/03/2024, 5:25 PMTej
12/03/2024, 6:04 PMduration) but only for Discovery.
ID: #[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address bytes: #[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address type: 0
Name: null
Data: #[0x02, 0x01, 0x06, 0x03, 0x03, 0xaa, 0xfe, 0x11, 0x16, 0xaa, 0xfe, 0x20, 0x00, 0x0b, 0xd2, 0x17, 0x33, 0x00, 0x4b, 0xe8, 0x01, 0x
01, 0xf8, 0x3e, 0x16]
Is Scan Response: false
ID: #[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address bytes: #[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address type: 0
Name: null
Data: #[0x02, 0x01, 0x06, 0x03, 0x03, 0xaa, 0xfe, 0x15, 0x16, 0xaa, 0xfe, 0x21, 0x04, 0x0f, 0x0b, 0xd2, 0x17, 0x33, 0x47, 0xf3, 0xff, 0x
e1, 0xff, 0xd2, 0x03, 0xf2, 0x01, 0x2b, 0x06]
Is Scan Response: false
// Repeats...
I simplified the code to do a single scan:
import ble
import encoding.hex
BEACON-SERVICE ::= ble.BleUuid "FEAA"
SCAN-DURATION ::= Duration --s=1
main:
adapter := ble.Adapter
central := adapter.central
central.scan --duration=SCAN-DURATION
--active=true
--limited-only=true
--interval=160
--window=158:
| device/ble.RemoteScannedDevice |
if device.data.services.contains BEACON-SERVICE:
address := hex.encode device.address-bytes.stringify
print "ID: $device.identifier"
print "Address bytes: $device.address-bytes"
print "Address type: $device.address-type"
print "Name: $device.data.name"
print "Data: $device.data.to-raw"
print "Is Scan Response: $device.is-scan-response"
Can you point me to where you pass the data to Toit from ble_esp32.cc - I can try and debug further from there.floitsch
12/03/2024, 6:12 PMscan_next function here:
https://github.com/toitlang/toit/blob/9bc1f09a2da28139d598162f17182479a9351e0c/src/resources/ble_esp32.cc#L2485
I think the reason it doesn't work for you is that the scan-response doesn't have the service (BEACON-SERVICE) anymore. If you look at the raw data, you can see that the first advertisement data contains the service (aa fe), but the scan response doesn't.
So you would need to collect the identifier (discovered-device.identifier) and then allow also scanned-device objects that don't have the BEACON-SERVICE but where you know that they have that service.
Something like:
found-devices := {}
central.scan ...
if device.data.contains-service BEACON-SERVICE or found-devices.contains device.identifier:
found-devices.add device.identifier
...Tej
12/05/2024, 4:06 AMBEACON-SERVICE being missing from the scan response.
ID: #[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address bytes: #[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address type: 0
Name: null
Data: #[0x02, 0x01, 0x06, 0x03, 0x03, 0xaa, 0xfe, 0x11, 0x16, 0xaa, 0xfe, 0x20, 0x00, 0x0b, 0xd2, 0x18, 0x02, 0x00, 0x4f, 0xa9, 0x65, 0x02, 0x0b, 0x0f, 0xd7]
Is Scan Response: false
ID: #[0x00, 0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address bytes: #[0xbc, 0x57, 0x29, 0x05, 0x90, 0x11]
Address type: 0
Name: BLE000000011
Data: #[0x09, 0x16, 0x80, 0x20, 0x66, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x09, 0x42, 0x4c, 0x45, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31]
Is Scan Response: true
Happy to report this is working as needed. Thanks again for your patience and support!