bluetooth --- 低階藍牙¶
本模組提供了與板載藍牙控制器互動的介面。它支援藍牙低功耗(BLE)的 Central(中央)、Peripheral(周邊)、Broadcaster(廣播者)與 Observer(觀察者)角色,並支援 GATT 伺服器與用戶端以及 L2CAP 連線導向通道。一個裝置可同時以多種角色運作。同時也支援配對(pairing)與綁定(bonding)。
本 API 旨在對應低階藍牙協定,並為更高階的抽象(例如特定裝置類型)提供基礎建構元件。
小訣竅
對於大多數應用程式,建議優先使用更高階的 aioble 函式庫,它在本模組之外提供了以 asyncio 為基礎的封裝。請參閱 aioble --- 非同步 BLE。
class BLE¶
- class bluetooth.BLE¶
傳回單例(singleton)BLE 物件。
組態設定
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
取得或設定 BLE 介面的組態值。要取得某個值時,參數名稱應以字串形式加上引號,且一次只能查詢一個參數。要設定值時則使用關鍵字語法,一次可以設定一個或多個參數。
目前支援的值為:
'mac':目前使用中的位址,取決於目前的位址模式。這會傳回一個(addr_type, addr)元組。關於位址類型的詳細資訊,請參閱
gap_scan。此值只能在介面目前處於啟用狀態時查詢。
'addr_mode':設定位址模式。可用的值為:值
名稱
行為
0x00PUBLIC
使用控制器的公開位址。
0x01RANDOM
使用產生的靜態位址。
0x02RPA
使用可解析的私有位址。
0x03NRPA
使用不可解析的私有位址。
預設情況下,介面會在可用時使用 PUBLIC 位址,否則會使用 RANDOM 位址。
'gap_name':取得/設定由 Generic Access 服務(UUID0x1800)的 Device Name 特徵(characteristic,UUID0x2a00)所使用的 GAP 裝置名稱。此值可隨時設定並可多次變更。'rxbuf':取得/設定用於儲存傳入事件的內部緩衝區大小(以位元組為單位)。此緩衝區對整個 BLE 驅動程式是全域的,因此會處理所有事件的傳入資料,包括所有特徵的資料。增大此值可更妥善地處理突發性的傳入資料(例如掃描結果),並能接收較大的特徵值。'mtu':取得/設定在 ATT MTU 交換期間將使用的 MTU。最終的 MTU 會是此值與遠端裝置 MTU 兩者中的較小值。ATT MTU 交換不會自動發生(除非遠端裝置主動發起),必須以gattc_exchange_mtu手動發起。請使用_IRQ_MTU_EXCHANGED事件來得知某個連線的 MTU。'bond':設定配對期間是否啟用綁定。啟用後,配對請求會設定「bond」旗標,且兩個裝置都會儲存金鑰。'mitm':設定配對是否需要 MITM 防護。'io':設定本裝置的 I/O 能力。可用的選項有:
常數
值
能力
_IO_CAPABILITY_DISPLAY_ONLY0
僅顯示
_IO_CAPABILITY_DISPLAY_YESNO1
顯示並具有是/否輸入
_IO_CAPABILITY_KEYBOARD_ONLY2
僅鍵盤
_IO_CAPABILITY_NO_INPUT_OUTPUT3
無輸入或輸出
_IO_CAPABILITY_KEYBOARD_DISPLAY4
鍵盤與顯示
'le_secure':設定是否需要「LE Secure」配對。預設為 false(亦即允許「Legacy Pairing」)。
事件處理
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
為來自 BLE 協定堆疊的事件註冊回呼函式。handler 接受兩個引數:
event(會是下列其中一個代碼)與data(是一個特定於該事件的值元組)。注意: 為了最佳化以避免不必要的記憶體配置,元組中的
addr、adv_data、char_data、notify_data與uuid項目都是唯讀的 memoryview 實例,指向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))。處理函式通常會根據事件代碼進行分派,並解開特定於該事件的酬載元組::
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,失敗時則為一個與實作相關的非零值。常數
值
事件
酬載元組
_IRQ_CENTRAL_CONNECT1
有一個 central 已連線至此 peripheral。
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
有一個 central 已從此 peripheral 斷線。
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
已連線的用戶端已寫入本機的某個特徵或描述子。請使用
gatts_read來取得新的值。(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
已連線的用戶端發出了一個讀取請求。從下表傳回一個非零的錯誤代碼以拒絕讀取,或傳回
0/None以接受。(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
在主動掃描期間收到了一個廣播封包。
(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
gattc_discover_descriptors找到了一個描述子。(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
描述子探索已完成。
(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
遠端伺服器已傳送一個(未確認的)通知。
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
遠端伺服器已傳送一個(已確認的)指示。
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
先前傳送的指示已獲得用戶端確認(或已逾時)。
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
一次 ATT MTU 交換已完成(由任一方發起)。
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
遠端裝置已在本裝置正在監聽的某個 PSM 上請求 L2CAP 連線。傳回非零整數以拒絕,或傳回
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
先前傳回
False的l2cap_send已排空,通道現已再次就緒。非零的status表示傳輸緩衝區發生溢位,應用程式必須重新傳送該資料。(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
遠端裝置已更新連線參數(interval、latency、supervision timeout)。
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
連線的加密狀態已變更,通常是在配對或綁定完成之後。
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
協定堆疊正在請求一個已儲存的綁定密鑰。如果
key為None,則傳回sec_type中第index個已儲存的值;否則傳回與給定的(sec_type, key)相關聯的值。若沒有儲存任何內容,則傳回None。(sec_type, index, key)_IRQ_SET_SECRET30
協定堆疊正要求應用程式將一個綁定密鑰持久化儲存。儲存完成後傳回
True。(sec_type, key, value)_IRQ_PASSKEY_ACTION31
配對過程中需要一個密碼金鑰(passkey)動作。請使用
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_ACTION_DISPLAY3
顯示一組 6 位數的密碼金鑰供遠端裝置輸入。
_PASSKEY_ACTION_NUMERIC_COMPARISON4
確認密碼金鑰與遠端裝置上顯示的相符。
為了節省韌體空間,這些常數並未包含在
bluetooth模組中。請從上方列表中將你需要的常數加入你的程式。
Broadcaster 角色(廣播者)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
以指定的間隔(以微秒為單位)開始廣播。此間隔會向下取整至最接近的 625us。要停止廣播,請將 interval_us 設為
None。adv_data 與 resp_data 可以是任何實作緩衝區協定的類型(例如
bytes、bytearray、str)。adv_data 會包含在所有廣播中,而 resp_data 則會在回應主動掃描時傳送。注意: 如果 adv_data(或 resp_data)為
None,則會重複使用上一次呼叫gap_advertise時傳入的資料。這讓廣播者只需以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)。掃描者會每隔 interval_us 微秒執行 window_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的值對應於藍牙規格:值
名稱
意義
0x00ADV_IND
可連線且可掃描的非定向廣播。
0x01ADV_DIRECT_IND
可連線的定向廣播。
0x02ADV_SCAN_IND
可掃描的非定向廣播。
0x03ADV_NONCONN_IND
不可連線的非定向廣播。
0x04SCAN_RSP
掃描回應。
如果你希望在結果中接收掃描回應,可將
active設為True。當掃描停止時(無論是因為持續時間結束或被明確停止),都會引發
_IRQ_SCAN_DONE事件。
Central 角色
central 裝置可以連線至它使用 observer 角色(參閱
gap_scan)所探索到的 peripheral,或是連線至已知位址的 peripheral。- 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 的時間以接收來自該裝置的廣播酬載。
連線間隔(connection interval)可使用 min_conn_interval_us 與 max_conn_interval_us 其中之一或兩者以微秒為單位設定。否則會選擇一個預設間隔,通常介於 30000 至 50000 微秒之間。較短的間隔會提高吞吐量,但代價是耗電量增加。
Peripheral 角色
peripheral 裝置應傳送可連線的廣播(參閱
gap_advertise)。它通常會作為 GATT 伺服器運作,並會先使用gatts_register_services註冊服務與特徵。當一個 central 連線時,會引發
_IRQ_CENTRAL_CONNECT事件。Central 與 Peripheral 角色
- gap_disconnect(conn_handle: int, /) bool¶
中斷指定連線控制代碼(connection handle)的連線。它可以是一個連線到本裝置的 central(若本裝置作為 peripheral),或是一個先前由本裝置連線的 peripheral(若本裝置作為 central)。
成功時會引發
_IRQ_PERIPHERAL_DISCONNECT或_IRQ_CENTRAL_DISCONNECT事件。如果該連線控制代碼並未連線,則傳回
False,否則傳回True。
GATT 伺服器
GATT 伺服器擁有一組已註冊的服務。每個服務可包含特徵,而每個特徵都有一個值。特徵也可以包含描述子,描述子本身也有值。
這些值儲存在本機,並透過其在服務註冊期間產生的「value handle」來存取。它們也可由遠端的用戶端裝置讀取或寫入。此外,伺服器可透過連線控制代碼向已連線的用戶端「通知」某個特徵。
處於 central 或 peripheral 角色的裝置都可以作為 GATT 伺服器運作,不過在大多數情況下,較常見的是由 peripheral 裝置作為伺服器。
特徵與描述子的預設最大大小為 20 個位元組(預設的 ATT MTU 為 23 個位元組,減去 3 個位元組的 ATT 標頭;協商出較大的 MTU 本身並不會提高此上限)。用戶端寫入的任何內容都會被截斷至此長度。然而,任何本機寫入都會增大其最大大小,因此若你想允許用戶端對某個特徵進行較大的寫入,請在註冊後使用
gatts_write,例如gatts_write(char_handle, bytes(100))。- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
以指定的服務設定伺服器,並取代任何現有的服務。
services_definition 是一個由 services 組成的清單,其中每個 service 都是一個兩元素的元組,包含一個 UUID 與一個 characteristics 清單。
每個 characteristic 都是一個兩元素或三元素的元組,包含一個 UUID、一個 flags 值,以及一個可選的 descriptors 清單。
每個 descriptor 都是一個兩元素的元組,包含一個 UUID 與一個 flags 值。
flags 是下面所定義旗標的位元 OR 組合。它們同時設定特徵(或描述子)的行為以及安全性與隱私需求。
傳回值是一個清單(每個服務一個元素),其元素為元組(每個元素都是一個 value handle)。特徵與描述子的控制代碼會依其定義順序被攤平到同一個元組中。
下列範例註冊了兩個服務(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), )
三個 value handle(
hr、tx、rx)可搭配gatts_read、gatts_write、gatts_notify與gatts_indicate使用。注意: 註冊服務前必須先停止廣播。
特徵與描述子可用的旗標為:
常數
值
意義
_FLAG_BROADCAST0x0001特徵可被廣播。
_FLAG_READ0x0002用戶端可讀取該值。
_FLAG_WRITE_NO_RESPONSE0x0004用戶端可寫入而不期望回應。
_FLAG_WRITE0x0008用戶端可進行帶有確認回應的寫入。
_FLAG_NOTIFY0x0010伺服器可傳送通知(未確認)。
_FLAG_INDICATE0x0020伺服器可傳送指示(已確認)。
_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,則任何已訂閱的用戶端都會收到關於此寫入的通知(或指示,取決於它們訂閱的內容以及該特徵支援哪些操作)。
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
向已連線的用戶端傳送一個通知請求。
如果 data 為
None(預設值),則會傳送目前的本機值(即以gatts_write設定的值)。否則,如果 data 不為
None,則該值會作為通知的一部分傳送給用戶端。本機值不會被修改。注意: 無論用戶端對此特徵的訂閱狀態為何,通知都會被傳送。
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
向已連線的用戶端傳送一個指示請求。
如果 data 為
None(預設值),則會傳送目前的本機值(即以gatts_write設定的值)。否則,如果 data 不為
None,則該值會作為指示的一部分傳送給用戶端。本機值不會被修改。在獲得確認(或失敗,例如逾時)時,會引發
_IRQ_GATTS_INDICATE_DONE事件。注意: 無論用戶端對此特徵的訂閱狀態為何,指示都會被傳送。
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
設定某個值的內部緩衝區大小(以位元組為單位)。這會限制可接收的最大寫入量。預設為 20 個位元組(預設的 ATT MTU 為 23,減去 3 個位元組的 ATT 標頭)。
將 append 設為
True會使所有遠端寫入以附加方式加入目前的值,而非取代它。以此方式最多可緩衝 len 個位元組。當你使用gatts_read時,讀取後該值會被清除。此功能在實作類似 Nordic UART Service 之類的東西時很有用。
GATT 用戶端
GATT 用戶端可以探索並讀取/寫入遠端 GATT 伺服器上的特徵。
較常見的是由 central 角色的裝置作為 GATT 用戶端,不過 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¶
向已連線的伺服器查詢指定範圍內的描述子。
對於每個探索到的描述子,都會引發
_IRQ_GATTC_DESCRIPTOR_RESULT事件,並在完成時引發_IRQ_GATTC_DESCRIPTOR_DONE。
- gattc_read(conn_handle: int, value_handle: int, /) None¶
向已連線的伺服器發出對指定特徵或描述子控制代碼的遠端讀取。
當有值可用時,會引發
_IRQ_GATTC_READ_RESULT事件,並在完成時引發_IRQ_GATTC_READ_DONE。
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
向已連線的伺服器發出對指定特徵或描述子控制代碼的遠端寫入。
引數 mode 指定寫入行為,目前支援的值為:
mode=0(預設)是不帶回應的寫入:寫入會傳送至遠端伺服器,但不會傳回任何確認,也不會引發任何事件。mode=1是帶回應的寫入:會要求遠端伺服器傳送一個回應/確認,表示它已收到資料。
如果收到來自遠端伺服器的回應,會引發
_IRQ_GATTC_WRITE_DONE事件。
- gattc_exchange_mtu(conn_handle: int, /) None¶
與已連線的伺服器發起 MTU 交換,使用以
BLE.config(mtu=value)設定的偏好 MTU。當 MTU 交換完成時,會引發
_IRQ_MTU_EXCHANGED事件。MTU 交換通常由 central 發起;NimBLE 支援兩種角色。
L2CAP 連線導向通道
此功能允許兩個 BLE 裝置之間進行類似 socket 的資料交換。一旦裝置透過 GAP 連線後,任一裝置都可以在一個數值型 PSM(Protocol/Service Multiplexer,協定/服務多工器)上監聽另一個裝置的連線。
同一時間只能有一個 L2CAP 通道處於啟用狀態(亦即你無法在監聽的同時進行連線)。
啟用中的 L2CAP 通道是以其建立所在的連線控制代碼以及一個 CID(通道 ID)來識別。
連線導向通道具有內建的信用額度式(credit-based)流量控制。與 ATT 不同(裝置在 ATT 中會協商一個共用的 MTU),監聽端與連線端裝置各自設定一個獨立的 MTU,用以限制在
l2cap_recvinto完全消耗之前,遠端裝置最多可傳送的未處理資料量。- l2cap_listen(psm: int, mtu: int, /) None¶
開始在指定的 psm 上監聽傳入的 L2CAP 通道請求,並將本機 MTU 設為 mtu。
當遠端裝置發起連線時,會引發
_IRQ_L2CAP_ACCEPT事件,這讓監聽伺服器有機會拒絕該傳入連線(透過傳回一個非零整數)。一旦連線被接受,會引發
_IRQ_L2CAP_CONNECT事件,讓伺服器能取得通道 ID(CID)以及本機與遠端的 MTU。注意: 目前無法停止監聽。
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
在指定的 psm 上連線至一個正在監聽的對等端(peer),並將本機 MTU 設為 mtu。
連線成功時,會引發
_IRQ_L2CAP_CONNECT事件,讓用戶端能取得 CID 以及本機與遠端(對等端)的 MTU。連線失敗時,會引發帶有非零 status 的
_IRQ_L2CAP_DISCONNECT事件。
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
在以 conn_handle 與 cid 識別的 L2CAP 通道上傳送指定的 buf(其必須支援緩衝區協定)。
緩衝區必須同時滿足兩項限制:它不得超過遠端(對等端)MTU,且不得超過本機 MTU 的兩倍。
如果通道現已「停滯(stalled)」,這會傳回
False,意思是在收到_IRQ_L2CAP_SEND_READY事件之前不得再次呼叫l2cap_send(該事件會在遠端裝置授予更多信用額度時發生,通常是在它接收並處理完資料之後)。
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
從指定的 conn_handle 與 cid 接收資料到所提供的 buf(其必須支援緩衝區協定,例如 bytearray 或 memoryview)中。
傳回從通道讀取的位元組數。
如果 buf 為
None,則傳回可用的位元組數。注意: 在收到
_IRQ_L2CAP_RECV事件後,應用程式應持續呼叫l2cap_recvinto,直到接收緩衝區中沒有更多可用的位元組為止(通常最多為遠端(對等端)MTU 的大小)。在接收緩衝區清空之前,遠端裝置不會獲得更多通道信用額度,因而無法再傳送任何資料。
配對與綁定
配對讓連線能夠透過交換密鑰而被加密與驗證(可選擇透過密碼金鑰驗證來提供 MITM 防護)。
綁定是將那些密鑰儲存到非揮發性儲存空間的過程。綁定後,裝置便能根據已儲存的識別解析金鑰(IRK)解析來自另一裝置的可解析私有位址(RPA)。為了支援綁定,應用程式必須實作
_IRQ_GET_SECRET與_IRQ_SET_SECRET事件。- gap_pair(conn_handle: int, /) None¶
與遠端裝置發起配對。
在呼叫此方法之前,請確保已設定
io、mitm、le_secure與bond組態選項(透過config)。配對成功時,會引發
_IRQ_ENCRYPTION_UPDATE事件。
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
針對指定的 conn_handle 與 action 回應一個
_IRQ_PASSKEY_ACTION事件。passkey 的意義取決於 action(而 action 又取決於所設定的 I/O 能力):動作
所需的 passkey 回應
_PASSKEY_ACTION_INPUT使用者從遠端裝置讀取到的密碼金鑰。
_PASSKEY_ACTION_DISPLAY在本機產生並顯示給使用者的隨機 6 位數密碼金鑰。
_PASSKEY_ACTION_NUMERIC_COMPARISON傳回
1以接受_IRQ_PASSKEY_ACTION事件中顯示的密碼金鑰,或傳回0以取消配對。
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
以指定的
value建立一個 UUID 實例。藍牙使用三種 UUID 寬度;UUID接受其中任何一種:UUID 寬度
可接受的
value類型範例
16 位元
int或一個 2 位元組緩衝區(小端序)UUID(0x2908)或UUID(b'\x08\x29')32 位元
4 位元組緩衝區(小端序)
UUID(b'\x08\x29\x00\x00')128 位元
16 位元組緩衝區或一個帶連字號的字串
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')16 位元與 32 位元 UUID 通常是 SIG 分配的識別碼(參閱 Bluetooth 分配編號);128 位元 UUID 通常由廠商自行定義。