【蓝牙】蓝牙,调试 hcitool与gatttool实例
Bluez协议栈在安装完以后,会提供两个命令行调试工具,hcitool与gattool,我们可以根据提供的工具来轻松的调试我们的蓝牙设备,调试BLE设备时,需要获取root权限。
蓝牙设备的开启与关闭
首先,查看在使用hci工具时,我们需要查看当前能够识别的蓝牙设备,这里我们需要使用的工具是hciconfig
命令,该命令如ifconfig
一样,可以控制蓝牙设备的开启与关闭,在默认情况下,蓝牙设备在插入host时是不会自动开启的,所以我们在调试之前要先开启设备。
如果我们需要查看蓝牙设备的话:
hci0: Type: Primary Bus: UART BD Address: 54:C9:DF:B1:CD:8C ACL MTU: 1024:7 SCO MTU: 60:8 UP RUNNING PSCAN RX bytes:85137 acl:851 sco:0 events:4646 errors:0 TX bytes:44582 acl:847 sco:0 commands:2426 errors:0
会输出以上内容,我们可以看到蓝牙设备的编号为hci0
,这是host分配给设备的ID,我们用来启动或关闭设备也是需要该ID来控制。
开启与关闭设备:
#设备打开 sudo hciconfig hci0 up #设备关闭 sudo hciconfig hci0 down
hcitool命令及参数
在打开蓝牙设备以后,就可以使用hcitool工具集对蓝牙进行控制,工具集参数 分为两部分,一为正常的蓝牙设备调试,二为低功耗即BLE设备, 工具参数如下:
$ hcitool
hcitool - HCI Tool ver 4.93
Usage:
hcitool [options] <command> [command parameters]
Options:
--help Display help
-i dev HCI device
Commands:
dev Display local devices
inq Inquire remote devices
scan Scan for remote devices
name Get name from remote device
info Get information from remote device
spinq Start periodic inquiry
epinq Exit periodic inquiry
cmd Submit arbitrary HCI commands
con Display active connections
cc Create connection to remote device
dc Disconnect from remote device
sr Switch master/slave role
cpt Change connection packet type
rssi Display connection RSSI
lq Display link quality
tpl Display transmit power level
afh Display AFH channel map
lp Set/display link policy settings
lst Set/display link supervision timeout
auth Request authentication
enc Set connection encryption
key Change connection link key
clkoff Read clock offset
clock Read local or remote clock
lescan Start LE scan
lewladd Add device to LE White List
lewlrm Remove device from LE White List
lewlsz Read size of LE White List
lewlclr Clear LE White list
lecc Create a LE Connection
ledc Disconnect a LE Connection
lecup LE Connection Update
For more information on the usage of each command use:
hcitool <command> --help
命令 | 说明 | 调用方式 |
---|---|---|
参数 | ||
–help | 进入帮助 | hcitool –help |
-i | 在host插有多个蓝牙适配器的情况下,可以通过该参数来指定某控制某一适配器 | hcitool -i [dbaddr] [command] |
命令 | 下面的命令是普通蓝牙设备,不需要sudo | |
dev | 同hciconfig一样,显示当前适配器设备,输出格式为[hciid MAC] | hcitool dev |
inq | 查询可发现的远程设备,与scan不同的是,除了能查询出MAC以外,还可以查出远程设备的时钟偏移值“clock offset”与设备类型“class”,scan是不会输出相关设备的类型,这可以让我们区分设备是蓝牙耳机,或蓝牙鼠标 | hcitool inq |
hcitool inq [–length=N]设置最大查询时间 | ||
hcitool inq [–numrsp=N]设置最大查询数量 | ||
hcitool inq [–iac=lap]指定查询的lac码 | ||
hcitool inq [–flush]清除缓存 | ||
scan | 查询可发现的远程设备,与inq不同的是,除了能查询出MAC以外,还可以输出设备的名字【名字写在标准的module中,若查询不到该key对应的values则会输出N/A】,可以通过设置参数来获取设备的类型,信息等 | hcitool scan |
hcitool scan[–length=N]设置最大查询时间 | ||
hcitool scan[–numrsp=N]设置最大查询数量 | ||
hcitool scan[–iac=lap]指定查询的lac码 | ||
hcitool scan[–class]查询设备类型 | ||
hcitool scan[–info]查询设备信息 | ||
hcitool scan[–oui]查询设备唯一标识 | ||
hcitool scan[–flush]清除缓存 | ||
name | 通过指定MAC地址来获取设备的名称,该命令可以补全inq查询时无法输出设备名称的问题. | hcitool name [dbaddr] |
info | 通过指定MAC地址来获取设备的相关信息。 | hcitool info [dbaddr] |
spinq | 开启定期查询,使设备被发现,没有则无输出 | hcitool spinq |
epinq | 关闭定期查询,没有则无输出 | hcitool epinq |
cmd | 向远程设备发送命令 | hcitool cmd < ogf > < ocf > [parameters] |
con | 显示当前连接信息 | hcitool con |
cc | 连接设备,可以设置数据类型,与主从关系 | hcitool cc < bdaddr > |
hcitool cc [–ptype=pkt_types] < bdaddr > 可以设置接收数据的类型,数据类型包括[DM1, DM3, DM5,DH1,DH3,DH5, HV1, HV2, HV3],可以设置多个类型,类型中间以逗号分隔,默认接收所有类型数据 | ||
hcitool cc [–role=m/s] < bdaddr >可以设置设备的主从关系,M为master,S为slave,默认为s | ||
Example: | hcitool cc –ptype=dm1,dh3,dh5 01:02:03:04:05:06 | |
cc –role=m 01:02:03:04:05:06 | ||
dc | 断开远程设备连接 | hcitool dc < bdaddr > [reason] |
sr | 设置设备的主从关系 | hcitool sr < bdaddr > < role > |
cpt | 设置远程设备数据类型 | hcitool cpt < bdaddr > < packet_types >可以设置接收数据的类型,数据类型包括[DM1, DM3, DM5,DH1,DH3,DH5, HV1, HV2, HV3],可以设置多个类型,类型中间以逗号分隔 |
rssi | 显示设备的信号强度 | hcitool rssi < bdaddr> |
lq | 显示设备的链路质量 | hcitool lq < bdaddr> |
tpl | 显示设备的发射功率级别 | hcitool tpl < bdaddr> [type] |
afh | 显示设备的AFH(适应性跳频)的信道地图 | hcitool afh < bdaddr> |
lp | 设置或显示设备的链路 | hcitool lp < bdaddr> [link policy] |
lst | 设置或显示连接超时时间,默认情况下连接超时断开连接为20s可以设置超时时间来缩短超时断开连接的时间 | hcitool lst < bdaddr> [new value in slots] |
auth | 请求设备配对认证 | hcitool auth < bdaddr> |
enc | 设置连接加密,同样可以关闭连接加密 | hcitool enc < bdaddr> [encrypt enable] |
key | 更新与远程设备的link key | hcitool key < bdaddr> |
clkoff | 读取远程设备的时钟偏移量,不过这个变量不太靠谱 | hcitool clkoff < bdaddr> |
clock | 读取本地时钟或远程设备的时钟 | hcitool clock [bdaddr] [which clock] |
BLE设备命令 | 以下命令需要root权限才能执行 | |
lescan | 搜索BLE设备 | hcitool lescan |
hcitool lescan[–privacy]启用隐私搜索 | ||
hcitool lescan [–passive]默认参数,设置被动扫描 | ||
hcitool lescan [–discovery=g/l] 设置搜索条件为综合设备或限制设备 | ||
hcitool lescan [–duplicates]过滤重复的设备 | ||
lewladd | 将设备加入BLE白名单 | hcitool lewladd [–random] < bdaddr>可声明该设备的MAC地址为随机地址,有的BLE设备可以被设置为随机MAC地址以增加私密性,为以后也能连接到该MAC地址,需要声明MAC地址是随机,这样才能用旧的MAC地址连接到设备 |
lewlrm | 将设备移除BLE白名单 | hcitool lewlrm < bdaddr> |
lewlsz | 输出白名单设备列表 | hcitool lewlsz |
lewlclr | 清空白名单列表 | hcitool lewlclr |
lecc | 连接BLE设备 | hcitool lecc < bdaddr> |
hcitool lecc [–random] < bdaddr>随机MAC地址连接 | ||
hcitool lecc –whitelist 连接所有白名单设备 | ||
ledc | 断开BLE设备的连接。在通过lecc链接后,hci工具会随机分配给该设备一个handle名,断开连接时需要使用该handle,因为在蓝牙4.0以后,一个蓝牙适配器可以连接7个BLE设备 | hcitool ledc < handle> [reason] |
lecup | 更新BLE设备的连接及状态 | hcitool lecup [Options] |
Options: | ||
-H, –handle < 0xXXXX>指定更新状态的BLE设备Handle,在通过lecc链接后,hci工具会随机分配给该设备一个handle名 | ||
-m, –min < interval> 设置设备蓝牙的休眠时间与–max联合使用,设置的区间为: 0x0006~0x0C80 | ||
-M, –max < interval> 设置实例【hcitool lecup –handle 71 –min 6 –max 100】 | ||
-l, –latency < range> 设置BLE数据传输速率,区间为: 0x0000~0x03E8 | ||
-t, –timeout < time> N * 10ms 设置设备超时等待时间,区间为 0x000A~0x0C80 | ||
备注: | min/max参数区间为7.5ms到4s,误差在1.25ms,timeout的区间为100ms到32s |
gattool命令及其参数
使用hcitool是为了对设备的连接进行管理,那么对BLE数据进行精细化管理的话,就需要用到gattool,使用gattool对蓝牙设备发送指令的操作上要比hcitool的cmd齐全很多,关于gattool的使用分为两种,一种直接使用参数对蓝牙设备进行控制,二就是使用-I
参数进入gattool的interactive模式对蓝牙设备进行控制。
首先,看一下gattool的参数:
# gattool -h
Usage:
gatttool [OPTION...]
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-gatt Show all GATT commands
--help-params Show all Primary Services/Characteristics arguments
--help-char-read-write Show all Characteristics Value/Descriptor Read/Write arguments
Application Options:
-i, --adapter=hciX Specify local adapter interface
-b, --device=MAC Specify remote Bluetooth address
-t, --addr-type=[public | random] Set LE address type. Default: public
-m, --mtu=MTU Specify the MTU size
-p, --psm=PSM Specify the PSM for GATT/ATT over BR/EDR
-l, --sec-level=[low | medium | high] Set security level. Default: low
-I, --interactive Use interactive mode
具体含义如下:
参数 | 说明 | 调用方式 |
---|---|---|
-i | 指定适配器 | gatttool -i < hciX> -b < MAC Address> |
-b | 指定远程设备,在连接多个设备的情况下需要指定控制某一设备 | gatttool -b < bdaddr> |
-t | 指定设备的类型,是开放设备还是私密设备 | gatttool -b < MAC Address> -t [public/random] |
-m | 设置数据包长度 | -m MTU |
–sec-leve | 设置数据发送级别,默认情况下是low,需要高频发射数据的情况下需要将级别设置为high,但相应的耗电会上升 | gatttool -b < MAC Address> -l [low/medium/high] |
-I | 进入interactive模式 | gatttool -b < MAC Address> -I |
以下参数可以直接在interactive模式下使用,也可以在命令行直接使用 | ||
–primary | 寻找BLE中可用的服务 | gatttool -b < MAC Address> –primary |
–characteristics | 查看设备服务的特性,其中handle是特性的句柄,char properties是特性的属性值,char value handle是特性值的句柄,uuid是特性的标识。 | gatttool -b < MAC Address> –characteristics |
–char-desc | 配合查看服务特性使用,可以查看该设备所有服务特性的值,该值类型为键值对 | gatttool –b < MAC Address> –char-desc [–uuid 0x000]可以通过设置UUID来查看某一特性的值 |
–char-write | 更新特性的值,该更新类似于键值对,一个uuid匹配一个value | gatttool -b –char-write –uuid [0x000] –value [0] |
–char-write-req | 读取notifications里的内容,可以设置listen来开启监听否则每次只读一次,监听读取notifications时需要向该handle写入一个1,在命令行中16进制的表示为0100,若向该handle写入0200的话则改为读取indications的内容 | gatttool -b < MAC Address> –char-write-req –handle=0xXXXX –value=0100 –listen |
完整示例: | gatttool -i hci0 -b aa:bb:cc:dd -t random –char-write-req -a 0x0039 -n 0100 –listen |
蓝牙的使用:
BLE蓝牙的使用:
1、使能hci接口
# hciconfig hci0 up
2、使用hcitool搜索BLE设备
# hcitool lescan
LE Scan ...
D0:39:72:BE:D2:26 (unknown)
D0:39:72:BE:D2:26 HMDongle
D0:39:72:BE:D2:26 (unknown)
搜索到设备后按CTRL+C停止搜索,设备名称为HMDongle,是一个蓝牙串口设备,MAC地址为D0:39:72:BE:D2:26
3、使用gatttool连接设备
先查看gatttool的help
# gattool -h
Usage:
gatttool [OPTION...]
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-gatt Show all GATT commands
--help-params Show all Primary Services/Characteristics arguments
--help-char-read-write Show all Characteristics Value/Descriptor Read/Write arguments
Application Options:
-i, --adapter=hciX Specify local adapter interface
-b, --device=MAC Specify remote Bluetooth address
-t, --addr-type=[public | random] Set LE address type. Default: public
-m, --mtu=MTU Specify the MTU size
-p, --psm=PSM Specify the PSM for GATT/ATT over BR/EDR
-l, --sec-level=[low | medium | high] Set security level. Default: low
-I, --interactive Use interactive mode
使用interactive方式连接设备
# gatttool -b D0:39:72:BE:D2:26 -I
[ ][D0:39:72:BE:D2:26][LE]>
查看help
[ ][D0:39:72:BE:D2:26][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
characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery
char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery
char-read-hnd <handle> [offset] 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 GATT/ATT
[ ][D0:39:72:BE:D2:26][LE]>
连接设备
[ ][D0:39:72:BE:D2:26][LE]> connect
[CON][D0:39:72:BE:D2:26][LE]>
连接成功之后命令行前面会有[CON]标识
查看设备提供的服务
[CON][D0:39:72:BE:D2:26][LE]> primary
[CON][D0:39:72:BE:D2:26][LE]>
attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0010, end grp handle: 0xffff uuid: 0000ffe0-0000-1000-8000-00805f9b34fb
查看特性
[CON][D0:39:72:BE:D2:26][LE]> characteristics
[CON][D0:39:72:BE:D2:26][LE]>
handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, char properties: 0x0a, char value handle: 0x0007, uuid: 00002a02-0000-1000-8000-00805f9b34fb
handle: 0x0008, char properties: 0x0a, char value handle: 0x0009, uuid: 00002a03-0000-1000-8000-00805f9b34fb
handle: 0x000a, char properties: 0x02, char value handle: 0x000b, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x000d, char properties: 0x20, char value handle: 0x000e, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x0011, char properties: 0x16, char value handle: 0x0012, uuid: 0000ffe1-0000-1000-8000-00805f9b34fb
其中handle是特性的句柄,char properties是特性的属性值,char value handle是特性值的句柄,uuid是特性的标识;
我想,可以把特性当作是设备特供的寄存器,寄存器会有属性,如只读、只写或可读可写,在蓝牙协议里面,还有notify的属性,当然,这个通知属性当作是寄存器的中断服务也是说得过去的;那么,第一个handle可以理解为寄存器的编号,第二个handle理解为寄存器的地址,properties即是寄存器属性,如果是可读可写,那么直接读写操作寄存器的地址即可。
上面列出了好多个特性,其中只有一个才是读写蓝牙串口的特性,很容易看得出来,它的uuid为ffe1,属性值为0x16,可读可写(without response)可通知。在这里,从蓝牙串口读取数据并不是直接去读取0x0012这个handle,而是通过notify获取数据,首先要使能notify功能,怎么使能呢,就是把特性值handle加1即0x0013,往这个0x0013handle写入0x0100,如:
[CON][D0:39:72:BE:D2:26][LE]> char-write-req 0x0013 0100
[CON][D0:39:72:BE:D2:26][LE]> Characteristic value was written successfully
往handle写入十六进制值时不要带0x,不然会出错
[CON][D0:39:72:BE:D2:26][LE]> char-write-req 0x0013 0x0100
[CON][D0:39:72:BE:D2:26][LE]> Characteristic Write Request failed: Attribute value length is invalid
如果要向设备发送串口数据就直接往0x0012写入数据即可
[CON][D0:39:72:BE:D2:26][LE]> char-write-cmd 0x0012 48