Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A custom Advertisement with a constructor can fail to parse incoming BLE data correctly #86

Open
kevinjwalters opened this issue May 28, 2020 · 3 comments
Labels
bug Something isn't working

Comments

@kevinjwalters
Copy link

kevinjwalters commented May 28, 2020

This innocent looking constructor in a sub-class of Advertisement:

    def __init__(self, enc_data=None, round=0):
        super().__init__()
        if enc_data is not None:
            self.enc_data = enc_data
        if round is not None:
            self.round = round

was causing ads to be receieved on another Adafruit device use this library as

<RpsEncDataAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=03 31 ff 00 > >

Minor possibility I've misdiagnosed this and they are sent like this due to a bug but this seems unlikely.

Originally mentioned in the comments of #79 (comment)

@kevinjwalters
Copy link
Author

I'm in the middle of writing an application using BLE. Give me a week or so and I'll provide a concise example which shows this.

@evaherrada evaherrada added the bug Something isn't working label Jun 17, 2020
@kevinjwalters
Copy link
Author

kevinjwalters commented Jul 7, 2020

I don't think extended is factor here but my example happens to feature it.

import struct

from adafruit_ble.advertising import Advertisement, LazyObjectField
from adafruit_ble.advertising.standard import ManufacturerData, ManufacturerDataField

MANUFACTURING_DATA_ADT = const(0xFF)
ADAFRUIT_COMPANY_ID = const(0x0822)

### DIRTY HACK - numbers chosen to get particular order based on current dict ordering
BIG_AD_ID = const(0xf1ac)
BIG_AD_ID_CANDIDATE = const(0xf1ad)

_DATA_FMT_SOME_NUMBER = "H"
    
class BigAdvertisement(Advertisement):
    """An Advertisement with a size that can only be transmitted as an extended Advertisement."""
    flags = None

    _PREFIX_FMT = "<B" "BHBH"
    _DATA_FMT_CANDIDATE = "200s"

    
    prefix = struct.pack(
        _PREFIX_FMT,
        struct.calcsize(_PREFIX_FMT) - 1,
        MANUFACTURING_DATA_ADT,
        ADAFRUIT_COMPANY_ID,
        struct.calcsize("<H" + _DATA_FMT_SOME_NUMBER),
        BIG_AD_ID
    )
    manufacturer_data = LazyObjectField(
        ManufacturerData,
        "manufacturer_data",
        advertising_data_type=MANUFACTURING_DATA_ADT,
        company_id=ADAFRUIT_COMPANY_ID,
        key_encoding="<H"
    )

    some_number = ManufacturerDataField(BIG_AD_ID, "<" + _DATA_FMT_SOME_NUMBER)
    candidate = ManufacturerDataField(BIG_AD_ID_CANDIDATE, "<" + _DATA_FMT_CANDIDATE)

    def __init__(self, *, some_number=0, candidate=None):
        super().__init__()
        if some_number is not None:
            self.some_number = some_number
        if candidate is not None:
            self.candidate = candidate

CLUE 1

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.3.0 on 2020-04-29; Adafruit CLUE nRF52840 Express with nRF52840
>>>
>>> from bigads import BigAdvertisement
>>> kw = BigAdvertisement()
>>> bytes(kw)
b'\x08\xff"\x08\x04\xac\xf1\x00\x00'
>>> kw.candidate = "Kanye"
>>> bytes(kw)
b'\xd3\xff"\x08\x04\xac\xf1\x00\x00\xca\xad\xf1Kanye\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> from adafruit_ble import BLERadio
>>> ble = BLERadio()
>>> ble.start_advertising(kw)

CLUE 2

Adafruit CircuitPython 5.3.0 on 2020-04-29; Adafruit CLUE nRF52840 Express with nRF52840
>>>
>>> from bigads import BigAdvertisement
>>> from adafruit_ble import BLERadio
>>> ble = BLERadio()
>>> for adv in ble.start_scan(BigAdvertisement, extended=True, timeout=2.0):
...     print(adv, adv.some_number, adv.candidate)
...
...
...
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None
<BigAdvertisement manufacturer_data=<ManufacturerData company_id=0822 data=04 ac f1 00 00 > > 0 None

@kevinjwalters
Copy link
Author

There's an unrelated issue with constructor needing to accept and forward entry kwarg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants