AltBeacon / android-beacon-library

Allows Android apps to interact with BLE beacons
Apache License 2.0
2.84k stars 836 forks source link

Getting ScanResponse #854

Open sepehr78 opened 5 years ago

sepehr78 commented 5 years ago

Expected behavior

I was wondering if there is a way to get the ScanResponse when a beacon is detected.

Actual behavior

Unless I remove all beaconLayouts, I cannot get the ScanResponse. Even when I do remove all layouts, I can only access the raw byte array in setNonBeaconLeScanCallback().

Steps to reproduce this behavior

Use range notifiers or monitor notifiers to get beacons.

Mobile device model and OS version

Pixel 2, Android 9.0.

Android Beacon Library version

2.16.1

IMPORTANT: This forum is reserved for feature requests or reproducible bugs with the library itself. If you need help with using the library with your project, please open a new question on StackOverflow.com.

davidgyoung commented 5 years ago

Following on to the discussion here...

One way to add this feature might be to add support for parsing The PDU or AD type for the scan response. This could be added to the library here: https://github.com/AltBeacon/android-beacon-library/blob/master/lib/src/main/java/org/altbeacon/beacon/BeaconParser.java#L429

Note that that code iterates over all the PDUs in the scan data, but ignores all AD types except GATT_SERVICE_UUID_PDU_TYPE (for Eddystone beacon types) and MANUFACTURER_DATA_PDU_TYPE (for iBeacon/AltBeacon). The idea would be to augment this code for it to also parse the scan response PDU.

If we were to do that, you could define a beacon layout similar to EDDYSTONE_TLM. If you look at its definition, you will see this is a special type of layout that has no identifiers but instead has extra telemetry fields (like what you want to do with the scan response).

So if you can make a PR 5o add code to parse the scan response PDU, I think we could then write a beacon parser to get Kontakt.io telemetry data out of those bytes. Then the state would be available to you in beacon.getExtraDataFields() as soon as the beacon frame and the scan response have both been received.

sybarra-avtc commented 4 years ago

Hello, I'm curious as to whether there are any updates to the status of this enhancement? I'm currently in the process of trying to access telemetry data from a kontakt.io asset tag beacon using the Alt-Beacon library - specifically accelerometer data regarding time since the tag's last movement and battery life data. The asset tag beacons will be broadcasting both an iBeacon advertisement as well as kontakt.io's custom telemetry packet, which contains the accelerometer and battery data (among other sensor data).

If I'm understanding everything correctly on a high level, the library would need a AD type defined (similar to MANUFACTURER_DATA_PDU_TYPE = 0xff, GATT_SERVICE_UUID_PDU_TYPE = 0x16) to allow it to parse a scan response PDU, and from there a custom kontakt telemetry layout string could be written comparable to the EDDYSTONE_TLM layout string. Once the new telemetry layout string is added as an extra parser, the telemetry data could then be accessed by calling the beacon.getExtraDataFields() inside the range notifier.

My first question above all is how would I find the hex value to set for a SCAN_RESPONSE_PDU_TYPE that, once added in the conditional that checks for Pdu type inside the BeaconParser.fromScanData function, would allow the system to parse the scan response that contains the kontakt telemetry data?

Thanks ahead for the help and I hope you're all healthy and well during these troubling times!

davidgyoung commented 4 years ago

@sybarra-avtc, no work on this. If you are interested in trying to implement I would welcome a PR.

Your description of the steps is accurate. Two clarifications:

  1. There is no PDU type for a scan response. It can have any PDU inside of it much like a regular advertisement. So a regular beacon parser will do fine. You can see a link to the Kontakt telemetry format in the scan response below.

  2. The Android BLE stack simply tacks the scan response onto the end of a regular advertisement bytes from a conventional scan callback. Presumably it does this by matching up the MAC addresses. If you set beacon Manager.serDebug(true) you will see all kinds of hex bytes in LogCat for matched packets. Do this and find the hex bytes for a known Kontakt beacon and you should be able to identify the scan response bytes tacked onto the end.

On you do the above, it is simply a matter of making the BeaconParser find and process these bytes tacked on the end and then breaking them into PDUs just like the regular advert.

You will see that Kontakt scan response uses 09 (local name) 0A (tx power) and 16 (service data). You could probably make an extra beacon layout for each of these if you wish, but you would need to add support for parsing 09 and 0A which is not currently in the library.

https://support.kontakt.io/hc/en-gb/articles/201492522-Scan-response-packet-structure