ubluepy --- Bluetooth LE peripheral และ central#

โมดูล ubluepy คือ API Bluetooth LE รุ่นเก่าที่จัดส่งมากับ MicroPython nRF port โดยมีแบบจำลองคร่าวๆ จากไลบรารี Python bluepy ของ Linux และทำงานโดยตรงบน Nordic SoftDevice --- ไม่มี back-end แบบพกพา ดังนั้นโมดูลนี้จึงใช้ได้เฉพาะบน Nordic targets (Arduino Nano 33 BLE Sense ในกลุ่มผลิตภัณฑ์ของ OpenMV) API bluetooth / aioble รุ่นใหม่กว่า ไม่ได้ เปิดใช้งานในบิลด์นี้ ดังนั้น ubluepy จึงเป็นวิธีเดียวในการขับเคลื่อนวิทยุในชิป

ชุดคุณสมบัติที่ใช้งานได้ขึ้นอยู่กับ SoftDevice ที่แฟลชโดย firmware:

  • s140 (Nano 33 BLE Sense) --- ทั้งบทบาท peripheral และ central (scanner) นี่คือสิ่งที่ OpenMV firmware จัดส่ง

  • s132 --- ทั้ง peripheral และ central

  • s110 --- เฉพาะ peripheral เท่านั้น โดย scanner / connect method ถูกคอมไพล์ออก

ตัวอย่าง Peripheral#

โฆษณาในฐานะ Bluetooth LE peripheral พร้อมบริการ environmental sensing เดียวและแจ้งเตือน temperature characteristic ในทุกการเขียนไปยัง Client Characteristic Configuration Descriptor (CCCD):

from ubluepy import Service, Characteristic, UUID, Peripheral, constants
from machine import LED

notif_enabled = False

def event_handler(event_id, handle, data):
    global notif_enabled
    if event_id == constants.EVT_GAP_CONNECTED:
        LED("LED_GREEN").on()
    elif event_id == constants.EVT_GAP_DISCONNECTED:
        LED("LED_GREEN").off()
        periph.advertise(device_name="Nano 33", services=[svc])
    elif event_id == constants.EVT_GATTS_WRITE:
        notif_enabled = bool(data[0])

svc = Service(UUID("181A"))            # Environmental Sensing
char = Characteristic(UUID("2A6E"),
                      props=Characteristic.PROP_NOTIFY | Characteristic.PROP_READ,
                      attrs=Characteristic.ATTR_CCCD)
svc.addCharacteristic(char)

periph = Peripheral()
periph.addService(svc)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33", services=[svc])

ตัวอย่าง Central#

สแกนหาอุปกรณ์โฆษณาที่อยู่ใกล้เคียงเป็นเวลา 100 ms และถอดรหัสข้อมูลโฆษณาของ ScanEntry แต่ละรายการ:

from ubluepy import Scanner, constants

s = Scanner()
for entry in s.scan(100):
    print(entry.addr(), entry.rssi(), "dBm")
    for ad_type, name, value in entry.getScanData():
        print(" ", ad_type, name, bytes(value))

เนื้อหาของโมดูล#

คลาส#

class ubluepy.UUID(value)#

สร้าง Bluetooth UUID ขนาด 16 บิตหรือ 128 บิต

value

หนึ่งในรายการต่อไปนี้:

  • int --- UUID ตัวเลข 16 บิต (UUID(0x180A))

  • สตริง "0xXXXX" 6 ตัวอักษร --- UUID 16 บิต เช่น UUID("0x181A")

  • สตริง "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 36 ตัวอักษร --- UUID 128 บิตแบบเต็ม โดยส่วนที่เฉพาะเจาะจงของ vendor จะถูกลงทะเบียนกับ SoftDevice เมื่อสร้าง

  • อินสแตนซ์ UUID อื่น --- ทำการคัดลอก

ความยาวอื่นๆ จะ raise ValueError("Invalid UUID string length")

binVal() int#

คืนค่า 16 บิตต่ำของ UUID เป็น int สำหรับ UUID 128 บิต จะคืนค่าเฉพาะฟิลด์ 16 บิตที่ฝังอยู่ภายใน vendor-specific UUID (ค่า 128 บิตแบบเต็มสามารถเข้าถึงได้เฉพาะผ่าน vendor-specific index ของ SoftDevice)

class ubluepy.Service(uuid: UUID, type: int = Service.PRIMARY)#

กำหนดบริการ GATT ที่จะลงทะเบียนกับ SoftDevice เมื่อเพิ่มไปยัง Peripheral

uuid

อินสแตนซ์ UUID การส่งออบเจ็กต์ที่ไม่ใช่ UUID จะ raise ValueError

type

เป็น Service.PRIMARY (ค่าเริ่มต้น) หรือ Service.SECONDARY ค่าอื่นๆ จะ raise ValueError

uuid() UUID#

คืนค่าอินสแตนซ์ UUID ของบริการ

addCharacteristic(characteristic: Characteristic) None#

ลงทะเบียน Characteristic กับบริการ โดย GATT handle ของ characteristic จะถูกกำหนดระหว่างการเรียกนี้

getCharacteristic(uuid: UUID) Characteristic | None#

ค้นหา Characteristic ที่เพิ่มไว้ก่อนหน้านี้ด้วย UUID คืนค่าอินสแตนซ์ characteristic หรือ None หากไม่พบรายการที่ตรงกัน

getCharacteristics() list#

คืนค่ารายการ characteristic ทั้งหมดที่เพิ่มไปยังบริการ

PRIMARY: int#

ค่าคงที่ประเภทบริการสำหรับ primary service (1)

SECONDARY: int#

ค่าคงที่ประเภทบริการสำหรับ secondary service (2)

class ubluepy.Characteristic(uuid: UUID, *, props: int = PROP_READ | PROP_WRITE, attrs: int = 0)#

กำหนด GATT characteristic โดยเพิ่มไปยัง Service ด้วย Service.addCharacteristic() ก่อนที่ Peripheral พาเรนต์จะเริ่มโฆษณา

uuid

อินสแตนซ์ UUID

props (keyword-only)

Bitmask ของค่า Characteristic.PROP_* หนึ่งรายการหรือมากกว่าที่อธิบายว่า characteristic รองรับการดำเนินการใดบ้าง

attrs (keyword-only)

Bitmask ของ GATT attribute เพิ่มเติม ใช้ Characteristic.ATTR_CCCD เพื่อแนบ Client Characteristic Configuration Descriptor --- จำเป็นสำหรับการทำให้ characteristic PROP_NOTIFY / PROP_INDICATE ทำงาน

uuid() UUID#

คืนค่าอินสแตนซ์ UUID ของ characteristic

properties() int#

คืนค่า bitmask props ที่กำหนดไว้เมื่อสร้าง

read() bytearray#

เฉพาะบทบาท Central เท่านั้น อ่านค่าของ characteristic จาก peer ที่เชื่อมต่อ คืนค่า bytearray พร้อมค่าล่าสุด บน peripheral นี้เป็น no-op และคืนค่า None

write(data, *, with_response: bool = False) None#

เขียนค่าไปยัง characteristic

  • บน peripheral หาก PROP_NOTIFY ถูกตั้งค่าใน properties ของ characteristic ค่าจะถูกส่งเป็น GATT notification ไปยัง central ที่เชื่อมต่อ มิฉะนั้นค่า attribute ในเครื่องจะถูกอัปเดต

  • บน central ค่าจะถูกเขียนไปยัง peer ระยะไกล ตั้งค่า with_response=True เพื่อออก write request และรอการยืนยันจาก peer แทนที่จะเป็น write command

data คือออบเจ็กต์ buffer-protocol ใดๆ (bytes, bytearray, memoryview)

PROP_BROADCAST: int#

Characteristic สามารถกระจายค่าของตน (0x01)

PROP_READ: int#

Characteristic รองรับการอ่าน (0x02)

PROP_WRITE_WO_RESP: int#

Characteristic รองรับการเขียนโดยไม่มีการตอบสนอง (0x04)

PROP_WRITE: int#

Characteristic รองรับการเขียนพร้อมการตอบสนอง (0x08)

PROP_NOTIFY: int#

Characteristic สามารถส่ง notification ไปยัง central ที่สมัครรับข้อมูล (0x10)

PROP_INDICATE: int#

Characteristic สามารถส่ง indication (notification ที่ยืนยัน) ไปยัง central ที่สมัครรับข้อมูล (0x20)

PROP_AUTH_SIGNED_WR: int#

Characteristic รองรับ authenticated signed write (0x40)

ATTR_CCCD: int#

เพิ่ม Client Characteristic Configuration Descriptor ไปยัง characteristic (0x01) จำเป็นสำหรับ client ในการสมัครรับ notification/indication

class ubluepy.Descriptor(uuid: UUID)#

คลาส stub สำหรับแสดง GATT descriptor การนำไปใช้งานปัจจุบันเก็บเฉพาะ UUID และไม่เปิดเผย method ใดๆ --- มีไว้เพื่อความเข้ากันได้ในอนาคตกับการแก้ไขโมดูลในอนาคต

class ubluepy.Peripheral#

อุปกรณ์ Bluetooth LE ในเครื่อง คลาสเดียวกันนี้ใช้สำหรับทั้งบทบาท peripheral และ central โดยบทบาทจะถูกเลือกตามวิธีการที่คุณเรียก (advertise() เลือก peripheral, connect() เลือก central)

addService(service: Service) None#

ลงทะเบียน Service (และ characteristic ที่เพิ่มไว้ก่อนหน้าทั้งหมด) กับ GATT server ในเครื่อง

getServices() list#

คืนค่ารายการบริการที่ลงทะเบียนกับ Peripheral นี้ในปัจจุบัน

advertise(*, device_name: str | None = None, services: list | None = None, data: bytes | None = None, connectable: bool = True) None#

เริ่มโฆษณาในบทบาท peripheral

device_name

ชื่อในเครื่องแบบสมบูรณ์ที่โฆษณาใน GAP payload

services

รายการของอินสแตนซ์ Service ที่จะโฆษณา UUID ของแต่ละบริการจะถูกรวมในโฆษณา

data

raw advertisement payload ที่ไม่บังคับ (bytes / bytearray) ที่ต่อท้าย header ที่สร้างอัตโนมัติ ใช้สำหรับ payload เฉพาะ vendor หรือ beacon เช่น Eddystone

connectable

เมื่อเป็น True (ค่าเริ่มต้น) โฆษณาเป็นอุปกรณ์ที่เชื่อมต่อได้และลงทะเบียน GAP / GATTS event handler เพื่อให้ callback setConnectionHandler() ที่กำหนดค่าไว้ทำงานเมื่อเชื่อมต่อ ตัดการเชื่อมต่อ และ CCCD write เมื่อเป็น False โฆษณาเป็น beacon --- ไม่มี handler แนบอยู่และอุปกรณ์ไม่สามารถเชื่อมต่อได้

advertise_stop() None#

หยุดการโฆษณาที่กำลังดำเนินอยู่

setConnectionHandler(func) None#

ลงทะเบียน callback ที่ถูกเรียกใช้กับ GAP และ GATTS event โดย callback จะถูกเรียกในรูปแบบ func(event_id, conn_handle, data) โดย event_id เป็นหนึ่งในค่า constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED หรือ constants.EVT_GATTS_WRITE, conn_handle คือ SoftDevice connection handle (หรือ attribute handle สำหรับ GATTS write) และ data คือ raw event payload เป็น bytearray (หรือ None สำหรับ connect / disconnect)

setNotificationHandler(func) None#

ลงทะเบียน callback สำหรับ notification event ที่ได้รับในบทบาท central

withDelegate(delegate: DefaultDelegate) None#

แนบอินสแตนซ์ DefaultDelegate เพื่อรับ GATT event ที่ถอดรหัสแล้ว

disconnect() None#

ยกเลิกการเชื่อมต่อที่ใช้งานอยู่ (ปัจจุบันเป็น no-op stub ในบิลด์นี้)

connect(addr, *, addr_type: int = constants.ADDR_TYPE_PUBLIC) None#

เฉพาะบทบาท Central เท่านั้น เชื่อมต่อกับ peer ที่มีที่อยู่ที่กำหนดและค้นพบ primary service และ characteristic ของมันแบบ synchronous บล็อกจนกว่าการเชื่อมต่อจะสร้างขึ้นและการค้นพบเสร็จสมบูรณ์ โดยบริการที่ค้นพบจะใช้ได้ผ่าน getServices()

addr

ที่อยู่ peer เป็นสตริง "xx:xx:xx:xx:xx:xx" 17 ตัวอักษร (เช่น ที่นำมาจาก ScanEntry.addr())

addr_type (keyword-only)

เป็น constants.ADDR_TYPE_PUBLIC (ค่าเริ่มต้น) หรือ constants.ADDR_TYPE_RANDOM_STATIC

class ubluepy.Scanner#

GAP observer สำหรับค้นพบอุปกรณ์โฆษณาที่อยู่ใกล้เคียง ใช้ได้เฉพาะเมื่อ firmware สร้างกับ SoftDevice ที่มีการรองรับ central (s132 / s140)

scan(timeout: int) list#

รันการสแกนแบบ passive เป็นเวลา timeout มิลลิวินาทีและคืนค่ารายการของอินสแตนซ์ ScanEntry --- หนึ่งรายการต่อรายงานโฆษณาที่ได้รับระหว่างช่วงเวลานั้น

class ubluepy.ScanEntry#

รายงานโฆษณาเดียวที่จับได้โดย Scanner.scan() โดยอินสแตนซ์จะถูกส่งคืนจาก scanner --- ไม่มี constructor สาธารณะ

addr() str#

คืนค่าที่อยู่ peer เป็นสตริง "xx:xx:xx:xx:xx:xx" 17 ตัวอักษร

addr_type() int#

คืนค่าประเภทที่อยู่ peer (constants.ADDR_TYPE_PUBLIC หรือ constants.ADDR_TYPE_RANDOM_STATIC)

rssi() int#

คืนค่าตัวบ่งชี้ความแรงสัญญาณเป็น dBm

getScanData() list#

ถอดรหัส advertisement payload เป็นรายการของ tuple (ad_type, description, value) โดย ad_type คือ byte ประเภท AD แบบตัวเลข (ดู constants.ad_types), description คือชื่อของค่าคงที่ที่ตรงกันเป็นสตริง (หรือ None หากประเภทไม่รู้จัก) และ value คือ AD record body เป็น bytearray

class ubluepy.DefaultDelegate#

คลาสพื้นฐานสำหรับออบเจ็กต์ที่ส่งไปยัง Peripheral.withDelegate() โดย subclass และ override handleConnection() / handleNotification() เพื่อตอบสนองต่อ GATT event

handleConnection() None#

ถูกเรียกเมื่อเกิด GAP connect / disconnect event การนำไปใช้งานเริ่มต้นเป็นค่าว่าง

handleNotification() None#

ถูกเรียกเมื่อได้รับ GATT notification ขาเข้า การนำไปใช้งานเริ่มต้นเป็นค่าว่าง

ค่าคงที่#

attribute constants ของโมดูลเป็น namespace ที่ประกอบด้วยตัวระบุ GAP/GATT event, ค่าประเภทที่อยู่ และ namespace ย่อย ad_types

ubluepy.constants: type#

คอนเทนเนอร์ที่เปิดเผยค่าคงที่ด้านล่าง

constants.EVT_GAP_CONNECTED: int#

Peripheral connection handler event_id สำหรับ GAP connect (16)

constants.EVT_GAP_DISCONNECTED: int#

Peripheral connection handler event_id สำหรับ GAP disconnect (17)

constants.EVT_GATTS_WRITE: int#

Peripheral connection handler event_id สำหรับการเขียนไปยัง GATT attribute ในเครื่อง รวมถึงการเขียนไปยัง CCCD ที่เปิด/ปิด notification (80)

constants.UUID_CCCD: int#

Bluetooth UUID มาตรฐานสำหรับ Client Characteristic Configuration Descriptor (0x2902)

constants.ADDR_TYPE_PUBLIC: int#

Public Bluetooth Device Address (0)

constants.ADDR_TYPE_RANDOM_STATIC: int#

Static random Bluetooth Device Address (1)

constants.ad_types: type#

Namespace ของค่าคงที่ประเภท AD ของข้อมูลการโฆษณาจาก Bluetooth Core Specification Supplement โดยแต่ละชื่อแมปกับประเภท AD 1 byte ที่สอดคล้องกัน:

ชื่อ

ค่า

AD_TYPE_FLAGS

0x01

AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE

0x02

AD_TYPE_16BIT_SERVICE_UUID_COMPLETE

0x03

AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE

0x04

AD_TYPE_32BIT_SERVICE_UUID_COMPLETE

0x05

AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE

0x06

AD_TYPE_128BIT_SERVICE_UUID_COMPLETE

0x07

AD_TYPE_SHORT_LOCAL_NAME

0x08

AD_TYPE_COMPLETE_LOCAL_NAME

0x09

AD_TYPE_TX_POWER_LEVEL

0x0A

AD_TYPE_CLASS_OF_DEVICE

0x0D

AD_TYPE_SIMPLE_PAIRING_HASH_C

0x0E

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R

0x0F

AD_TYPE_SECURITY_MANAGER_TK_VALUE

0x10

AD_TYPE_SECURITY_MANAGER_OOB_FLAGS

0x11

AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE

0x12

AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT

0x14

AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT

0x15

AD_TYPE_SERVICE_DATA

0x16

AD_TYPE_PUBLIC_TARGET_ADDRESS

0x17

AD_TYPE_RANDOM_TARGET_ADDRESS

0x18

AD_TYPE_APPEARANCE

0x19

AD_TYPE_ADVERTISING_INTERVAL

0x1A

AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS

0x1B

AD_TYPE_LE_ROLE

0x1C

AD_TYPE_SIMPLE_PAIRING_HASH_C256

0x1D

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256

0x1E

AD_TYPE_SERVICE_DATA_32BIT_UUID

0x20

AD_TYPE_SERVICE_DATA_128BIT_UUID

0x21

AD_TYPE_URI

0x24

AD_TYPE_3D_INFORMATION_DATA

0x3D

AD_TYPE_MANUFACTURER_SPECIFIC_DATA

0xFF