aioble — BLE אסינכרוני¶
aioble הוא עטיפה ברמה גבוהה וידידותית ל-asyncio סביב המודול bluetooth. הוא מספק קורוטינות נקיות לסריקה, התחברות, פרסום, שירותי GATT וערוצי L2CAP.
כל הפעולות המרוחקות (connect, disconnect, קריאה/כתיבה של לקוח, indicate של שרת, recv/send של l2cap, pair) ניתנות להמתנה (awaitable) ותומכות בפסקי זמן.
תפקידים נתמכים:
משדר (מפרסם) — יצירת מטעני פרסום ותגובת סריקה עבור שדות נפוצים, פיצול אוטומטי של המטען בין הפרסום לתגובת הסריקה, פרסום ללא הגבלת זמן או למשך זמן קבוע.
התקן היקפי — המתנה להתחברות מצד התקן מרכזי, המתנה להחלפת MTU.
צופה (סורק) — סריקה פסיבית ואקטיבית, שילוב מטעני פרסום ותגובת סריקה עבור אותו התקן, ניתוח שדות נפוצים ממטעני פרסום.
מרכזי — התחברות להתקן היקפי, יזימת החלפת MTU.
לקוח GATT — גילוי שירותים / מאפיינים / מתארים (אופציונלית לפי UUID); קריאה / כתיבה / כתיבה-עם-תגובה על מאפיינים ומתארים; הרשמה להתראות (notifications) ולחיוויים (indications) (באמצעות ה-CCCD); המתנה להתראות ולחיוויים.
שרת GATT — רישום שירותים / מאפיינים / מתארים; המתנה לכתיבות על מאפיינים ומתארים; יירוט בקשות קריאה; שליחת התראות וחיוויים (והמתנה לתגובה).
L2CAP — קבלה והתחברות של ערוצי L2CAP מבוססי-חיבור, ניהול בקרת זרימה של הערוץ.
אבטחה — ניהול מפתחות/סודות מגובה JSON, יזימת התאמה (pairing), שאילתת מצב הצפנה / אימות.
דוגמאות¶
סרוק אחר התקני BLE סמוכים והדפס כל אחד מהם כשהוא נראה:
import aioble
import asyncio
async def find_devices():
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
print(result.device.addr_hex(), result.rssi, result.name())
asyncio.run(find_devices())
התחבר כ-מרכזי להתקן היקפי המפרסם את שירות קצב הלב והירשם להתראות המדידה שלו:
import aioble
import asyncio
import bluetooth
_HR_SERVICE = bluetooth.UUID(0x180D)
_HR_MEASUREMENT = bluetooth.UUID(0x2A37)
async def connect_and_read():
device = None
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
if _HR_SERVICE in result.services():
device = result.device
break
if device is None:
return
async with await device.connect() as conn:
service = await conn.service(_HR_SERVICE)
char = await service.characteristic(_HR_MEASUREMENT)
await char.subscribe(notify=True)
while True:
data = await char.notified()
print("notify:", data)
asyncio.run(connect_and_read())
פעל כ-התקן היקפי: רשום שירות GATT, פרסם אותו, ודחוף התראות לכל מי שמתחבר:
import aioble
import asyncio
import bluetooth
import struct
_ENV_SERVICE = bluetooth.UUID(0x181A)
_TEMP_CHAR = bluetooth.UUID(0x2A6E)
def encode_temperature(deg_c):
# Bluetooth Temperature (0x2A6E) is sint16 little-endian, 0.01 degC units.
return struct.pack("<h", round(deg_c * 100))
service = aioble.Service(_ENV_SERVICE)
temp_char = aioble.Characteristic(service, _TEMP_CHAR, read=True, notify=True)
aioble.register_services(service)
async def peripheral_task():
while True:
connection = await aioble.advertise(
interval_us=250000,
name="openmv-sensor",
services=[_ENV_SERVICE],
appearance=0x0300,
)
print("connected:", connection.device.addr_hex())
async with connection:
while connection.is_connected():
temp_char.write(encode_temperature(23.68), send_update=True)
await asyncio.sleep(1)
asyncio.run(peripheral_task())
פונקציות ברמת המודול¶
- aioble.config(*args, **kwargs) Any¶
מעביר אל
bluetooth.BLE.config(), תוך הבטחה שרדיו ה-BLE פעיל תחילה.- args
שם פרמטר יחיד אופציונלי לשאילתה.
- kwargs
ארגומנטים בעלי מילות מפתח לקביעת ערכי תצורה.
- aioble.stop() None¶
השבת את רדיו ה-BLE הבסיסי והרץ את כל מטפלי הכיבוי הרשומים של תת-המודולים. לאחר קריאה לזה, כל הסורקים, המפרסמים, החיבורים וערוצי L2CAP מפורקים.
- aioble.scan(duration_ms: int, interval_us: int | None = None, window_us: int | None = None, active: bool = False) scan¶
מחזיר מנהל-הקשר אסינכרוני / איטרטור אסינכרוני של
scanהמניב מופעיScanResultעבור כל התקן ייחודי שמתגלה (או עבור כל פיסת נתוני פרסום חדשה מהתקן מוכר).- duration_ms
כמה זמן לסרוק, באלפיות שנייה. העבר
0כדי לסרוק ללא הגבלת זמן עד שמנהל ההקשר יוצא.- interval_us
מרווח סריקה במיקרו-שניות. ברירת המחדל היא 1,280,000.
- window_us
חלון סריקה במיקרו-שניות (חייב להיות קטן או שווה ל-interval_us). ברירת המחדל היא 11,250.
- active
אם
True, בצע סריקה אקטיבית (בקש נתוני תגובת סריקה). ברירת המחדל היאFalse.
- aioble.advertise(interval_us: int, adv_data: bytes | None = None, resp_data: bytes | None = None, connectable: bool = True, limited_disc: bool = False, br_edr: bool = False, name: str | None = None, services: list | None = None, appearance: int = 0, manufacturer: tuple | None = None, timeout_ms: int | None = None) DeviceConnection¶
קורוטינה אסינכרונית שמתחילה לפרסם וממתינה להתחברות נכנסת של התקן מרכזי. מחזירה
DeviceConnectionהמייצג את ההתקן המרכזי המחובר, או מעלהasyncio.TimeoutErrorבעת פסק זמן.- interval_us
מרווח הפרסום, במיקרו-שניות.
- adv_data
מטען פרסום גולמי. אם לא הוגדר, adv_data נבנה מיתר הארגומנטים בעלי מילות המפתח.
- resp_data
מטען תגובת סריקה גולמי. מאוכלס אוטומטית מהגלישה של adv_data במידת הצורך.
- connectable
אם
True, זהו פרסום הניתן להתחברות.- limited_disc
השתמש בדגל הגילוי-המוגבל במקום בכללי.
- br_edr
קבע את דגל תמיכת BR/EDR.
- name
שם מקומי מלא אופציונלי להטמעה.
- services
אובייקט נתן-לאיטרציה של
bluetooth.UUIDלפרסום.- appearance
ערך מראה (appearance) בן 16 סיביות (ראה מספרי Bluetooth מוקצים).
- manufacturer
טפל (tuple) של
(company_id, data_bytes)לפרסום כנתונים ספציפיים ליצרן.- timeout_ms
הפסק לפרסם לאחר כל כך הרבה אלפיות שנייה ללא חיבור.
Noneפירושו לפרסם עד להתחברות.
קבועים ברמת המודול¶
- aioble.ADDR_PUBLIC¶
סוג כתובת התקן BLE ציבורי (
0).
- aioble.ADDR_RANDOM¶
סוג כתובת התקן BLE אקראי (
1).
חריגות¶
- exception aioble.GattError¶
מועלית כאשר פעולת GATT מרוחקת (קריאה / כתיבה / חיווי) מסתיימת עם סטטוס שאינו אפס. קוד הסטטוס זמין במאפיין
_status.
- exception aioble.DeviceDisconnectedError¶
מועלית בתוך פעולה אסינכרונית (למשל read, write, notified) כאשר החיבור הבסיסי נופל בזמן ההמתנה.
- exception aioble.L2CAPDisconnectedError¶
מועלית כאשר מתבצע ניסיון לפעולת send/recv/flush של ערוץ L2CAP על (או מופרע על ידי) ערוץ מנותק.
- exception aioble.L2CAPConnectionError¶
מועלית על ידי
DeviceConnection.l2cap_connectכאשר יצירת הערוץ נכשלת. קוד סטטוס ה-Bluetooth הוא הארגומנט הראשון.
מחלקות¶
- class aioble.Device(addr_type: int, addr: bytes | str)¶
מייצג התקן BLE מרוחק לפי כתובת. שני מופעי
Deviceשווים אם גם addr_type וגם addr תואמים. משמש כידית לייזום חיבורים.- addr_type
או
ADDR_PUBLICאוADDR_RANDOM.- addr
כתובת בת שישה בתים כ-
bytes, או מחרוזת הקסדצימלית מופרדת בנקודתיים (למשל"aa:bb:cc:dd:ee:ff").
- addr_type¶
סוג הכתובת שאיתה נבנה ההתקן.
- addr¶
כתובת ההתקן הגולמית בת שישה הבתים.
- connect(timeout_ms: int = 10000, scan_duration_ms: int | None = None, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None) Awaitable[DeviceConnection]¶
אסינכרוני. יזום חיבור GAP להתקן זה והחזר את ה-
DeviceConnectionהמתקבל. מבטל כל סריקה המתבצעת.- timeout_ms
כמה זמן להמתין להשלמת החיבור.
- scan_duration_ms
משך הסריקה ההתחלתי לפני ההתחברות (ספציפי לבקר).
- min_conn_interval_us / max_conn_interval_us
גבולות מרווח חיבור אופציונליים, במיקרו-שניות.
- class aioble.DeviceConnection¶
חיבור GAP פעיל אל
Device. מוחזר על ידיDevice.connect()אוadvertise. תומך בשימוש כמנהל הקשרasync withשמתנתק אוטומטית ביציאה.אל תבנה ישירות.
- encrypted¶
Trueברגע שהקישור מוצפן (למשל לאחר התאמה).
- authenticated¶
Trueאם הקישור אומת (התאמה מוגנת-MITM).
- bonded¶
Trueאם ההתאמה הפיקה מפתחות קישור (bonding).
- key_size¶
גודל מפתח ההצפנה שהוסכם בבתים, או
Falseאם לא מוצפן.
- mtu¶
ATT MTU שהוסכם לאחר
exchange_mtu, אוNoneעד להגדרה.
- disconnect(timeout_ms: int = 2000) Awaitable[None]¶
אסינכרוני. התנתק והמתן לפסיקת ההתנתקות (IRQ).
- timeout_ms
הזמן המרבי להמתנה להתנתקות.
- disconnected(timeout_ms: int | None = None, disconnect: bool = False) Awaitable[None]¶
אסינכרוני. המתן לכך שהחיבור יסתיים על ידי אחד הצדדים. אם disconnect הוא
Trueהוא מתנתק אקטיבית תחילה.- timeout_ms
הזמן המרבי להמתנה.
Noneפירושו להמתין לנצח.- disconnect
אם
True, יזום התנתקות.
- timeout(timeout_ms: int | None) DeviceTimeout¶
החזר מנהל הקשר שמבטל את גוף הקוד שלו אם פסק הזמן חולף (ומעלה
asyncio.TimeoutError) או אם ההתקן מתנתק (ומעלהDeviceDisconnectedError).- timeout_ms
פסק זמן באלפיות שנייה, או
Noneללא פסק זמן.
- exchange_mtu(mtu: int | None = None, timeout_ms: int = 1000) Awaitable[int]¶
אסינכרוני. יזום החלפת ATT MTU והחזר את ה-MTU שהוסכם.
- mtu
MTU מועדף אופציונלי לקביעה על ממשק ה-BLE הבסיסי לפני ההחלפה.
- timeout_ms
פסק זמן עבור ההחלפה.
- service(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientService | None]¶
אסינכרוני. גלה שירות מרוחק יחיד התואם את uuid, או
Noneאם לא נמצא.
- services(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
החזר איטרטור אסינכרוני של אובייקטי
ClientServiceמרוחקים. השתמש עםasync forוהרץ את הלולאה עד סופה.- uuid
מסנן UUID אופציונלי.
Noneמחזיר כל שירות.- timeout_ms
פסק זמן לכל גילוי.
- pair(bond: bool = True, le_secure: bool = True, mitm: bool = False, io: int = 3, timeout_ms: int = 20000) Awaitable[None]¶
אסינכרוני. יזום התאמה על חיבור זה. מעדכן את המאפיינים
encrypted/authenticated/bonded/key_sizeבעת ההשלמה.- bond
שמור את מפתחות ההתאמה.
- le_secure
השתמש ב-LE Secure Connections.
- mitm
דרוש הגנת man-in-the-middle.
- io
קבוע יכולת IO (למשל
3עבור ללא קלט/פלט).- timeout_ms
פסק זמן להתאמה.
- l2cap_accept(psm: int, mtu: int, timeout_ms: int | None = None) Awaitable[L2CAPChannel]¶
אסינכרוני. האזן ב-PSM הנתון והחזר
L2CAPChannelברגע שהצד המרוחק פותח אותו.- psm
ה-Protocol/Service Multiplexer להאזנה בו.
- mtu
גודל הקבלה המרבי, בבתים.
- timeout_ms
הזמן המרבי להמתנה להתחברות הצד המרוחק.
- l2cap_connect(psm: int, mtu: int, timeout_ms: int = 1000) Awaitable[L2CAPChannel]¶
אסינכרוני. פתח ערוץ L2CAP לצד המרוחק ב-PSM הנתון.
- psm
ה-Protocol/Service Multiplexer להתחברות אליו.
- mtu
גודל הקבלה המרבי, בבתים.
- timeout_ms
פסק זמן לחיבור.
- class aioble.ScanResult¶
התקן יחיד שהתגלה במהלך
scan. אותו מופע מונב מחדש ככל שמגיעים נתוני פרסום חדשים.אל תבנה ישירות.
- rssi¶
ה-RSSI האחרון שדווח, ב-dBm.
- adv_data¶
מטען פרסום גולמי (
bytesאוNone).
- resp_data¶
מטען תגובת סריקה גולמי (
bytesאוNone), אם סריקה אקטיבית מאופשרת.
- connectable¶
Trueאם הפרסום האחרון היה ניתן להתחברות.
- services() Iterator[bluetooth.UUID]¶
גנרטור המניב כל
bluetooth.UUIDשפורסם בשדות רשימת-השירותים בני 16/32/128 הסיביות.
- class aioble.Service(uuid: bluetooth.UUID)¶
שירות GATT מקומי. בנה שירות עם מופע
Characteristicאחד או יותר, ואז העבר אותו אלregister_services.- uuid
ה-UUID של השירות.
- uuid¶
ה-UUID של השירות.
- characteristics¶
רשימת אובייקטי
Characteristicהמאוגדים לשירות זה.
- class aioble.Characteristic(service: Service, uuid: bluetooth.UUID, read: bool = False, write: bool = False, write_no_response: bool = False, notify: bool = False, indicate: bool = False, initial: bytes | None = None, capture: bool = False)¶
מאפיין GATT מקומי. בנייה של אחד מצרפת אותו אוטומטית אל service.
- service
ה-
Serviceהבעלים.- uuid
ה-UUID של המאפיין.
- read, write, write_no_response, notify, indicate
ערכים בוליאניים הבוחרים את פעולות ה-GATT הנתמכות.
- initial
ערך התחלתי אופציונלי (
bytes).- capture
אם
True, ערכים שנכתבו מוכנסים לתור (עד עומק 10) כך שכתיבות רצופות מהירות לא יאבדו. כל קריאתwrittenמחזירה אז טפל (tuple) של(connection, data).
- uuid¶
ה-UUID של המאפיין.
- flags¶
מסכת סיביות של דגלי תכונות ה-GATT שנבנו מהבנאי.
- descriptors¶
רשימת אובייקטי
Descriptorהמאוגדים למאפיין זה.
- write(data: bytes, send_update: bool = False) None¶
עדכן את הערך במסד הנתונים המקומי של GATT.
- data
בתי הערך החדש.
- send_update
אם
True, גם התראה/חיווי לכל חיבור שנרשם.
- notify(connection: DeviceConnection, data: bytes | None = None) None¶
שלח GATT Notify אל connection.
- connection
חיבור הלקוח היעד.
- data
מטען לשליחה. אם
None, הערך המקומי הנוכחי נשלח.
- indicate(connection: DeviceConnection, data: bytes | None = None, timeout_ms: int = 1000) Awaitable[None]¶
אסינכרוני. שלח GATT Indicate אל connection והמתן לאישור הלקוח. מעלה
GattErrorבעת סטטוס שאינו אפס.- connection
חיבור הלקוח היעד.
- data
מטען לחיווי, או
Noneלשליחת הערך המקומי.- timeout_ms
הזמן המרבי להמתנה לאישור.
- written(timeout_ms: int | None = None) Awaitable[DeviceConnection | tuple[DeviceConnection, bytes]]¶
אסינכרוני. המתן לכתיבה מרוחקת. מחזיר את ה-
DeviceConnectionהכותב, או(connection, data)אם המאפיין נוצר עםcapture=True.- timeout_ms
הזמן המרבי להמתנה.
Noneממתין לנצח.
- on_read(connection: DeviceConnection) int¶
וו עקיפה (hook) המופעל באופן סינכרוני כאשר מתקבלת קריאה מרוחקת. החזר
0כדי לאפשר את הקריאה או קוד שגיאת ATT שאינו אפס כדי לדחות אותה. יישום ברירת המחדל מחזיר0.
- class aioble.BufferedCharacteristic(service: Service, uuid: bluetooth.UUID, max_len: int = 20, append: bool = False, **kwargs)¶
Characteristicשאת חוצץ ה-GATT המגבה שלו ניתן להגדיר. שימושי לקבלת ערכים גדולים מגודל התכונה כברירת מחדל, או לתיעדוף כתיבות רצופות.- max_len
גודל החוצץ (buffer), בבתים.
- append
אם
True, כתיבות עוקבות מתווספות לחוצץ במקום לדרוס אותו.
ארגומנטים אחרים מועברים אל
Characteristic.
- class aioble.Descriptor(characteristic: Characteristic, uuid: bluetooth.UUID, read: bool = False, write: bool = False, initial: bytes | None = None)¶
מתאר GATT מקומי. בנייה של אחד מצרפת אותו אוטומטית אל characteristic. יורש את
read,writeו-writtenמ-Characteristic.- characteristic
ה-
Characteristicהבעלים.- uuid
ה-UUID של המתאר.
- read, write
ערכים בוליאניים הבוחרים את פעולות ה-GATT הנתמכות.
- initial
ערך התחלתי אופציונלי (
bytes).
- class aioble.ClientService¶
שירות GATT מרוחק שהתגלה על עמית. מוחזר על ידי
DeviceConnection.service()או נאסף באיטרציה מ-DeviceConnection.services().אל תבנה ישירות.
- connection¶
ה-
DeviceConnectionהבעלים.
- uuid¶
ה-UUID של השירות המרוחק.
- characteristic(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientCharacteristic | None]¶
אסינכרוני. גלה מאפיין יחיד לפי UUID, או
Noneאם לא נמצא.
- characteristics(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
החזר איטרטור אסינכרוני של אובייקטי
ClientCharacteristic. השתמש עםasync forוהרץ את הלולאה עד סופה.- uuid
מסנן UUID אופציונלי.
- timeout_ms
פסק זמן לכל גילוי.
- class aioble.ClientCharacteristic¶
מאפיין GATT מרוחק שהתגלה על עמית. מוחזר על ידי
ClientService.characteristic()או נאסף באיטרציה מ-ClientService.characteristics().אל תבנה ישירות.
- service¶
ה-
ClientServiceהבעלים.
- uuid¶
ה-UUID של המאפיין.
- properties¶
מסכת סיביות של פעולות ה-GATT הנתמכות כפי שדווח על ידי העמית.
- read(timeout_ms: int = 1000) Awaitable[bytes]¶
אסינכרוני. הוצא GATT Read והחזר את הערך. מעלה
GattErrorבעת סטטוס שאינו אפס.- timeout_ms
פסק זמן לקריאה.
- write(data: bytes, response: bool | None = None, timeout_ms: int = 1000) Awaitable[None]¶
אסינכרוני. הוצא GATT Write.
- data
ערך לכתיבה.
- response
Trueכדי לדרוש תגובת-כתיבה (ולהעלותGattErrorבעת כישלון).Falseעבור כתיבה-ללא-תגובה.None(ברירת מחדל) בוחר אוטומטית בהתאם למה שהעמית מפרסם.- timeout_ms
פסק זמן לכתיבה (רלוונטי רק אם response הוא
True).
- notified(timeout_ms: int | None = None) Awaitable[bytes]¶
אסינכרוני. המתן להתראה הבאה על מאפיין זה והחזר את המטען שלה. מחזיר מיד אם התראה כבר נמצאת בתור.
- timeout_ms
הזמן המרבי להמתנה.
Noneממתין לנצח.
- indicated(timeout_ms: int | None = None) Awaitable[bytes]¶
אסינכרוני. המתן לחיווי הבא על מאפיין זה והחזר את המטען שלו.
- timeout_ms
הזמן המרבי להמתנה.
- subscribe(notify: bool = True, indicate: bool = False) Awaitable[None]¶
אסינכרוני. כתוב את ה-Client Characteristic Configuration Descriptor (CCCD) כדי להירשם (או לבטל הרשמה) להתראות ו/או לחיוויים.
- notify
אפשר התראות.
- indicate
אפשר חיוויים.
- descriptor(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientDescriptor | None]¶
אסינכרוני. גלה מתאר יחיד לפי UUID, או
Noneאם לא נמצא.
- descriptors(timeout_ms: int = 2000) ClientDiscover¶
החזר איטרטור אסינכרוני של אובייקטי
ClientDescriptor. השתמש עםasync forוהרץ את הלולאה עד סופה.
- class aioble.ClientDescriptor¶
מתאר GATT מרוחק שהתגלה על עמית. יורש את
readו-writeמ-ClientCharacteristic.אל תבנה ישירות.
- characteristic¶
ה-
ClientCharacteristicהבעלים.
- uuid¶
ה-UUID של המתאר.
- class aioble.L2CAPChannel¶
ערוץ L2CAP פעיל מבוסס-חיבור. מוחזר על ידי
DeviceConnection.l2cap_accept()אוDeviceConnection.l2cap_connect(). תומך בשימוש כמנהל הקשרasync withשמתנתק אוטומטית ביציאה.אל תבנה ישירות.
- our_mtu¶
הגודל המרבי, בבתים, שהעמית רשאי לשלוח אלינו ב-SDU יחיד.
- peer_mtu¶
הגודל המרבי, בבתים, שאנו רשאים לשלוח לעמית ב-SDU יחיד.
- available() bool¶
החזר באופן סינכרוני
Trueאם נתוני קבלה מאוחסנים בחוצץ מוכנים (כלומרrecvintoלא ייחסם).
- recvinto(buf: bytearray, timeout_ms: int | None = None) Awaitable[int]¶
אסינכרוני. קבל אל תוך buf, והחזר את מספר הבתים שנקראו. ממתין לנתונים חדשים אם הערוץ ריק.
- buf
חוצץ מוקצה-מראש למילוי.
- timeout_ms
הזמן המרבי להמתנה.
Noneממתין לנצח.
- send(buf: bytes, timeout_ms: int | None = None, chunk_size: int | None = None) Awaitable[None]¶
אסינכרוני. שלח את buf על הערוץ, תוך פיצול מטענים גדולים יותר לחלקים בגודל MTU. ממתין לאשראי בקרת-זרימה לפי הצורך.
- buf
אובייקט דמוי-בתים לשליחה.
- timeout_ms
הזמן המרבי להמתנה לכל חלק.
- chunk_size
עקיפה אופציונלית לגודל החלק לכל קריאה. מוגבל ל-
min(our_mtu * 2, peer_mtu).
- flush(timeout_ms: int | None = None) Awaitable[None]¶
אסינכרוני. המתן עד שכל
sendתקוע נוקז על ידי הבקר.- timeout_ms
הזמן המרבי להמתנה.