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")
- class ubluepy.Service(uuid: UUID, type: int = Service.PRIMARY)¶
กำหนดบริการ GATT ที่จะลงทะเบียนกับ SoftDevice เมื่อเพิ่มไปยัง
Peripheraluuidอินสแตนซ์
UUIDการส่งออบเจ็กต์ที่ไม่ใช่ UUID จะ raiseValueErrortypeเป็น
Service.PRIMARY(ค่าเริ่มต้น) หรือService.SECONDARYค่าอื่นๆ จะ raiseValueError
- addCharacteristic(characteristic: Characteristic) None¶
ลงทะเบียน
Characteristicกับบริการ โดย GATT handle ของ characteristic จะถูกกำหนดระหว่างการเรียกนี้
- getCharacteristic(uuid: UUID) Characteristic | None¶
ค้นหา
Characteristicที่เพิ่มไว้ก่อนหน้านี้ด้วย UUID คืนค่าอินสแตนซ์ characteristic หรือNoneหากไม่พบรายการที่ตรงกัน
- class ubluepy.Characteristic(uuid: UUID, *, props: int = PROP_READ | PROP_WRITE, attrs: int = 0)¶
กำหนด GATT characteristic โดยเพิ่มไปยัง
Serviceด้วยService.addCharacteristic()ก่อนที่Peripheralพาเรนต์จะเริ่มโฆษณาuuidอินสแตนซ์
UUIDprops(keyword-only)Bitmask ของค่า
Characteristic.PROP_*หนึ่งรายการหรือมากกว่าที่อธิบายว่า characteristic รองรับการดำเนินการใดบ้างattrs(keyword-only)Bitmask ของ GATT attribute เพิ่มเติม ใช้
Characteristic.ATTR_CCCDเพื่อแนบ Client Characteristic Configuration Descriptor --- จำเป็นสำหรับการทำให้ characteristicPROP_NOTIFY/PROP_INDICATEทำงาน
- 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)
- 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 ของแต่ละบริการจะถูกรวมในโฆษณาdataraw advertisement payload ที่ไม่บังคับ (
bytes/bytearray) ที่ต่อท้าย header ที่สร้างอัตโนมัติ ใช้สำหรับ payload เฉพาะ vendor หรือ beacon เช่น Eddystoneconnectableเมื่อเป็น
True(ค่าเริ่มต้น) โฆษณาเป็นอุปกรณ์ที่เชื่อมต่อได้และลงทะเบียน GAP / GATTS event handler เพื่อให้ callbacksetConnectionHandler()ที่กำหนดค่าไว้ทำงานเมื่อเชื่อมต่อ ตัดการเชื่อมต่อ และ CCCD write เมื่อเป็นFalseโฆษณาเป็น beacon --- ไม่มี handler แนบอยู่และอุปกรณ์ไม่สามารถเชื่อมต่อได้
- 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 ที่ถอดรหัสแล้ว
- 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)
- class ubluepy.ScanEntry¶
รายงานโฆษณาเดียวที่จับได้โดย
Scanner.scan()โดยอินสแตนซ์จะถูกส่งคืนจาก scanner --- ไม่มี constructor สาธารณะ- addr_type() int¶
คืนค่าประเภทที่อยู่ peer (
constants.ADDR_TYPE_PUBLICหรือconstants.ADDR_TYPE_RANDOM_STATIC)
- 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 และ overridehandleConnection()/handleNotification()เพื่อตอบสนองต่อ GATT event
ค่าคงที่¶
attribute constants ของโมดูลเป็น namespace ที่ประกอบด้วยตัวระบุ GAP/GATT event, ค่าประเภทที่อยู่ และ namespace ย่อย ad_types
- constants.EVT_GAP_DISCONNECTED: int¶
Peripheralconnection handlerevent_idสำหรับ GAP disconnect (17)
- constants.EVT_GATTS_WRITE: int¶
Peripheralconnection handlerevent_idสำหรับการเขียนไปยัง GATT attribute ในเครื่อง รวมถึงการเขียนไปยัง CCCD ที่เปิด/ปิด notification (80)
- constants.UUID_CCCD: int¶
Bluetooth UUID มาตรฐานสำหรับ Client Characteristic Configuration Descriptor (
0x2902)
- constants.ad_types: type¶
Namespace ของค่าคงที่ประเภท AD ของข้อมูลการโฆษณาจาก Bluetooth Core Specification Supplement โดยแต่ละชื่อแมปกับประเภท AD 1 byte ที่สอดคล้องกัน:
ชื่อ
ค่า
AD_TYPE_FLAGS0x01AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE0x02AD_TYPE_16BIT_SERVICE_UUID_COMPLETE0x03AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE0x04AD_TYPE_32BIT_SERVICE_UUID_COMPLETE0x05AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE0x06AD_TYPE_128BIT_SERVICE_UUID_COMPLETE0x07AD_TYPE_SHORT_LOCAL_NAME0x08AD_TYPE_COMPLETE_LOCAL_NAME0x09AD_TYPE_TX_POWER_LEVEL0x0AAD_TYPE_CLASS_OF_DEVICE0x0DAD_TYPE_SIMPLE_PAIRING_HASH_C0x0EAD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R0x0FAD_TYPE_SECURITY_MANAGER_TK_VALUE0x10AD_TYPE_SECURITY_MANAGER_OOB_FLAGS0x11AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE0x12AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT0x14AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT0x15AD_TYPE_SERVICE_DATA0x16AD_TYPE_PUBLIC_TARGET_ADDRESS0x17AD_TYPE_RANDOM_TARGET_ADDRESS0x18AD_TYPE_APPEARANCE0x19AD_TYPE_ADVERTISING_INTERVAL0x1AAD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS0x1BAD_TYPE_LE_ROLE0x1CAD_TYPE_SIMPLE_PAIRING_HASH_C2560x1DAD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R2560x1EAD_TYPE_SERVICE_DATA_32BIT_UUID0x20AD_TYPE_SERVICE_DATA_128BIT_UUID0x21AD_TYPE_URI0x24AD_TYPE_3D_INFORMATION_DATA0x3DAD_TYPE_MANUFACTURER_SPECIFIC_DATA0xFF