ubluepy — התקן היקפי ומרכזי של Bluetooth LE

המודול ubluepy הוא ה-API הישן של Bluetooth LE המשולח עם הסבת nRF של MicroPython. הוא מעוצב באופן רופף על פי ספריית Python bluepy של Linux ויושב ישירות מעל ה-Nordic SoftDevice — אין לו מנגנון אחורי נייד, ולכן המודול זמין רק ביעדי Nordic (ה-Arduino Nano 33 BLE Sense בשורת המוצרים של OpenMV). ממשקי ה-API החדשים יותר bluetooth / aioble אינם מופעלים בבנייה זו, ולכן ubluepy הוא הדרך היחידה להפעיל את הרדיו שעל-גבי השבב.

מערך התכונות הזמין תלוי ב-SoftDevice שנצרב על ידי הקושחה:

  • s140 (Nano 33 BLE Sense) — תפקידי התקן היקפי וגם מרכזי (סורק). זהו מה שמשולח עם קושחת OpenMV.

  • s132 — גם התקן היקפי וגם מרכזי.

  • s110 — התקן היקפי בלבד; מתודות הסורק / החיבור מהודרות החוצה.

דוגמה להתקן היקפי

פרסום כהתקן היקפי של Bluetooth LE עם שירות יחיד לחישה סביבתית, ושליחת התראה על מאפיין טמפרטורה בכל כתיבה אל ה-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])

דוגמה להתקן מרכזי

סריקה לאיתור התקנים מפרסמים בקרבת מקום למשך 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)

בניית UUID של Bluetooth בן 16 או 128 ביט.

value

אחד מהבאים:

  • int — UUID מספרי בן 16 ביט (UUID(0x180A)).

  • מחרוזת "0xXXXX" בת 6 תווים — UUID בן 16 ביט, למשל UUID("0x181A").

  • מחרוזת "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" בת 36 תווים — UUID מלא בן 128 ביט. החלק הספציפי-ליצרן נרשם ב-SoftDevice בעת הבנייה.

  • מופע UUID אחר — מבצע העתקה.

כל אורך אחר מעלה ValueError("Invalid UUID string length").

binVal() int

מחזיר את 16 הביטים הנמוכים של ה-UUID כ-int. עבור UUID בני 128 ביט מוחזר רק שדה 16 הביט המוטמע בתוך ה-UUID הספציפי-ליצרן (הערך המלא בן 128 ביט נגיש רק דרך האינדקס הספציפי-ליצרן של ה-SoftDevice).

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

הגדרת שירות GATT שיירשם ב-SoftDevice כאשר יתווסף ל-Peripheral.

uuid

מופע UUID. העברת אובייקט שאינו UUID מעלה ValueError.

type

או Service.PRIMARY (ברירת מחדל) או Service.SECONDARY. ערכים אחרים מעלים ValueError.

uuid() UUID

מחזיר את מופע ה-UUID של השירות.

addCharacteristic(characteristic: Characteristic) None

רישום Characteristic בשירות. ה-handle של GATT עבור המאפיין מוקצה במהלך קריאה זו.

getCharacteristic(uuid: UUID) Characteristic | None

חיפוש Characteristic שנוסף קודם לכן לפי UUID. מחזיר את מופע המאפיין, או None אם לא נמצאה התאמה.

getCharacteristics() list

מחזיר את רשימת כל המאפיינים שנוספו לשירות.

PRIMARY: int

קבוע סוג-שירות עבור שירותים ראשיים (1).

SECONDARY: int

קבוע סוג-שירות עבור שירותים משניים (2).

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

הגדרת מאפיין GATT. הוסיפו אותו ל-Service באמצעות Service.addCharacteristic() לפני שה-Peripheral ההורה מתחיל לפרסם.

uuid

מופע UUID.

props (מילת-מפתח בלבד)

מסכת ביטים של ערך Characteristic.PROP_* אחד או יותר המתארים אילו פעולות המאפיין תומך בהן.

attrs (מילת-מפתח בלבד)

מסכת ביטים של תכונות GATT נוספות. השתמשו ב-Characteristic.ATTR_CCCD כדי לצרף Client Characteristic Configuration Descriptor — נדרש כדי לגרום למאפייני PROP_NOTIFY / PROP_INDICATE לעבוד.

uuid() UUID

מחזיר את מופע ה-UUID של המאפיין.

properties() int

מחזיר את מסכת הביטים props שנקבעה בעת הבנייה.

read() bytearray

תפקיד מרכזי בלבד. קריאת ערך המאפיין מן העמית המחובר. מחזיר bytearray עם הערך העדכני ביותר. בהתקן היקפי זוהי פעולת no-op והיא מחזירה None.

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

כתיבה אל המאפיין.

  • בהתקן היקפי, אם PROP_NOTIFY מוגדר במאפייני ה-characteristic, הערך נשלח כהתראת GATT אל ההתקן המרכזי המחובר; אחרת ערך התכונה המקומי מתעדכן.

  • בהתקן מרכזי, הערך נכתב אל העמית המרוחק. הגדירו with_response=True כדי להנפיק בקשת כתיבה ולהמתין לאישור של העמית במקום פקודת כתיבה.

data הוא כל אובייקט התומך בפרוטוקול buffer (bytes, bytearray, memoryview).

PROP_BROADCAST: int

המאפיין יכול לשדר את ערכו (0x01).

PROP_READ: int

המאפיין תומך בקריאות (0x02).

PROP_WRITE_WO_RESP: int

המאפיין תומך בכתיבות ללא תגובה (0x04).

PROP_WRITE: int

המאפיין תומך בכתיבות עם תגובה (0x08).

PROP_NOTIFY: int

המאפיין יכול לדחוף התראות אל התקן מרכזי מנוי (0x10).

PROP_INDICATE: int

המאפיין יכול לדחוף אינדיקציות (התראות מאושרות) אל התקן מרכזי מנוי (0x20).

PROP_AUTH_SIGNED_WR: int

המאפיין תומך בכתיבות חתומות ומאומתות (0x40).

ATTR_CCCD: int

הוספת Client Characteristic Configuration Descriptor למאפיין (0x01). נדרש כדי שלקוחות יוכלו להירשם להתראות/אינדיקציות.

class ubluepy.Descriptor(uuid: UUID)

מחלקת stub לייצוג מתארי GATT. המימוש הנוכחי שומר אך ורק את ה-UUID ואינו חושף מתודות כלשהן — היא מסופקת לצורך תאימות עתידית עם גרסאות עתידיות של המודול.

class ubluepy.Peripheral

התקן ה-Bluetooth LE המקומי. אותה מחלקה משמשת הן עבור תפקיד התקן היקפי והן עבור תפקיד התקן מרכזי; התפקיד נבחר לפי המתודות שאתם קוראים להן (advertise() בוחרת התקן היקפי, connect() בוחרת התקן מרכזי).

addService(service: Service) None

רישום Service (וכל המאפיינים שנוספו לו קודם לכן) בשרת ה-GATT המקומי.

getServices() list

מחזיר את רשימת השירותים הרשומים כעת ב-Peripheral זה.

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

התחלת פרסום בתפקיד התקן היקפי.

device_name

השם המקומי המלא המפורסם במטען ה-GAP.

services

רשימת מופעי Service לפרסום. ה-UUID של כל שירות כלול בפרסום.

data

מטען פרסום גולמי אופציונלי (bytes / bytearray) המצורף לכותרת שנוצרה אוטומטית. השתמשו בזה עבור מטענים ספציפיים-ליצרן או מטעני beacon כגון Eddystone.

connectable

כאשר True (ברירת מחדל), מתבצע פרסום כהתקן בר-חיבור ונרשמים מטפלי אירועי GAP / GATTS כך שפונקציית ה-callback המוגדרת setConnectionHandler() מופעלת בעת חיבור, ניתוק וכתיבות CCCD. כאשר False, מתבצע פרסום כ-beacon — לא מצורפים מטפלים ולא ניתן להתחבר להתקן.

advertise_stop() None

עצירת כל פרסום שמתבצע.

setConnectionHandler(func) None

רישום פונקציית callback המופעלת באירועי GAP ו-GATTS. ה-callback נקרא כ-func(event_id, conn_handle, data) כאשר event_id הוא אחד מהערכים constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED, או constants.EVT_GATTS_WRITE, conn_handle הוא ה-handle של החיבור של ה-SoftDevice (או handle של תכונה עבור כתיבות GATTS), ו-data הוא מטען האירוע הגולמי כ-bytearray (או None עבור חיבור / ניתוק).

setNotificationHandler(func) None

רישום פונקציית callback עבור אירועי התראה המתקבלים בתפקיד התקן מרכזי.

withDelegate(delegate: DefaultDelegate) None

צירוף מופע DefaultDelegate לקבלת אירועי GATT מפוענחים.

disconnect() None

ניתוק החיבור הפעיל (כרגע stub של no-op בבנייה זו).

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

תפקיד מרכזי בלבד. התחברות אל העמית בעל הכתובת הנתונה וגילוי סינכרוני של השירותים והמאפיינים הראשיים שלו. חוסם עד שהחיבור נוצר והגילוי מסתיים; השירותים שהתגלו זמינים לאחר מכן דרך getServices().

addr

כתובת העמית כמחרוזת "xx:xx:xx:xx:xx:xx" בת 17 תווים (למשל זו שנלקחה מ-ScanEntry.addr()).

addr_type (מילת-מפתח בלבד)

או constants.ADDR_TYPE_PUBLIC (ברירת מחדל) או constants.ADDR_TYPE_RANDOM_STATIC.

class ubluepy.Scanner

צופה GAP לגילוי התקנים מפרסמים בקרבת מקום. זמין רק כאשר הקושחה נבנתה כנגד SoftDevice עם תמיכה במרכזי (s132 / s140).

scan(timeout: int) list

ביצוע סריקה פסיבית למשך timeout אלפיות-שנייה והחזרת רשימה של מופעי ScanEntry — אחד לכל דוח פרסום שהתקבל במהלך החלון.

class ubluepy.ScanEntry

דוח פרסום בודד שנלכד על ידי Scanner.scan(). המופעים מוחזרים מן הסורק — אין constructor ציבורי.

addr() str

מחזיר את כתובת העמית כמחרוזת "xx:xx:xx:xx:xx:xx" בת 17 תווים.

addr_type() int

מחזיר את סוג כתובת העמית (constants.ADDR_TYPE_PUBLIC או constants.ADDR_TYPE_RANDOM_STATIC).

rssi() int

מחזיר את מחוון עוצמת האות ב-dBm.

getScanData() list

פענוח מטען הפרסום לרשימה של tuple-ים (ad_type, description, value). ad_type הוא בית סוג ה-AD המספרי (ראו constants.ad_types), description הוא שם הקבוע התואם כמחרוזת (או None אם הסוג אינו ידוע), ו-value הוא גוף רשומת ה-AD כ-bytearray.

class ubluepy.DefaultDelegate

מחלקת בסיס עבור אובייקטים המועברים אל Peripheral.withDelegate(). צרו ממנה תת-מחלקה ועקפו את handleConnection() / handleNotification() כדי להגיב לאירועי GATT.

handleConnection() None

נקראת באירועי חיבור / ניתוק של GAP. מימוש ברירת המחדל ריק.

handleNotification() None

נקראת בעת התראות GATT נכנסות. מימוש ברירת המחדל ריק.

קבועים

התכונה constants של המודול היא מרחב שמות המכיל מזהי אירועי GAP/GATT, ערכי סוג-כתובת, ומרחב השמות המקונן ad_types.

ubluepy.constants: type

מכל החושף את הקבועים שלהלן.

constants.EVT_GAP_CONNECTED: int

ערך event_id של מטפל החיבור של Peripheral עבור חיבור GAP (16).

constants.EVT_GAP_DISCONNECTED: int

ערך event_id של מטפל החיבור של Peripheral עבור ניתוק GAP (17).

constants.EVT_GATTS_WRITE: int

ערך event_id של מטפל החיבור של Peripheral עבור כתיבה לתכונת GATT מקומית, כולל כתיבות ל-CCCD המפעילות/מבטלות התראות (80).

constants.UUID_CCCD: int

UUID סטנדרטי של Bluetooth עבור ה-Client Characteristic Configuration Descriptor (0x2902).

constants.ADDR_TYPE_PUBLIC: int

כתובת התקן Bluetooth ציבורית (0).

constants.ADDR_TYPE_RANDOM_STATIC: int

כתובת התקן Bluetooth אקראית סטטית (1).

constants.ad_types: type

מרחב שמות של קבועי סוג-AD של נתוני פרסום מן ה-Bluetooth Core Specification Supplement. כל שם ממופה לסוג ה-AD בן הבית הבודד התואם:

שם

ערך

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