Python 寫藍芽 L2CAP 通訊程式

以下範例 ShengYu 將會介紹如何使用 Python 來寫 L2CAP 藍芽通訊程式,內容包含使用 bluetooth socket 建立一個連線,傳輸資料與斷線。

範例 l2cap-server.py 和 l2cap-client.py 簡單演示了如何使用 L2CAP 傳輸協定。

使用 L2CAP socket 幾乎與 RFCOMM socket 相同。

唯一不一樣的地方是在 BluetoothSocket 建構時傳入 L2CAP 這個參數, 並且 port number 為 0x1001 到 0x8FFF 之間的奇數, 而不是原本的 1 到 30。

預設的最大傳輸單元 MTU 為 672 bytes.

server 端程式

l2cap-server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP )

port = 0x1001
server_sock.bind(("",port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address

data = client_sock.recv(1024)
print "received [%s]" % data

client_sock.close()
server_sock.close()

client 端程式

l2cap-client.py
1
2
3
4
5
6
7
8
9
10
11
12
import bluetooth

sock=bluetooth.BluetoothSocket( bluetooth.L2CAP )

bd_addr = "01:23:45:67:89:AB" # server 端的 addr
port = 0x1001

sock.connect((bd_addr, port))

sock.send("hello!!")

sock.close()

L2CAP 發送封包有最大限制,兩個裝置都各自維護了一個 MTU 來指定收到封包的最大大小,如果兩者調整各自的MTU,那麼它們有可能增加整個連線的MTU,從預設的 672 bytes 可以調整到 65535 bytes。但通常兩裝置的MTU值是設定相同的數值。在 PyBluez 裡,可以透過 set_l2cap_mtu 函式來調整這個值。

1
2
3
4
5
l2cap_sock = bluetooth.BluetoothSocket( bluetooth.L2CAP )
.
. # connect the socket
.
bluetooth.set_l2cap_mtu( l2cap_sock, 65535 )

set_l2cap_mtu 這函式使用方式相當地直觀,第一個參數為 L2CAP BluetoothSocket,第二個參數為欲設定的 MTU 數值。指定 Socket 的 incoming MTU 將會被調整,其它的 Socket 不受影響。set_l2cap_mtu 與其它 PyBluez 函式一樣,返回錯誤的話會拋出 BluetoothException 例外。

雖然我們先前提到使用 L2CAP 連線是不可靠,許多情況下有可能會用到,調整一個連線的可靠性在 PyBluez 也是很簡單呼叫個 set_packet_timeout 函式就完成了。

1
bluetooth.set_packet_timeout( bdaddr, timeout )

set_packet_timeout 帶入參數為 Bluetooth address 和一個 timeout 時間(單位為milliseconds),它將嘗試去調整封包的 timeout 時間(對任何 L2CAP 和 RFCOMM 的裝置連線)。 這個程序必須要使用管理員權限執行,且必須是一個主動連線。 只要有任何主動連線是打開的,這調整效果將一直持續,包含 Python 以外的程式。

參考
https://people.csail.mit.edu/albert/bluez-intro/x264.html

相關主題
Python 的第一支藍芽程式
Python 寫藍芽 RFCOMM 通訊程式
Python 寫藍芽 Service Discovery Protocol 通訊程式