diff --git a/docs/source/ble_advertising.py b/docs/source/ble_advertising.py new file mode 100644 index 0000000..2fe17d6 --- /dev/null +++ b/docs/source/ble_advertising.py @@ -0,0 +1,102 @@ +# Helpers for generating BLE advertising payloads. + +# A more fully-featured (and easier to use) version of this is implemented in +# aioble. This code is provided just as a basic example. See +# https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble + +from micropython import const +import struct +import bluetooth + +# Advertising payloads are repeated packets of the following form: +# 1 byte data length (N + 1) +# 1 byte type (see constants below) +# N bytes type-specific data + +_ADV_TYPE_FLAGS = const(0x01) +_ADV_TYPE_NAME = const(0x09) +_ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_UUID32_COMPLETE = const(0x5) +_ADV_TYPE_UUID128_COMPLETE = const(0x7) +_ADV_TYPE_UUID16_MORE = const(0x2) +_ADV_TYPE_UUID32_MORE = const(0x4) +_ADV_TYPE_UUID128_MORE = const(0x6) +_ADV_TYPE_APPEARANCE = const(0x19) + +_ADV_MAX_PAYLOAD = const(31) + + +# Generate a payload to be passed to gap_advertise(adv_data=...). +def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): + payload = bytearray() + + def _append(adv_type, value): + nonlocal payload + payload += struct.pack("BB", len(value) + 1, adv_type) + value + + _append( + _ADV_TYPE_FLAGS, + struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)), + ) + + if name: + _append(_ADV_TYPE_NAME, name) + + if services: + for uuid in services: + b = bytes(uuid) + if len(b) == 2: + _append(_ADV_TYPE_UUID16_COMPLETE, b) + elif len(b) == 4: + _append(_ADV_TYPE_UUID32_COMPLETE, b) + elif len(b) == 16: + _append(_ADV_TYPE_UUID128_COMPLETE, b) + + # See org.bluetooth.characteristic.gap.appearance.xml + if appearance: + _append(_ADV_TYPE_APPEARANCE, struct.pack(" _ADV_MAX_PAYLOAD: + raise ValueError("advertising payload too large") + + return payload + + +def decode_field(payload, adv_type): + i = 0 + result = [] + while i + 1 < len(payload): + if payload[i + 1] == adv_type: + result.append(payload[i + 2 : i + payload[i] + 1]) + i += 1 + payload[i] + return result + + +def decode_name(payload): + n = decode_field(payload, _ADV_TYPE_NAME) + return str(n[0], "utf-8") if n else "" + + +def decode_services(payload): + services = [] + for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE): + services.append(bluetooth.UUID(struct.unpack("`_ from Arduino will walk you through the process of "bootloading" the Nano RP2040 so that you can run MicroPython code on it. After you have done this once, you should not need to do it again. -To use the NanoNav supplementary code, either download :download:`nanonav.py ` to your project directory - -Or copy the code below into a file called nanonav.py - -.. raw:: html - -
- -.. literalinclude:: /../../nanonav.py - :language: python - :linenos: - -.. raw:: html - -
- +To use the NanoNav supplementary code, download :download:`nanonav.py ` and :download:`ble_advertising.py ` to your project directory. This is highly recommended! .. _Workflow: