pycom / pycom-micropython-sigfox

A fork of MicroPython with the ESP32 port customized to run on Pycom's IoT multi-network modules.
MIT License
198 stars 167 forks source link

Advertising of manufacturer data in the Bluetooth module not working properly in FW later than 1.18.2.r3 #551

Open achtnullzwei opened 3 years ago

achtnullzwei commented 3 years ago

Dear all, there seems to be an issue when trying to advertise manufacturer specific data with the Bluetooth module. It seems setting the manufacturer_data does not work properly. On newer Firmware it is just not transmitted properly. I did some testing and below are my findings. For testing, I used the identical code posted below in both cases. To validate if the man manufacturer specific data is sent correctly i used a RPI Zero running "aioblescan". Outputs for each case are posted as well to indicate the issue. I also traced it back to the latest firmware version which works.

Firmware Version/Model: 1.20.2.r4 / WiPy 3.0 os.uname(): (sysname='WiPy', nodename='WiPy', release='1.20.2.r4', version='v1.11-ffb0e1c on 2021-01-12', machine='WiPy with ESP32', pybytes='1.6.1')

Test Code:

from struct import unpack
from network import Bluetooth
import time
bluetooth = Bluetooth()
bluetooth.start_scan(10)

send_payload = ubinascii.unhexlify(b'4c000215a495bb20c5b14b44b5121370f02d74de004c03e2c5')

bluetooth.set_advertisement(name = None, manufacturer_data = bytes(send_payload))
bluetooth.advertise(True)
time.sleep(1)
bluetooth.advertise(False)

aioblescan output:

HCI Event:
    code:
        3e
    length:
        24
    LE Meta:
        code:
            02
        Adv Report:
            num reports:
                1
            ev type:
                generic adv
            addr type:
                public
            peer:
                XX:XX:XX:XX:XX:XX
            length:
                12
            flags:
                Simul LE - BR/EDR (Host): False
                Simul LE - BR/EDR (Control.): False
                BR/EDR Not Supported: False
                LE General Disc.: True
                LE Limited Disc.: True
            Payload for tx_power_level:
                03
            Payload for slave_conn_intvl_range:
                20:00:40:00
            rssi:
                -80

The aioblescan output shows, no manufacturer data is part of the package. Instead, "slave_conn_intvl_range" is recieved.

Firmware Version/Model: 1.18.2.r3 / WiPy 3.0 os.uname(): (sysname='WiPy', nodename='WiPy', release='1.18.2.r3', version='v1.8.6-849-a1641ca on 2019-02-28', machine='WiPy with ESP32', pybytes='0.9.10')

Test Code:

from struct import unpack
from network import Bluetooth
import time
bluetooth = Bluetooth()
bluetooth.start_scan(10)

send_payload = ubinascii.unhexlify(b'4c000215a495bb20c5b14b44b5121370f02d74de004c03e2c5')

bluetooth.set_advertisement(name = None, manufacturer_data = bytes(send_payload))
bluetooth.advertise(True)
time.sleep(1)
bluetooth.advertise(False)

aioblescan output:

HCI Event:
    code:
        3e
    length:
        42
    LE Meta:
        code:
            02
        Adv Report:
            num reports:
                1
            ev type:
                generic adv
            addr type:
                public
            peer:
                XX:XX:XX:XX:XX:XX
            length:
                30
            flags:
                Simul LE - BR/EDR (Host): False
                Simul LE - BR/EDR (Control.): False
                BR/EDR Not Supported: False
                LE General Disc.: True
                LE Limited Disc.: True
            Payload for mfg_specific_data:
                4c:00:02:15:a4:95:bb:20:c5:b1:4b:44:b5:12:13:70:f0:2d:74:de:00:4c:03:e2:c5
            rssi:
                -77

With firmware 1.18.2.r3 the manufacturer data is transmitted properly as expected. I am not sure what causes this, but this firmware is the latest that works with the above code. It is also the latest that works with another example code posted in a BLE iBeacon question in the pycom Forum. Furthermore, I did a test with the example code from this post by papasmurph (https://forum.pycom.io/topic/1911/wipy-as-an-ibeacon/8?_=1621242732074). It also works with 1.18.2.r3 but none of the later versions.

At the moment I am sticking with this firmware as manufacturer data sent properly is essential for my project. However, it would be great if this can be fixed in a future release.

In case this is expected behaviour, I would kindly ask for an example how to accomplish this in the current firmware. I could not find any further/newer documentation on how to send manufacturer data properly.

Thank you very much!

msariisik commented 3 years ago

Dear achtnullzwei,

I tried what you said in this post. I tested on the firmware versions which are 1.18.2.r3 and 1.20.0.rc13. I haven't seen any problem on the output.

When I looked at your output, it looks like parsing the advertisement data according to advertisement type. The type value of Manufacturer specific data is 0xFF. The client side parses the values from fields inside manufacturer data by using this type value.

Can you check with one of pycom boards? You can use this script to parse fields in the manufacturer data (https://forum.pycom.io/topic/6902/accessing-minor-major-from-ibeacon-scan/4?_=1621253254009).

Can you check also with one of the ble mobile app? When I use nrf connect, it shows that the manufacturer data correctly. The results are same for both of the firmware versions in my experiments.

If I am missing a point, please let me know.

Best regards, Meric

achtnullzwei commented 3 years ago

Hi Meric,

thx a lot for looking into this. I will look into it in the evening. Maybe this is a Problem with the Version of aioblescan I use.

Maybe some explanation around this: I am looking into repeating a BLE iBeacon advertisement from a floating hydrometer. The scenario is, that in some cases, the hydrometer's signal is too weak to protrude a stainless steel enclosure, hence i wanted to repeat it with my WiPy. Maybe the iBeacon packets this device advertises are out of specifications, for some reason.

I will setup an RPI with the newest version of aioblescan and also try to use nrf mobile to check.

If the issue is aioblescan, then I am sorry for the inconvenience. I will let you know my findings. :-)

Best, Matthias