BlueZ 是 Linux 官方蓝牙协议栈。它是一个基于 GPL 发布的开源项目,从 Linux2.4.6 开始便成为 Linux 内核的一部分。其基础代码均是由就职于 Qualcomm 的 Maxim Krasnyansky 完成,包括 HCI、L2CAP、RFCOMM 和基本 socket 的实现。
安装
安装完 Bluez 协议栈后,系统会增加一些调试工具,包括 bluetootchctl、hciconfig、hcitool 和 gatttool。
本文我们将使用 gatttool
连接 Thunderboard 蓝牙设备对其进行操作,同时我们可以对其数据进行分析,找出这些控制指令。
hciconfig
使用 hciconfig
命令可以查看当前能够识别的蓝牙设备,该命令类似 ifconfig
查看网卡设备。可以控制蓝牙设备的开启与关闭,在默认情况下,蓝牙设备在插入 host 时是不会自动开启的,所以我们在调试之前要先开启设备。
$ hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 74:E5:F9:FF:B0:CB ACL MTU: 1021:4 SCO MTU: 96:6
UP RUNNING PSCAN ISCAN
RX bytes:56591727 acl:245 sco:0 events:8083009 errors:0
TX bytes:700294981 acl:8080058 sco:0 commands:2632 errors:0
会输出以上内容,我们可以看到蓝牙设备的编号为 hci0
,这是 host 分配给设备的 ID,我们用来启动或关闭设备也是需要该 ID 来控制。
开启与关闭设备:
#设备打开
sudo hciconfig hci0 up
#设备关闭
sudo
hcitool
在打开蓝牙设备以后,就可以使用 hcitool 工具集对蓝牙进行控制,工具集参数分为两部分,一为正常的蓝牙设备调试,二为低功耗即 BLE 设备, 工具参数如下:
搜索 BLE 设备:
$ sudo hcitool lescan
LE Scan ...
6B:FB:CD:E4:6E:FB (unknown)
6B:FB:CD:E4:6E:FB (unknown)
60:A4:23:C9:69:9C Thunderboard #27036
60:A4:23:C9:69:9C (unknown)
50:76:0F:FA:95:10 (unknown)
50:76:0F:FA:95:10 (unknown)
F8:31:68:A0:8C:06 SMI-M1
F8:31:68:A0:8C:06 (unknown)
可以看到 Thunderboard #27036 开发板对应的地址是 60:A4:23:C9:69:9C。(后面马上用上)
gatttool
使用 interactive 方式(交互模式)连接设备:
或直接带上 BT 地址:
gatttool -b 60:A4:23:C9:69:9C -I
查看帮助:
[60:A4:23:C9:69:9C][LE]> help
help Show this help
exit Exit interactive mode
quit Exit interactive mode
connect [address [address type]] Connect to a remote device
disconnect Disconnect from a remote device
primary [UUID] Primary Service Discovery
included [start hnd [end hnd]] Find Included Services
characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery
char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery
char-read-hnd <handle> Characteristics Value/Descriptor Read by handle
char-read-uuid <UUID> [start hnd] [end hnd] Characteristics Value/Descriptor Read by UUID
char-write-req <handle> <new value> Characteristic Value Write (Write Request)
char-write-cmd <handle> <new value> Characteristic Value Write (No response)
sec-level [low | medium | high] Set security level. Default: low
mtu <value> Exchange MTU for
连接:
[60:A4:23:C9:69:9C][LE]> connect
Attempting to connect to 60:A4:23:C9:69:9C
Connection successful
查看设备提供的服务:
查看特征
其中 handle 是特性的句柄,char properties 是特性的属性值,char value handle 是特性值的句柄,uuid 是特性的标识;
我想,可以把特性(characteristic)当作是设备特供的寄存器,寄存器会有属性,如只读、只写或可读可写,在蓝牙协议里面,还有 notify 的属性,当然,这个通知属性当作是寄存器的中断服务也是说得过去的;那么,第一个 handle 可以理解为寄存器的编号,第二个 handle 理解为寄存器的地址,properties 即是寄存器属性,如果是可读可写,那么直接读写操作寄存器的地址即可。
比如 LED 对应 Automation IO Service,其 characteristic 为:
handle: 0x0021,
char properties: 0x0a, # 可读可写
我们可以通过如下方式打开、关闭 LED
[60:A4:23:C9:69:9C][LE]> char-write-req 0x0022 01
Characteristic value was written successfully
[60:A4:23:C9:69:9C][LE]>
而 温度传感器 对应 Environment Service,其 characteristic 为:
handle: 0x0044,
char properties: 0x02, # 只读
我们可以通过如下方式获取当前温度值:
08 f9
转换成十进制即 22.97 ℃
就这,是不是很简单?