前面的MicroPython版本有個不小的缺陷,就是無法使用藍牙模塊。ESP32的一個巨大優勢就是將藍牙和WIFI集成到了一塊芯片上,沒有藍牙功能無疑是個巨大的損失。現在已經有一個版本已經支持藍牙開發了,這裏簡單介紹一下如何使用藍牙模塊。
最新的版本:
bluetooth
— 低級藍牙
該模塊爲板上的藍牙控制器提供接口。目前,這支持中央、外設、廣播和觀察者角色的低功耗藍牙 (BLE),以及 GATT 服務器和客戶端以及 L2CAP 面向連接的通道。一個設備可以同時扮演多個角色。某些端口支持配對(和綁定)。
此 API 旨在匹配低級藍牙協議,併爲更高級別的抽象(例如特定設備類型)提供構建塊。
筆記
該模塊仍在開發中,其類、函數、方法和常量可能會發生變化。
低功耗等級
構造函數
class bluetooth.
BLE
返回單例 BLE 對象。
配置
BLE.
active
([active, ]/)
可選擇更改 BLE 無線電的活動狀態,並返回當前狀態。
在使用此類上的任何其他方法之前,必須使無線電處於活動狀態。
BLE.
config
('param', /)
BLE.
config
(*, param=value, ...)
獲取或設置 BLE 接口的配置值。要獲得一個值,參數名稱應該被引用爲一個字符串,並且一次只查詢一個參數。要設置值,請使用關鍵字語法,並且一次可以設置一個或多個參數。
當前支持的值是:
-
'mac'
: 當前使用的地址,取決於當前地址模式。這將返回一個元組。(addr_type, addr)
.gatts_write
有關地址類型的詳細信息,請參閱。這隻能在接口當前處於活動狀態時查詢。
-
'addr_mode'
: 設置地址模式。值可以是:-
0x00 - PUBLIC - 使用控制器的公共地址。
-
0x01 - RANDOM - 使用生成的靜態地址。
-
0x02 - RPA - 使用可解析的私有地址。
-
0x03 - NRPA - 使用不可解析的私有地址。
默認情況下,如果可用,接口模式將使用 PUBLIC 地址,否則將使用 RANDOM 地址。
-
-
'gap_name'
: 獲取/設置服務0x1800使用的GAP設備名稱,特徵0x2a00。這可以隨時設置並多次更改。 -
'rxbuf'
: 獲取/設置用於存儲傳入事件的內部緩衝區的大小(以字節爲單位)。該緩衝區對整個 BLE 驅動程序是全局的,因此處理所有事件的傳入數據,包括所有特徵。增加此值可以更好地處理突發傳入數據(例如掃描結果)和接收更大特徵值的能力。 -
'mtu'
:獲取/設置將在 ATT MTU 交換期間使用的 MTU。生成的 MTU 將是該 MTU 和遠程設備的 MTU 中的最小值。ATT MTU 交換不會自動發生(除非遠程設備啓動它),必須手動啓動gattc_exchange_mtu
。使用該_IRQ_MTU_EXCHANGED
事件來發現給定連接的 MTU。 -
'bond'
: 設置配對時是否啓用綁定。啓用後,配對請求將設置“綁定”標誌,並且密鑰將由兩個設備存儲。 -
'mitm'
:設置配對是否需要 MITM 保護。 -
'io'
: 設置此設備的 I/O 功能。可用選項有:
_IO_CAPABILITY_DISPLAY_ONLY = const(0) _IO_CAPABILITY_DISPLAY_YESNO = const(1) _IO_CAPABILITY_KEYBOARD_ONLY = const(2) _IO_CAPABILITY_NO_INPUT_OUTPUT = const(3) _IO_CAPABILITY_KEYBOARD_DISPLAY = const(4)
-
'le_secure'
: 設置是否需要“LE Secure”配對。默認爲 false(即允許“傳統配對”)。
事件處理
BLE.
irq
(handler, /)
爲來自 BLE 堆棧的事件註冊回調。的處理程序採用兩個參數,event
(這將在下面的代碼中的一個)和data
(其是值的特定事件元組)。
注:作爲一種優化,以防止不必要的配發,addr
, adv_data
, char_data
, notify_data
, 和 uuid
在元組的條目是隻讀的指向memoryview實例 bluetooth
的內部ringbuffer,並且僅在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: # A central has connected to this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_CENTRAL_DISCONNECT: # A central has disconnected from this peripheral. conn_handle, addr_type, addr = data elif event == _IRQ_GATTS_WRITE: # A client has written to this characteristic or descriptor. conn_handle, attr_handle = data elif event == _IRQ_GATTS_READ_REQUEST: # A client has issued a read. Note: this is only supported on STM32. # Return a non-zero integer to deny the read (see below), or zero (or None) # to accept the read. conn_handle, attr_handle = data elif event == _IRQ_SCAN_RESULT: # A single scan result. addr_type, addr, adv_type, rssi, adv_data = data elif event == _IRQ_SCAN_DONE: # Scan duration finished or manually stopped. pass elif event == _IRQ_PERIPHERAL_CONNECT: # A successful gap_connect(). conn_handle, addr_type, addr = data elif event == _IRQ_PERIPHERAL_DISCONNECT: # Connected peripheral has disconnected. conn_handle, addr_type, addr = data elif event == _IRQ_GATTC_SERVICE_RESULT: # Called for each service found by gattc_discover_services(). conn_handle, start_handle, end_handle, uuid = data elif event == _IRQ_GATTC_SERVICE_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). conn_handle, def_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_DESCRIPTOR_RESULT: # Called for each descriptor found by gattc_discover_descriptors(). conn_handle, dsc_handle, uuid = data elif event == _IRQ_GATTC_DESCRIPTOR_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, status = data elif event == _IRQ_GATTC_READ_RESULT: # A gattc_read() has completed. conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_READ_DONE: # A gattc_read() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_WRITE_DONE: # A gattc_write() has completed. # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: # A server has sent a notify request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTC_INDICATE: # A server has sent an indicate request. conn_handle, value_handle, notify_data = data elif event == _IRQ_GATTS_INDICATE_DONE: # A client has acknowledged the indication. # Note: Status will be zero on successful acknowledgment, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_MTU_EXCHANGED: # ATT MTU exchange complete (either initiated by us or the remote device). conn_handle, mtu = data elif event == _IRQ_L2CAP_ACCEPT: # A new channel has been accepted. # Return a non-zero integer to reject the connection, or zero (or None) to accept. conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_CONNECT: # A new channel is now connected (either as a result of connecting or accepting). conn_handle, cid, psm, our_mtu, peer_mtu = data elif event == _IRQ_L2CAP_DISCONNECT: # Existing channel has disconnected (status is zero), or a connection attempt failed (non-zero status). conn_handle, cid, psm, status = data elif event == _IRQ_L2CAP_RECV: # New data is available on the channel. Use l2cap_recvinto to read. conn_handle, cid = data elif event == _IRQ_L2CAP_SEND_READY: # A previous l2cap_send that returned False has now completed and the channel is ready to send again. # If status is non-zero, then the transmit buffer overflowed and the application should re-send the data. conn_handle, cid, status = data elif event == _IRQ_CONNECTION_UPDATE: # The remote device has updated connection parameters. conn_handle, conn_interval, conn_latency, supervision_timeout, status = data elif event == _IRQ_ENCRYPTION_UPDATE: # The encryption state has changed (likely as a result of pairing or bonding). conn_handle, encrypted, authenticated, bonded, key_size = data elif event == _IRQ_GET_SECRET: # Return a stored secret. # If key is None, return the index'th value of this sec_type. # Otherwise return the corresponding value for this sec_type and key. sec_type, index, key = data return value elif event == _IRQ_SET_SECRET: # Save a secret to the store for this sec_type and key. sec_type, key, value = data return True elif event == _IRQ_PASSKEY_ACTION: # Respond to a passkey request during pairing. # See gap_passkey() for details. # action will be an action that is compatible with the configured "io" config. # passkey will be non-zero if action is "numeric comparison". conn_handle, action, passkey = data
事件代碼是:
from micropython import const _IRQ_CENTRAL_CONNECT = const(1) _IRQ_CENTRAL_DISCONNECT = const(2) _IRQ_GATTS_WRITE = const(3) _IRQ_GATTS_READ_REQUEST = const(4) _IRQ_SCAN_RESULT = const(5) _IRQ_SCAN_DONE = const(6) _IRQ_PERIPHERAL_CONNECT = const(7) _IRQ_PERIPHERAL_DISCONNECT = const(8) _IRQ_GATTC_SERVICE_RESULT = const(9) _IRQ_GATTC_SERVICE_DONE = const(10) _IRQ_GATTC_CHARACTERISTIC_RESULT = const(11) _IRQ_GATTC_CHARACTERISTIC_DONE = const(12) _IRQ_GATTC_DESCRIPTOR_RESULT = const(13) _IRQ_GATTC_DESCRIPTOR_DONE = const(14) _IRQ_GATTC_READ_RESULT = const(15) _IRQ_GATTC_READ_DONE = const(16) _IRQ_GATTC_WRITE_DONE = const(17) _IRQ_GATTC_NOTIFY = const(18) _IRQ_GATTC_INDICATE = const(19) _IRQ_GATTS_INDICATE_DONE = const(20) _IRQ_MTU_EXCHANGED = const(21) _IRQ_L2CAP_ACCEPT = const(22) _IRQ_L2CAP_CONNECT = const(23) _IRQ_L2CAP_DISCONNECT = const(24) _IRQ_L2CAP_RECV = const(25) _IRQ_L2CAP_SEND_READY = const(26) _IRQ_CONNECTION_UPDATE = const(27) _IRQ_ENCRYPTION_UPDATE = const(28) _IRQ_GET_SECRET = const(29) _IRQ_SET_SECRET = const(30)
對於該_IRQ_GATTS_READ_REQUEST
事件,可用的返回代碼爲:
_GATTS_NO_ERROR = const(0x00) _GATTS_ERROR_READ_NOT_PERMITTED = const(0x02) _GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03) _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05) _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08) _GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f)
對於_IRQ_PASSKEY_ACTION
事件,可用的操作是:
_PASSKEY_ACTION_NONE = const(0) _PASSKEY_ACTION_INPUT = const(2) _PASSKEY_ACTION_DISPLAY = const(3) _PASSKEY_ACTION_NUMERIC_COMPARISON = const(4)
爲了節省固件空間,這些常量不包含在 bluetooth
模塊中。將上面列表中您需要的那些添加到您的程序中。
廣播員角色(廣告商)
BLE.
gap_advertise
(interval_us, adv_data=None, *, resp_data=None, connectable=True)
以指定的時間間隔(以微秒爲單位)開始廣告。此間隔將向下舍入到最接近的 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''
。
觀察者角色(掃描儀)
BLE.
gap_scan
(duration_ms, interval_us=1280000, window_us=11250, active=False, /)
運行持續指定持續時間(以毫秒爲單位)的掃描操作。
要無限期掃描,請將duration_ms設置爲0
.
要停止掃描,請將duration_ms設置爲 None
.
使用interval_us和window_us可選擇配置佔空比。掃描器將每interval_us微秒運行window_us 微秒,總共持續duration_ms毫秒。默認間隔和窗口分別爲 1.28 秒和 11.25 毫秒(後臺掃描)。
對於每個掃描結果,_IRQ_SCAN_RESULT
將引發事件,並帶有事件數據。(addr_type, addr, adv_type, rssi, adv_data)
.
addr_type
值表示公共或隨機地址:
-
0x00 - 公共
-
0x01 - RANDOM (靜態、RPA 或 NRPA,類型在地址本身中編碼)
adv_type
值對應於藍牙規範:
0x00 - ADV_IND - 可連接和可掃描的無向廣告
0x01 - ADV_DIRECT_IND - 可連接的定向廣告
0x02 - ADV_SCAN_IND - 可掃描的無向廣告
0x03 - ADV_NONCONN_IND - 不可連接的無向廣告
0x04 - SCAN_RSP - 掃描響應
active
True
如果要在結果中接收掃描響應,可以設置。
當掃描停止時(由於持續時間完成或明確停止),_IRQ_SCAN_DONE
將引發該事件。
核心角色
中央設備可以使用觀察者角色(參見 參考資料 gap_scan
)或已知地址連接到它發現的外圍設備。
BLE.
gap_connect
(addr_type, addr, scan_duration_ms=2000, /)
連接到外圍設備。
See gap_scan
有關地址類型的詳細信息,請參閱。
成功後,_IRQ_PERIPHERAL_CONNECT
將引發該事件。
外圍角色
外圍設備應發送可連接的廣告(請參閱 參考資料 gap_advertise
)。它通常充當 GATT 服務器,首先使用 gatts_register_services
.
當中心連接時, _IRQ_CENTRAL_CONNECT
將引發該事件。
中心和外圍角色
BLE.
gap_disconnect
(conn_handle, /)
斷開指定的連接句柄。這可以是已連接到該設備的中央設備(如果充當外圍設備),也可以是之前由該設備連接的外圍設備(如果充當中央設備)。
成功時, 將引發_IRQ_PERIPHERAL_DISCONNECT
或 _IRQ_CENTRAL_DISCONNECT
事件。
False
如果連接句柄未連接,True
則返回,否則返回。
關貿總協定服務器
GATT 服務器有一組註冊服務。每個服務可能包含特性,每個特性都有一個值。特徵還可以包含描述符,描述符本身具有值。
這些值存儲在本地,並由服務註冊期間生成的“值句柄”訪問。它們也可以從遠程客戶端設備讀取或寫入。此外,服務器可以通過連接句柄向連接的客戶端“通知”特徵。
處於中央或外圍角色的設備可以充當 GATT 服務器,但在大多數情況下,外圍設備充當服務器更爲常見。
特徵和描述符的默認最大大小爲 20 字節。客戶寫給他們的任何東西都將被截斷到這個長度。但是,任何本地寫入都會增加最大大小,因此如果您希望允許從客戶端對給定特性進行更大的寫入,請 gatts_write
在註冊後使用 。例如 。 gatts_write(char_handle, bytes(100))
.
BLE.
gatts_register_services
(services_definition, /)
使用指定的服務配置服務器,替換任何現有服務。
services_definition是列表服務,其中每個服務是包含UUID和列表的兩個元素的元組的特性。
每個特性都是一個包含 UUID、標誌值和可選的描述符列表的二或三元素元組 。
每個描述符都是一個包含 UUID 和標誌 值的兩元素元組。
這些標誌是下面定義的標誌的按位或組合。這些設置了特徵(或描述符)的行爲以及安全和隱私要求。
返回值是一個元組列表(每個服務一個元素)(每個元素是一個值句柄)。特徵和描述符句柄按照定義的順序平展爲同一個元組。
以下示例註冊了兩個服務(Heart Rate 和 Nordic UART):
HR_UUID = bluetooth.UUID(0x180D) HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) HR_SERVICE = (HR_UUID, (HR_CHAR,),) UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),) SERVICES = (HR_SERVICE, UART_SERVICE,) ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES)
這三個值手柄(hr
, tx
, rx
)可與使用 gatts_read
, gatts_write
, gatts_notify
和 gatts_indicate
。
注意: 在註冊服務之前必須停止廣告。
特徵和描述符的可用標誌是:
from micropython import const _FLAG_BROADCAST = const(0x0001) _FLAG_READ = const(0x0002) _FLAG_WRITE_NO_RESPONSE = const(0x0004) _FLAG_WRITE = const(0x0008) _FLAG_NOTIFY = const(0x0010) _FLAG_INDICATE = const(0x0020) _FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040) _FLAG_AUX_WRITE = const(0x0100) _FLAG_READ_ENCRYPTED = const(0x0200) _FLAG_READ_AUTHENTICATED = const(0x0400) _FLAG_READ_AUTHORIZED = const(0x0800) _FLAG_WRITE_ENCRYPTED = const(0x1000) _FLAG_WRITE_AUTHENTICATED = const(0x2000) _FLAG_WRITE_AUTHORIZED = const(0x4000)
至於上面的 IRQ,任何需要的常量都應該添加到你的 Python 代碼中。
BLE.
gatts_read
(value_handle, /)
讀取此句柄的本地值(已由 gatts_write
遠程客戶端寫入或由遠程客戶端寫入 )。
BLE.
gatts_write
(value_handle, data, send_update=False, /)
寫入此句柄的本地值,客戶端可以讀取該值。
如果send_update是True
,則任何訂閱的客戶端都將收到有關此寫入的通知(或指示,具體取決於他們訂閱的內容和特徵支持的操作)。
BLE.
gatts_notify
(conn_handle, value_handle, data=None, /)
向連接的客戶端發送通知請求。
如果data不是None
,則該值將作爲通知的一部分發送給客戶端。本地值不會被修改。
否則,如果data是None
,則將發送當前本地值(使用 設置gatts_write
) 。
注意: 無論客戶端對此特性的訂閱狀態如何,都會發送通知。
BLE.
gatts_indicate
(conn_handle, value_handle, /)
向連接的客戶端發送包含特徵當前值的指示請求。
在確認(或失敗,例如超時)時, _IRQ_GATTS_INDICATE_DONE
將引發該 事件。
注意: 無論客戶端對此特性的訂閱狀態如何,都會發送指示。
BLE.
gatts_set_buffer
(value_handle, len, append=False, /)
以字節爲單位設置值的內部緩衝區大小。這將限制可以接收的最大可能寫入。默認值爲 20。
設置append toTrue
將使所有遠程寫入附加到當前值,而不是替換當前值。在大多數LEN字節可以用這種方式進行緩衝。當您使用 時gatts_read
,讀取後該值將被清除。在實現類似 Nordic UART 服務之類的功能時,此功能很有用。
關貿總協定客戶端
GATT 客戶端可以發現和讀取/寫入遠程 GATT 服務器上的特性。
中央角色設備充當 GATT 客戶端更爲常見,但是外圍設備也可以充當客戶端,以發現有關已連接到它的中央角色的信息(例如,從設備信息服務)。
BLE.
gattc_discover_services
(conn_handle, uuid=None, /)
查詢已連接服務器的服務。
(可選)指定服務uuid以僅查詢該服務。
對於發現的每個服務, _IRQ_GATTC_SERVICE_RESULT
將引發事件,然後是_IRQ_GATTC_SERVICE_DONE
完成。
BLE.
gattc_discover_characteristics
(conn_handle, start_handle, end_handle, uuid=None, /)
查詢連接的服務器以獲取指定範圍內的特徵。
可選)指定一個特徵uuid以僅查詢該特徵。
您可以使用start_handle=1
, end_handle=0xffff
在任何服務中搜索特徵。
對於發現的每個特徵, _IRQ_GATTC_CHARACTERISTIC_RESULT
將引發事件,然後是 _IRQ_GATTC_CHARACTERISTIC_DONE
完成。
BLE.
gattc_discover_descriptors
(conn_handle, start_handle, end_handle, /)
向連接的服務器查詢指定範圍內的描述符。
對於發現的每個描述符,_IRQ_GATTC_DESCRIPTOR_RESULT
將引發事件,然後_IRQ_GATTC_DESCRIPTOR_DONE
在完成時引發。
BLE.
gattc_read
(conn_handle, value_handle, /)
爲指定的特徵或描述符句柄向連接的服務器發出遠程讀取。
當值可用時,_IRQ_GATTC_READ_RESULT
將引發該事件。此外,_IRQ_GATTC_READ_DONE
將提高。
BLE.
gattc_write
(conn_handle, value_handle, data, mode=0, /)
爲指定的特徵或描述符句柄向連接的服務器發出遠程寫入。
參數mode指定寫入行爲,當前支持的值爲:
mode=0
(默認)是無響應寫入:寫入將發送到遠程服務器,但不會返回確認,也不會引發任何事件。
mode=1
是 write-with-response:請求遠程服務器發送它收到數據的響應/確認。
如果收到來自遠程服務器的響應, _IRQ_GATTC_WRITE_DONE
則將引發該 事件。
BLE.
gattc_exchange_mtu
(conn_handle, /)
使用首選 MTU 集啓動與連接的服務器的 MTU 交換BLE.config(mtu=value)
.
_IRQ_MTU_EXCHANGED
當 MTU 交換完成時將引發該事件。
注意: MTU 交換通常由中央發起。在中心角色中使用 BlueKitchen 堆棧時,它不支持啓動 MTU 交換的遠程外圍設備。NimBLE 適用於這兩個角色。
L2CAP 面向連接的通道
此功能允許在兩個 BLE 設備之間進行類似套接字的數據交換。一旦設備通過 GAP 連接,任何一個設備都可以偵聽另一個設備連接到數字 PSM(協議/服務多路複用器)。
注意: 目前僅在 STM32 和 Unix(非 ESP32)上使用 NimBLE 堆棧時才支持此功能。在給定的時間可能只有一個 L2CAP 通道處於活動狀態(即您在收聽時無法連接)。
活動 L2CAP 通道由建立它們的連接句柄和 CID(通道 ID)標識。
面向連接的通道具有內置的基於信用的流量控制。與設備協商共享 MTU 的 ATT 不同,偵聽設備和連接設備都設置了一個獨立的 MTU,該 MTU 限制了遠程設備在完全消耗之前可以發送的最大未完成數據量
l2cap_recvinto
。
BLE.
l2cap_listen
(psm, mtu, /)
在本地 MTU 設置爲mtu 的情況下,開始偵聽指定psm上的傳入 L2CAP 通道請求。
當遠程設備發起連接時, _IRQ_L2CAP_ACCEPT
將引發該事件,這使偵聽服務器有機會拒絕傳入連接(通過返回非零整數)。
一旦連接被接受,_IRQ_L2CAP_CONNECT
將引發該事件,允許服務器獲取通道 ID (CID) 以及本地和遠程 MTU。
注意:目前無法停止收聽。
BLE.
l2cap_connect
(conn_handle, psm, mtu, /)
連接到指定 psm上的偵聽對等方,並將本地 MTU 設置爲mtu。
成功連接後,_IRQ_L2CAP_CONNECT
將引發該事件,允許客戶端獲取 CID 以及本地和遠程(對等)MTU。
不成功的連接將引發 _IRQ_L2CAP_DISCONNECT
具有非零狀態的事件。
BLE.
l2cap_disconnect
(conn_handle, cid, /)
使用指定的conn_handle和 cid斷開活動的 L2CAP 通道。
BLE.
l2cap_send
(conn_handle, cid, buf, /)
在由conn_handle和cid標識的 L2CAP 通道上發送指定的buf(必須支持緩衝區協議)。
指定的緩衝區不能大於遠程(對等)MTU,並且不能超過本地 MTU 大小的兩倍。
False
如果通道現在“停滯”,這將返回,這意味着 l2cap_send
在 _IRQ_L2CAP_SEND_READY
接收到事件之前不得再次調用 它(這將在遠程設備授予更多信用時發生,通常是在它接收並處理數據之後)。
BLE.
l2cap_recvinto
(conn_handle, cid, buf, /)
從指定的conn_handle和cid接收數據到提供的 buf(必須支持緩衝區協議,例如 bytearray 或 memoryview)。
返回從通道讀取的字節數。
如果buf爲 None,則返回可用字節數。
注意: 收到 _IRQ_L2CAP_RECV
事件後,應用程序應繼續調用,l2cap_recvinto
直到接收緩衝區中沒有可用字節爲止(通常達到遠程(對等)MTU 的大小)。
在接收緩衝區爲空之前,遠程設備將不會被授予更多的信道信用,並且將無法再發送任何數據。
配對和綁定
配對允許通過祕密交換對連接進行加密和身份驗證(通過密鑰身份驗證提供可選的 MITM 保護)。
綁定是將這些祕密存儲到非易失性存儲中的過程。綁定後,設備能夠根據存儲的身份解析密鑰 (IRK) 解析來自另一設備的可解析私有地址 (RPA)。要支持綁定,應用程序必須實現
_IRQ_GET_SECRET
和_IRQ_SET_SECRET
事件。注意: 目前僅在 STM32 和 Unix(非 ESP32)上使用 NimBLE 堆棧時才支持此功能。
BLE.
gap_pair
(conn_handle, /)
啓動與遠程設備的配對。
調用此之前,請確保 io
, mitm
, le_secure
, 和 bond
配置選項(通過設置config
)。
成功配對後, _IRQ_ENCRYPTION_UPDATE
將引發該事件。
BLE.
gap_passkey
(conn_handle, action, passkey, /)
響應_IRQ_PASSKEY_ACTION
指定的conn_handle 和action的事件。
該密鑰是一個數值,將取決於在 行動(這將取決於什麼樣的I / O能力已經設置):
當操作爲 時
_PASSKEY_ACTION_INPUT
,應用程序應提示用戶輸入遠程設備上顯示的密碼。當操作爲 時
_PASSKEY_ACTION_DISPLAY
,應用程序應生成一個隨機的 6 位密碼並將其顯示給用戶。當操作爲 時
_PASSKEY_ACTION_NUMERIC_COMPARISON
,應用程序應顯示_IRQ_PASSKEY_ACTION
事件中提供的密鑰,然後以0
(取消配對)或1
(接受配對)響應。
類 UUID
構造函數
class bluetooth.
UUID
(value, /)
創建具有指定值的 UUID 實例。
該值可以是:
-
一個 16 位整數。例如
0x2908
. -
一個 128 位的 UUID 字符串。例如
'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
.
以下爲以前版本:
一、固件更新
從下面這個鏈接可以下載到最新的MicroPython的版本:
更新過程請參考專欄中《EPS32 MicroPython 開發入門》這篇文章
https://zhuanlan.zhihu.com/p/55366938
下面這個鏈接是GitHub上MicroPython Bluetooth分支的連接。在這裏你可以看到源碼,如果你會自己編譯的話,可以通過源碼編譯得到帶有藍牙功能的固件。
https://github.com/icetomcat/micropython/tree/bluetooth
二、例程
這裏放一個簡單藍牙收發的例程。
from machine import Pin
import os
import bluetooth
bt = bluetooth.Bluetooth()
bt.active(1)
bt.advertise(100, 'ESP32_BLE_01')
LED=Pin(21, Pin.OUT) #port 21 is used for led
LED.value(0)
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])
def callback(char, data):
print("Get command:",data)
if(data == b'0'):
LED.value(0)
print("LED OFF")
tx.write("LED is OFF Now!\n\r")
if(data == b'1'):
LED.value(1)
print("LED OFF")
tx.write("LED is ON Now!\n\r")
rx.on_update(callback)
整個例程中創建了一個藍牙的service,包含一個監聽讀取的Characteristic和一個寫入的Characteristic。當收到字節‘1’的時候點亮LED,收到‘0’的時候關閉LED,並向控制檯返回LED的狀態。
當藍牙程序運行後,可以在手機上使用藍牙調試軟件連接名爲“ESP32_BLE_01”的藍牙設備,在發送框裏輸入0或者1。我使用是FreeBlue,在appstore上面直接下載。調試界面如下:
調試界面