bluetooth — Bluetooth ברמה נמוכה¶
מודול זה מספק ממשק לבקר ה-Bluetooth המובנה. הוא תומך ב-Bluetooth Low Energy (BLE) בתפקידי Central, Peripheral, Broadcaster ו-Observer, וכן ב-GATT Server וב-Client ובערוצי L2CAP מוכווני חיבור. התקן יכול לפעול בכמה תפקידים בו-זמנית. כמו כן נתמכים Pairing ו-Bonding.
ממשק API זה נועד להתאים לפרוטוקול ה-Bluetooth ברמה נמוכה ולספק אבני בניין לרמות הפשטה גבוהות יותר, כגון סוגי התקנים ספציפיים.
טיפ
עבור רוב היישומים, מומלץ להעדיף את הספרייה ברמה גבוהה יותר aioble, המספקת עטיפה מבוססת asyncio סביב מודול זה. ראו aioble — BLE אסינכרוני.
class BLE¶
- class bluetooth.BLE¶
מחזירה את אובייקט ה-BLE היחיד (singleton).
תצורה
- active(active: bool | None = None, /) bool¶
משנה אופציונלית את מצב הפעילות של רדיו ה-BLE, ומחזירה את המצב הנוכחי.
יש להפעיל את הרדיו לפני השימוש בכל שיטה אחרת במחלקה זו.
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
מקבלת או קובעת ערכי תצורה של ממשק ה-BLE. לקבלת ערך יש לציין את שם הפרמטר כמחרוזת בין מירכאות, ומתבצעת שאילתה של פרמטר אחד בלבד בכל פעם. לקביעת ערכים יש להשתמש בתחביר מילות מפתח, וניתן לקבוע פרמטר אחד או יותר בכל פעם.
הערכים הנתמכים כעת הם:
'mac': הכתובת הנוכחית שבשימוש, בהתאם למצב הכתובת הנוכחי. מחזיר tuple בצורת(addr_type, addr).ראו
gap_scanלפרטים על סוג הכתובת.ניתן לבצע שאילתה זו רק כאשר הממשק פעיל כעת.
'addr_mode': קובע את מצב הכתובת. הערכים הם:ערך
שם
התנהגות
0x00PUBLIC
שימוש בכתובת הציבורית של הבקר.
0x01RANDOM
שימוש בכתובת סטטית מחוללת.
0x02RPA
שימוש בכתובות פרטיות הניתנות לפענוח (resolvable).
0x03NRPA
שימוש בכתובות פרטיות שאינן ניתנות לפענוח (non-resolvable).
כברירת מחדל, הממשק ישתמש בכתובת PUBLIC אם היא זמינה, אחרת ישתמש בכתובת RANDOM.
'gap_name': מקבל/קובע את שם התקן ה-GAP המשמש את שירות ה-Generic Access (UUID0x1800), מאפיין Device Name (UUID0x2a00). ניתן לקבוע זאת בכל עת ולשנות פעמים רבות.'rxbuf': מקבל/קובע את גודל החוצץ (buffer) הפנימי בבתים המשמש לאחסון אירועים נכנסים. חוצץ זה הוא גלובלי לכל מנהל ההתקן של ה-BLE ולכן מטפל בנתונים נכנסים עבור כל האירועים, כולל כל המאפיינים. הגדלתו מאפשרת טיפול טוב יותר בנתונים נכנסים בפרצים (לדוגמה תוצאות סריקה) ויכולת לקבל ערכי מאפיינים גדולים יותר.'mtu': מקבל/קובע את ה-MTU שישמש במהלך חילופי ATT MTU. ה-MTU המתקבל יהיה המינימום בין ערך זה לבין ה-MTU של ההתקן המרוחק. חילופי ATT MTU לא יקרו אוטומטית (אלא אם ההתקן המרוחק יוזם זאת), ויש ליזום אותם ידנית באמצעותgattc_exchange_mtu. השתמשו באירוע_IRQ_MTU_EXCHANGEDכדי לגלות את ה-MTU עבור חיבור נתון.'bond': קובע האם Bonding יופעל במהלך ה-Pairing. כאשר מופעל, בקשות Pairing יקבעו את דגל ”bond“ והמפתחות יאוחסנו בשני ההתקנים.'mitm': קובע האם נדרשת הגנת MITM עבור ה-Pairing.'io': קובע את יכולות הקלט/פלט של התקן זה.האפשרויות הזמינות הן:
קבוע
ערך
יכולת
_IO_CAPABILITY_DISPLAY_ONLY0
תצוגה בלבד
_IO_CAPABILITY_DISPLAY_YESNO1
תצוגה עם קלט כן/לא
_IO_CAPABILITY_KEYBOARD_ONLY2
מקלדת בלבד
_IO_CAPABILITY_NO_INPUT_OUTPUT3
ללא קלט או פלט
_IO_CAPABILITY_KEYBOARD_DISPLAY4
מקלדת ותצוגה
'le_secure': קובע האם נדרש Pairing מסוג ”LE Secure“. ברירת המחדל היא false (כלומר, מאפשר ”Legacy Pairing“).
טיפול באירועים
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
רושמת פונקציית callback עבור אירועים מערימת ה-BLE. ה-handler מקבל שני ארגומנטים,
event(שיהיה אחד מהקודים שלהלן) ו-data(שהוא tuple של ערכים ספציפי לאירוע).הערה: כאופטימיזציה למניעת הקצאות מיותרות, הרשומות
addr,adv_data,char_data,notify_dataו-uuidב-tuples הן מופעי memoryview לקריאה בלבד המצביעים על ה-ringbuffer הפנימי שלbluetooth, ותקפים רק במהלך הקריאה לפונקציית מטפל ה-IRQ. אם התוכנית שלכם צריכה לשמור אחד מערכים אלה לגישה לאחר שמטפל ה-IRQ חזר (למשל על ידי שמירתו במופע מחלקה או במשתנה גלובלי), עליה ליצור עותק של הנתונים, באמצעותbytes()אוbluetooth.UUID(), כך:connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid)
לדוגמה, מטפל ה-IRQ עבור תוצאת סריקה עשוי לבדוק את
adv_dataכדי להחליט אם זה ההתקן הנכון, ורק אז להעתיק את נתוני הכתובת לשימוש במקום אחר בתוכנית. וכדי להדפיס נתונים מתוך מטפל ה-IRQ, יידרשprint(bytes(addr)).מטפל מנתב בדרך כלל לפי קוד האירוע ופורק את ה-tuple של המטען (payload) הספציפי לאירוע:
def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: conn_handle, addr_type, addr = data ... elif event == _IRQ_SCAN_RESULT: addr_type, addr, adv_type, rssi, adv_data = data ...
כל קוד אירוע, המטען שהוא מספק, ותיאור קצר מופיעים להלן. עבור אירועים שבהם מצוין השדה
status,statusהוא0בהצלחה וערך לא-אפס ספציפי למימוש בכשל.קבוע
ערך
אירוע
tuple של מטען (payload)
_IRQ_CENTRAL_CONNECT1
התקן central התחבר ל-peripheral זה.
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
התקן central התנתק מ-peripheral זה.
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
לקוח מחובר כתב למאפיין או למתאר (descriptor) מקומי. השתמשו ב-
gatts_readכדי לאחזר את הערך החדש.(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
לקוח מחובר ביצע קריאה. החזירו קוד שגיאה לא-אפס מהטבלה שלהלן כדי לדחות את הקריאה, או
0/Noneכדי לקבל אותה.(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
חבילת פרסום (advertising) בודדת התקבלה במהלך סריקה פעילה.
(addr_type, addr, adv_type, rssi, adv_data)_IRQ_SCAN_DONE6
הסריקה הנוכחית הסתיימה, או משום שחלף משך הזמן שהוגדר או משום ש-
gap_scan(None)נקראה.()_IRQ_PERIPHERAL_CONNECT7
קריאת
gap_connectקודמת הצליחה.(conn_handle, addr_type, addr)_IRQ_PERIPHERAL_DISCONNECT8
התקן peripheral מחובר התנתק.
(conn_handle, addr_type, addr)_IRQ_GATTC_SERVICE_RESULT9
שירות אחד נמצא על ידי
gattc_discover_services.(conn_handle, start_handle, end_handle, uuid)_IRQ_GATTC_SERVICE_DONE10
גילוי השירותים הסתיים.
(conn_handle, status)_IRQ_GATTC_CHARACTERISTIC_RESULT11
מאפיין אחד נמצא על ידי
gattc_discover_characteristics.(conn_handle, end_handle, value_handle, properties, uuid)_IRQ_GATTC_CHARACTERISTIC_DONE12
גילוי המאפיינים הסתיים.
(conn_handle, status)_IRQ_GATTC_DESCRIPTOR_RESULT13
מתאר (descriptor) אחד נמצא על ידי
gattc_discover_descriptors.(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
גילוי המתארים (descriptors) הסתיים.
(conn_handle, status)_IRQ_GATTC_READ_RESULT15
קריאת
gattc_readקודמת החזירה נתונים.(conn_handle, value_handle, char_data)_IRQ_GATTC_READ_DONE16
קריאת
gattc_readקודמת הסתיימה.(conn_handle, value_handle, status)_IRQ_GATTC_WRITE_DONE17
כתיבת
gattc_writeקודמת אושרה.(conn_handle, value_handle, status)_IRQ_GATTC_NOTIFY18
שרת מרוחק שלח התראה (notification) שאינה מאושרת.
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
שרת מרוחק שלח התרעה (indication) מאושרת.
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
התרעה (indication) שנשלחה קודם לכן אושרה על ידי הלקוח (או שתם הזמן הקצוב לה).
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
חילופי ATT MTU הושלמו (ביוזמת אחד הצדדים).
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
התקן מרוחק ביקש חיבור L2CAP ב-PSM שהתקן זה מאזין עליו. החזירו מספר שלם לא-אפס כדי לדחות, או
0/Noneכדי לקבל.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_CONNECT23
ערוץ L2CAP נוצר כעת, או על ידי קבלת בקשה נכנסת או על ידי השלמת
l2cap_connectיוצא.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_DISCONNECT24
ערוץ L2CAP התנתק.
statusהוא0עבור ניתוק נקי, או לא-אפס אם ניסיון חיבור יוצא נכשל.(conn_handle, cid, psm, status)_IRQ_L2CAP_RECV25
נתונים הגיעו בערוץ L2CAP. קראו ל-
l2cap_recvintoכדי לקרוא אותם.(conn_handle, cid)_IRQ_L2CAP_SEND_READY26
קריאת
l2cap_sendקודמת שהחזירהFalseהתרוקנה והערוץ מוכן שוב.statusלא-אפס משמעו שחוצץ השידור גלש ועל היישום לשלוח את הנתונים מחדש.(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
ההתקן המרוחק עדכן את פרמטרי החיבור (interval, latency, supervision timeout).
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
מצב ההצפנה של חיבור השתנה, בדרך כלל לאחר השלמת Pairing או Bonding.
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
הערימה מבקשת סוד Bonding מאוחסן. אם
keyהואNone, החזירו את הערך המאוחסן ה-indexי מסוגsec_type; אחרת החזירו את הערך המשויך ל-(sec_type, key)הנתון. החזירוNoneאם לא מאוחסן דבר.(sec_type, index, key)_IRQ_SET_SECRET30
הערימה מבקשת מהיישום לשמור סוד Bonding. החזירו
Trueלאחר השמירה.(sec_type, key, value)_IRQ_PASSKEY_ACTION31
נדרשת פעולת passkey כחלק מה-Pairing. הגיבו באמצעות
gap_passkey; ראו את טבלת פעולות ה-passkey שלהלן עבור הפעולות האפשריות.(conn_handle, action, passkey)עבור אירוע
_IRQ_GATTS_READ_REQUEST, קודי ההחזרה הזמינים הם:קבוע
ערך
משמעות
_GATTS_NO_ERROR0x00קבל את הקריאה.
_GATTS_ERROR_READ_NOT_PERMITTED0x02קריאה אינה מותרת.
_GATTS_ERROR_WRITE_NOT_PERMITTED0x03כתיבה אינה מותרת.
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION0x05הלקוח אינו מאומת.
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION0x08הלקוח אינו מורשה.
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION0x0fהקישור אינו מוצפן.
עבור אירוע
_IRQ_PASSKEY_ACTION, הפעולות הזמינות הן:קבוע
ערך
משמעות
_PASSKEY_ACTION_NONE0
לא נדרשת פעולה.
_PASSKEY_ACTION_INPUT2
בקש מהמשתמש להזין את ה-passkey המוצג בהתקן המרוחק.
_PASSKEY_ACTION_DISPLAY3
הצג passkey בן 6 ספרות שההתקן המרוחק יזין.
_PASSKEY_ACTION_NUMERIC_COMPARISON4
אשר שה-passkey תואם לזה המוצג בהתקן המרוחק.
כדי לחסוך מקום בקושחה, קבועים אלה אינם כלולים במודול
bluetooth. הוסיפו לתוכנית שלכם את אלה שאתם צריכים מהרשימות שלמעלה.
תפקיד Broadcaster (מפרסם)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
מתחילה פרסום (advertising) במרווח שצוין (במיקרו-שניות). מרווח זה יעוגל כלפי מטה ל-625us הקרובים ביותר. כדי להפסיק את הפרסום, קבעו את interval_us ל-
None.adv_data ו-resp_data יכולים להיות כל טיפוס שמממש את פרוטוקול החוצץ (buffer) (למשל
bytes,bytearray,str). adv_data נכלל בכל השידורים, ו-resp_data נשלח בתגובה לסריקה פעילה.הערה: אם adv_data (או resp_data) הוא
None, אזי הנתונים שהועברו בקריאה הקודמת ל-gap_advertiseיישמשו מחדש. הדבר מאפשר ל-broadcaster לחדש את הפרסום באמצעותgap_advertise(interval_us)בלבד. כדי לנקות את מטען הפרסום העבירוbytesריק, כלומרb''.
תפקיד Observer (סורק)
- gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None¶
מריצה פעולת סריקה הנמשכת למשך הזמן שצוין (באלפיות שנייה).
כדי לסרוק ללא הגבלת זמן, קבעו את duration_ms ל-
0.כדי להפסיק את הסריקה, קבעו את duration_ms ל-
None.השתמשו ב-interval_us וב-window_us כדי להגדיר אופציונלית את מחזור הפעולה (duty cycle). הסורק יפעל למשך window_us מיקרו-שניות בכל interval_us מיקרו-שניות, לסך הכול של duration_ms אלפיות שנייה. ברירת המחדל של ה-interval וה-window היא 1.28 שניות ו-11.25 אלפיות שנייה בהתאמה (סריקת רקע).
עבור כל תוצאת סריקה יופעל אירוע
_IRQ_SCAN_RESULT, עם נתוני אירוע(addr_type, addr, adv_type, rssi, adv_data).ערכי
addr_typeמציינים כתובות ציבוריות או אקראיות:ערך
שם
משמעות
0x00PUBLIC
כתובת התקן ציבורית.
0x01RANDOM
כתובת אקראית (סטטית, RPA או NRPA; הסוג מקודד בכתובת עצמה).
ערכי
adv_typeמתאימים למפרט ה-Bluetooth:ערך
שם
משמעות
0x00ADV_IND
פרסום בלתי-מכוון הניתן לחיבור ולסריקה.
0x01ADV_DIRECT_IND
פרסום מכוון הניתן לחיבור.
0x02ADV_SCAN_IND
פרסום בלתי-מכוון הניתן לסריקה.
0x03ADV_NONCONN_IND
פרסום בלתי-מכוון שאינו ניתן לחיבור.
0x04SCAN_RSP
תגובת סריקה.
ניתן לקבוע את
activeל-Trueאם ברצונכם לקבל תגובות סריקה בתוצאות.כאשר הסריקה נעצרת (או בשל סיום משך הזמן או בעצירה מפורשת), יופעל אירוע
_IRQ_SCAN_DONE.
תפקיד Central
התקן central יכול להתחבר ל-peripherals שהוא גילה באמצעות תפקיד ה-observer (ראו
gap_scan) או באמצעות כתובת ידועה.- gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None¶
מתחברת ל-peripheral.
ראו
gap_scanלפרטים על סוגי כתובות.כדי לבטל ניסיון חיבור תלוי ועומד מוקדם, קראו ל-
gap_connect(None).בהצלחה, יופעל אירוע
_IRQ_PERIPHERAL_CONNECT. בעת ביטול ניסיון חיבור, יופעל אירוע_IRQ_PERIPHERAL_DISCONNECT.ההתקן ימתין עד scan_duration_ms כדי לקבל מטען פרסום מההתקן.
ניתן להגדיר את מרווח החיבור במיקרו-שניות באמצעות min_conn_interval_us ו/או max_conn_interval_us. אחרת ייבחר מרווח ברירת מחדל, בדרך כלל בין 30000 ל-50000 מיקרו-שניות. מרווח קצר יותר יגדיל את התפוקה, על חשבון צריכת החשמל.
תפקיד Peripheral
מצופה מהתקן peripheral לשלוח פרסומים הניתנים לחיבור (ראו
gap_advertise). הוא ישמש בדרך כלל כ-GATT server, לאחר שרשם תחילה שירותים ומאפיינים באמצעותgatts_register_services.כאשר התקן central מתחבר, יופעל אירוע
_IRQ_CENTRAL_CONNECT.תפקידי Central ו-Peripheral
- gap_disconnect(conn_handle: int, /) bool¶
מנתקת את ידית החיבור שצוינה. זה יכול להיות או התקן central שהתחבר להתקן זה (אם פועל כ-peripheral) או התקן peripheral שהתקן זה התחבר אליו קודם לכן (אם פועל כ-central).
בהצלחה, יופעל אירוע
_IRQ_PERIPHERAL_DISCONNECTאו_IRQ_CENTRAL_DISCONNECT.מחזירה
Falseאם ידית החיבור לא הייתה מחוברת, ו-Trueאחרת.
GATT Server
ל-GATT server יש קבוצה של שירותים רשומים. כל שירות עשוי להכיל מאפיינים, שלכל אחד מהם ערך. מאפיינים יכולים גם להכיל מתארים (descriptors), שלהם עצמם יש ערכים.
ערכים אלה מאוחסנים מקומית, וניגשים אליהם באמצעות ”value handle“ שלהם המחולל במהלך רישום השירות. ניתן גם לקרוא או לכתוב אליהם על ידי התקן לקוח מרוחק. בנוסף, שרת יכול ”להתריע“ (notify) על מאפיין ללקוח מחובר באמצעות ידית חיבור.
התקן בתפקיד central או peripheral יכול לתפקד כ-GATT server, אולם ברוב המקרים יהיה נפוץ יותר שהתקן peripheral יפעל כשרת.
למאפיינים ולמתארים (descriptors) יש גודל מרבי ברירת מחדל של 20 בתים (ברירת המחדל של ATT MTU היא 23 בתים פחות כותרת ATT בת 3 בתים; MTU גדול יותר שהוסכם אינו מעלה כשלעצמו מגבלה זו). כל מה שלקוח יכתוב אליהם יקוצץ לאורך זה. עם זאת, כל כתיבה מקומית תגדיל את הגודל המרבי, כך שאם ברצונכם לאפשר כתיבות גדולות יותר מלקוח למאפיין נתון, השתמשו ב-
gatts_writeלאחר הרישום. למשלgatts_write(char_handle, bytes(100)).- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
מגדירה את השרת עם השירותים שצוינו, ומחליפה שירותים קיימים.
services_definition הוא רשימה של services, שבה כל service הוא tuple בן שני איברים המכיל UUID ורשימה של characteristics.
כל characteristic הוא tuple בן שניים או שלושה איברים המכיל UUID, ערך flags, ואופציונלית רשימה של descriptors.
כל descriptor הוא tuple בן שני איברים המכיל UUID וערך flags.
ה-flags הם שילוב bitwise-OR של הדגלים המוגדרים להלן. הם קובעים הן את התנהגות המאפיין (או המתאר) והן את דרישות האבטחה והפרטיות.
ערך ההחזרה הוא רשימה (איבר אחד לכל שירות) של tuples (כל איבר הוא value handle). ידיות המאפיינים והמתארים משוטחות לאותו tuple, בסדר שבו הן מוגדרות.
הדוגמה הבאה רושמת שני שירותים (Heart Rate ו-Nordic UART):
bt = bluetooth.BLE() bt.active(True) # Heart Rate service: one Heart Rate Measurement characteristic. HR_SERVICE = ( bluetooth.UUID(0x180D), ( (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), ), ) # Nordic UART service: a TX characteristic the client subscribes # to for notifications, and an RX characteristic it writes to. UART_SERVICE = ( bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'), ( (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE), ), ) ((hr,), (tx, rx)) = bt.gatts_register_services( (HR_SERVICE, UART_SERVICE), )
שלוש ידיות הערכים (
hr,tx,rx) יכולות לשמש עםgatts_read,gatts_write,gatts_notifyו-gatts_indicate.הערה: יש להפסיק את הפרסום לפני רישום שירותים.
הדגלים הזמינים עבור מאפיינים ומתארים (descriptors) הם:
קבוע
ערך
משמעות
_FLAG_BROADCAST0x0001ניתן לשדר את המאפיין.
_FLAG_READ0x0002הלקוח רשאי לקרוא את הערך.
_FLAG_WRITE_NO_RESPONSE0x0004הלקוח רשאי לכתוב מבלי לצפות לתגובה.
_FLAG_WRITE0x0008הלקוח רשאי לכתוב עם תגובת אישור.
_FLAG_NOTIFY0x0010השרת רשאי לשלוח התראות (notifications) לא מאושרות.
_FLAG_INDICATE0x0020השרת רשאי לשלוח התרעות (indications) מאושרות.
_FLAG_AUTHENTICATED_SIGNED_WRITE0x0040הלקוח רשאי לבצע כתיבות חתומות.
_FLAG_AUX_WRITE0x0100מאפיינים מורחבים: כתיבות בתור/אמינות מותרות.
_FLAG_READ_ENCRYPTED0x0200קריאה דורשת קישור מוצפן.
_FLAG_READ_AUTHENTICATED0x0400קריאה דורשת קישור מאומת (מוגן MITM).
_FLAG_READ_AUTHORIZED0x0800קריאה דורשת הרשאה ברמת היישום.
_FLAG_WRITE_ENCRYPTED0x1000כתיבה דורשת קישור מוצפן.
_FLAG_WRITE_AUTHENTICATED0x2000כתיבה דורשת קישור מאומת (מוגן MITM).
_FLAG_WRITE_AUTHORIZED0x4000כתיבה דורשת הרשאה ברמת היישום.
כמו עם קבועי האירועים שלמעלה, דגלים אלה אינם מסופקים על ידי מודול
bluetooth; העתיקו לתוכנית שלכם את אלה שאתם צריכים.
- gatts_read(value_handle: int, /) bytes¶
קוראת את הערך המקומי עבור ידית זו (שנכתב או על ידי
gatts_writeאו על ידי לקוח מרוחק).
- gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None¶
כותבת את הערך המקומי עבור ידית זו, שלקוח יכול לקרוא.
אם send_update הוא
True, אזי כל לקוח רשום יקבל התראה (notification) (או התרעה, בהתאם למה שהוא רשום אליו ולאילו פעולות המאפיין תומך) על כתיבה זו.
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
שולחת בקשת התראה (notification) ללקוח מחובר.
אם data הוא
None(ברירת המחדל), אזי יישלח הערך המקומי הנוכחי (כפי שנקבע באמצעותgatts_write).אחרת, אם data אינו
None, אזי ערך זה יישלח ללקוח כחלק מההתראה (notification). הערך המקומי לא ישתנה.הערה: ההתראה (notification) תישלח ללא תלות במצב המינוי (subscription) של הלקוח למאפיין זה.
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
שולחת בקשת התרעה (indication) ללקוח מחובר.
אם data הוא
None(ברירת המחדל), אזי יישלח הערך המקומי הנוכחי (כפי שנקבע באמצעותgatts_write).אחרת, אם data אינו
None, אזי ערך זה יישלח ללקוח כחלק מההתרעה (indication). הערך המקומי לא ישתנה.באישור (או בכשל, למשל timeout), יופעל אירוע
_IRQ_GATTS_INDICATE_DONE.הערה: ההתרעה (indication) תישלח ללא תלות במצב המינוי (subscription) של הלקוח למאפיין זה.
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
קובעת את גודל החוצץ (buffer) הפנימי עבור ערך בבתים. הדבר יגביל את הכתיבה הגדולה ביותר האפשרית שניתן לקבל. ברירת המחדל היא 20 בתים (ברירת מחדל של ATT MTU בת 23 פחות כותרת ATT בת 3 בתים).
קביעת append ל-
Trueתגרום לכל הכתיבות המרוחקות להתווסף לערך הנוכחי במקום להחליפו. ניתן לאגור בחוצץ עד len בתים בדרך זו. כאשר אתם משתמשים ב-gatts_read, הערך ינוקה לאחר הקריאה. תכונה זו שימושית בעת מימוש משהו כמו Nordic UART Service.
GATT Client
GATT client יכול לגלות ולקרוא/לכתוב מאפיינים על GATT server מרוחק.
נפוץ יותר שהתקן בתפקיד central יפעל כ-GATT client, אולם ייתכן גם שהתקן peripheral יפעל כלקוח כדי לגלות מידע על ה-central שהתחבר אליו (למשל לקרוא את שם ההתקן משירות פרטי ההתקן).
- gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None¶
מבצעת שאילתה לשרת מחובר לקבלת שירותיו.
ציינו אופציונלית uuid של שירות כדי לבצע שאילתה לשירות זה בלבד.
עבור כל שירות שמתגלה, יופעל אירוע
_IRQ_GATTC_SERVICE_RESULT, ולאחריו_IRQ_GATTC_SERVICE_DONEבסיום.
- gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None¶
מבצעת שאילתה לשרת מחובר לקבלת מאפיינים בטווח שצוין.
ציינו אופציונלית uuid של מאפיין כדי לבצע שאילתה למאפיין זה בלבד.
העברת
start_handle=1ו-end_handle=0xffffמכסה את טווח ידיות מאפייני ה-GATT המלא, כך ששילוב זה למעשה מחפש בכל שירות בהתקן המרוחק.עבור כל מאפיין שמתגלה, יופעל אירוע
_IRQ_GATTC_CHARACTERISTIC_RESULT, ולאחריו_IRQ_GATTC_CHARACTERISTIC_DONEבסיום.
- gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None¶
מבצעת שאילתה לשרת מחובר לקבלת מתארים (descriptors) בטווח שצוין.
עבור כל מתאר (descriptor) שמתגלה, יופעל אירוע
_IRQ_GATTC_DESCRIPTOR_RESULT, ולאחריו_IRQ_GATTC_DESCRIPTOR_DONEבסיום.
- gattc_read(conn_handle: int, value_handle: int, /) None¶
מבצעת קריאה מרוחקת לשרת מחובר עבור ידית המאפיין או המתאר (descriptor) שצוינה.
כאשר ערך זמין, יופעל אירוע
_IRQ_GATTC_READ_RESULT, ולאחריו_IRQ_GATTC_READ_DONEבסיום.
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
מבצעת כתיבה מרוחקת לשרת מחובר עבור ידית המאפיין או המתאר (descriptor) שצוינה.
הארגומנט mode מציין את התנהגות הכתיבה, כשהערכים הנתמכים כעת הם:
mode=0(ברירת מחדל) הוא כתיבה-ללא-תגובה: הכתיבה תישלח לשרת המרוחק אך לא תוחזר אישור, ולא יופעל אירוע.mode=1הוא כתיבה-עם-תגובה: מתבקש מהשרת המרוחק לשלוח תגובה/אישור על כך שקיבל את הנתונים.
אם מתקבלת תגובה מהשרת המרוחק, יופעל אירוע
_IRQ_GATTC_WRITE_DONE.
- gattc_exchange_mtu(conn_handle: int, /) None¶
יוזמת חילופי MTU עם שרת מחובר, באמצעות ה-MTU המועדף שנקבע באמצעות
BLE.config(mtu=value).אירוע
_IRQ_MTU_EXCHANGEDיופעל כאשר חילופי ה-MTU יושלמו.חילופי MTU מיוזמים בדרך כלל על ידי ה-central; NimBLE תומך בשני התפקידים.
ערוצי L2CAP מוכווני חיבור
תכונה זו מאפשרת חילופי נתונים דמויי socket בין שני התקני BLE. לאחר שההתקנים מחוברים באמצעות GAP, כל אחד מההתקנים יכול להאזין לחיבור של האחר ב-PSM מספרי (Protocol/Service Multiplexer).
רק ערוץ L2CAP אחד יכול להיות פעיל בכל זמן נתון (כלומר, לא ניתן להתחבר בזמן האזנה).
ערוצי L2CAP פעילים מזוהים על ידי ידית החיבור שעליה נוצרו ו-CID (channel ID).
לערוצים מוכווני חיבור יש בקרת זרימה מובנית מבוססת אשראי (credit). בניגוד ל-ATT, שבו ההתקנים מנהלים משא ומתן על MTU משותף, הן ההתקן המאזין והן ההתקן המתחבר קובעים כל אחד MTU עצמאי המגביל את הכמות המרבית של נתונים תלויים ועומדים שההתקן המרוחק יכול לשלוח לפני שהם נצרכים במלואם ב-
l2cap_recvinto.- l2cap_listen(psm: int, mtu: int, /) None¶
מתחילה להאזין לבקשות ערוץ L2CAP נכנסות ב-psm שצוין כאשר ה-MTU המקומי נקבע ל-mtu.
כאשר התקן מרוחק יוזם חיבור, יופעל אירוע
_IRQ_L2CAP_ACCEPT, המעניק לשרת המאזין הזדמנות לדחות את החיבור הנכנס (על ידי החזרת מספר שלם לא-אפס).לאחר שהחיבור מתקבל, יופעל אירוע
_IRQ_L2CAP_CONNECT, המאפשר לשרת לקבל את ה-channel ID (CID) ואת ה-MTU המקומי והמרוחק.הערה: כרגע לא ניתן להפסיק את ההאזנה.
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
מתחברת לעמית מאזין ב-psm שצוין כאשר ה-MTU המקומי נקבע ל-mtu.
בחיבור מוצלח, יופעל אירוע
_IRQ_L2CAP_CONNECT, המאפשר ללקוח לקבל את ה-CID ואת ה-MTU המקומי והמרוחק (peer).חיבור לא מוצלח יפעיל את אירוע
_IRQ_L2CAP_DISCONNECTעם status לא-אפס.
- l2cap_disconnect(conn_handle: int, cid: int, /) None¶
מנתקת ערוץ L2CAP פעיל עם ה-conn_handle וה-cid שצוינו.
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
שולחת את ה-buf שצוין (שחייב לתמוך בפרוטוקול החוצץ (buffer)) בערוץ ה-L2CAP המזוהה על ידי conn_handle ו-cid.
החוצץ (buffer) חייב לעמוד בשתי המגבלות: אסור לו לחרוג מה-MTU המרוחק (peer), ואסור לו לחרוג מפי שניים מה-MTU המקומי.
פעולה זו תחזיר
Falseאם הערוץ נמצא כעת ב“תקיעה“ (stalled), כלומר אסור לקרוא ל-l2cap_sendשוב עד שיתקבל אירוע_IRQ_L2CAP_SEND_READY(שיקרה כאשר ההתקן המרוחק יעניק אשראי (credits) נוסף, בדרך כלל לאחר שקיבל ועיבד את הנתונים).
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
מקבלת נתונים מה-conn_handle וה-cid שצוינו אל תוך ה-buf שסופק (שחייב לתמוך בפרוטוקול החוצץ (buffer), למשל bytearray או memoryview).
מחזירה את מספר הבתים שנקראו מהערוץ.
אם buf הוא
None, אזי מחזירה את מספר הבתים הזמינים.הערה: לאחר קבלת אירוע
_IRQ_L2CAP_RECV, על היישום להמשיך לקרוא ל-l2cap_recvintoעד שלא יישארו בתים זמינים בחוצץ הקבלה (בדרך כלל עד גודל ה-MTU המרוחק (peer)).עד שחוצץ הקבלה ריק, ההתקן המרוחק לא יקבל אשראי (credits) נוסף לערוץ ולא יוכל לשלוח נתונים נוספים.
Pairing ו-Bonding
Pairing מאפשר להצפין ולאמת חיבור באמצעות חילופי סודות (עם הגנת MITM אופציונלית באמצעות אימות passkey).
Bonding הוא תהליך אחסון הסודות הללו באחסון לא-נדיף. כאשר מקושר (bonded), התקן מסוגל לפענח כתובת פרטית הניתנת לפענוח (RPA) מהתקן אחר על בסיס מפתח זיהוי הזהות המאוחסן (IRK). כדי לתמוך ב-Bonding, על היישום לממש את האירועים
_IRQ_GET_SECRETו-_IRQ_SET_SECRET.- gap_pair(conn_handle: int, /) None¶
יוזמת Pairing עם ההתקן המרוחק.
לפני הקריאה לזה, ודאו שאפשרויות התצורה
io,mitm,le_secureו-bondנקבעו (באמצעותconfig).ב-Pairing מוצלח, יופעל אירוע
_IRQ_ENCRYPTION_UPDATE.
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
מגיבה לאירוע
_IRQ_PASSKEY_ACTIONעבור ה-conn_handle וה-action שצוינו. משמעות passkey תלויה ב-action (שבתורו תלוי ביכולת הקלט/פלט שהוגדרה):פעולה
תגובת passkey נדרשת
_PASSKEY_ACTION_INPUTה-passkey שהמשתמש קורא מההתקן המרוחק.
_PASSKEY_ACTION_DISPLAYpasskey אקראי בן 6 ספרות שחולל מקומית ומוצג למשתמש.
_PASSKEY_ACTION_NUMERIC_COMPARISON1כדי לקבל את ה-passkey המוצג באירוע_IRQ_PASSKEY_ACTION, או0כדי לבטל את ה-Pairing.
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
יוצרת מופע UUID עם ה-
valueשצוין. Bluetooth משתמש בשלושה רוחבי UUID;UUIDמקבל כל אחד מהם:רוחב UUID
טיפוסי
valueמקובליםדוגמה
16-bit
intאו חוצץ בן 2 בתים (little-endian)UUID(0x2908)אוUUID(b'\x08\x29')32-bit
חוצץ בן 4 בתים (little-endian)
UUID(b'\x08\x29\x00\x00')128-bit
חוצץ בן 16 בתים או מחרוזת עם מקפים
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')UUIDs בני 16 ו-32 ביט הם בדרך כלל מזהים שהוקצו על ידי ה-SIG (ראו מספרים מוקצים של Bluetooth); UUIDs בני 128 ביט מוגדרים בדרך כלל על ידי הספק.