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