
0 前言 自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。/ R7 K( U/ c0 W( V C/ {/ b 9 D3 `- ?( N; X& o1 V 1 最小闭环回路% J( l) \4 s4 b2 p& x 最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。 1 ![]() % v( Z1 v- z- x6 d- _# q- f0 b ; ~9 R- v6 H0 E+ F x) T/ m; a( A$ z6 a4 j7 | 7 ~, a0 j! ~: f 2 系统软件环境 在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。 笔记本使用上位机是自己编写的python代码。 2 ![]() 0 D" f( S* I% |0 b; P+ x 我们将开发板当作外围设备。将笔记本作为中心设备。 / [) o g! |, d3 y 3 连接实验9 [2 M4 @' ]! Z- L/ {" x: f4 R; y; U 3.1 发现设备 下载好单片机程序,给单片机上电。$ y! \7 n# s! F0 b7 l3 L 在笔记本设置中打开蓝牙,并点击添加蓝牙。 3 ![]() % @/ C2 Y/ ~) t" q- q 可以看到我们的设备HRSTM。0 U2 t9 S# B; k7 A- r 接下来使用我编写好代码:& d1 f& p4 G( n% G h import bleak.backends.dotnet.discovery as Discovery import asyncio async def run():* J% f% {* s7 L% }6 f. _8 g devices = await Discovery.discover() for d in devices:; u; }# M( y! I print(d) loop = asyncio.get_event_loop() loop.run_until_complete(run())% [$ ~# _1 B0 T5 v3 G/ ^0 h3 F& s 在输出窗口可以看到可以被发现了的蓝牙: B8:7C:6F:47:81:BF: MiKettle 6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec')! p1 i$ J; L3 Z% K5 C4 G 80:E1:26:00:68:7C: HRSTM 1 E, U# e, d) ]: U/ ?9 r 我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。 9 y* R- \+ L# |/ y8 Q : r7 U$ ~/ N8 R6 h4 ` 3.2 连接和发现服务 接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:; b D' A5 x7 k* T( o5 h" v% }- y async with BleakClient(address, loop=loop) as client: x = await client.is_connected()& j2 l* N9 q# D9 ^8 y, K log.info("Connected: {0}".format(x)) log.info("[Service] {0}: {1}".format(service.uuid, service.description)) for char in service.characteristics:4 G7 }/ x; @1 S4 X0 ]+ d0 ~ if "read" in char.properties:2 F4 q3 l9 Q7 K try: value = bytes(await client.read_gatt_char(char.uuid)) except Exception as e:$ ]6 L6 Z/ t8 A. C value = str(e).encode()2 @. M1 D; c& Y0 n- p9 G$ d else: value = None log.info(5 b {0 ~1 E( ?& o "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format( char.uuid, ",".join(char.properties), char.description, value5 b! P, l) q% w1 `6 Z* w )- ^: Y- y8 h/ Y( q& S4 e4 ] ) for descriptor in char.descriptors: value = await client.read_gatt_descriptor(descriptor.handle)1 P3 g) @8 E- H7 ~+ e$ R9 K log.info( "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format( descriptor.uuid, descriptor.handle, bytes(value) ) )4 m ?% J: m; ?3 b ' c8 g8 \9 _5 |% S 输出的结果: Connected: True [Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile( `& e/ c. y6 O- ]& j0 Q2 K [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00' [Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile, R5 B& C2 s; b6 v) ?0 g [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'STM32WB' [Characteristic] 00002a01-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'@\x03' [Characteristic] 00002a04-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\xff\xff\xff\xff\x00\x00\xff\xff' G7 U9 H' e: V6 D; k [Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00', p" F0 A$ z4 n& _ [Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate9 u5 N, O a: T) B/ \1 N! M _ [Characteristic] 00002a37-0000-1000-8000-00805f9b34fb: (notify) | Name: , Value: None [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00': A r3 @% q, e1 _# h! M [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04'9 C1 h% g! b! E3 f [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None 观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下: /* UUIDs for Heart Rate Service */ #define HEART_RATE_SERVICE_UUID (0x180D)6 c& L5 H7 T) \* s, `* L #define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID (0x2902) #define HEART_RATE_MEASURMENT_UUID (0x2A37) #define SENSOR_LOCATION_UUID (0x2A38) #define CONTROL_POINT_UUID (0x2A39)& M' c$ [1 G( W* i 9 a, l5 X, }+ `5 p, r7 E 3.3 通知和获取数据! C7 S4 p% w- \3 b 通过STM的蓝牙软件,发现软件是有数据传递的。0 q; a9 K6 \8 D3 P' x+ `% w% e 4 ![]() ( Z$ J: i0 H+ B 其采用的方式是通知的方式,我是用了一下程序: def notification_handler(sender, data): # strs=data.hex! x0 ?9 I) Y l( J4 P print(f"{sender}: {data}")3 l0 i0 h! N# ^- k7 F, \- o byarray = bytearray(data) print(byarray.hex()) async def run(address, loop, debug=False):- E* Q" a' g/ t9 M1 O( L/ I async with BleakClient(address, loop=loop) as client:: E# Y+ c, E" V9 j/ ^. n x = await client.is_connected()9 |. l* C; g4 L; K" K. x5 B await client.start_notify(CHARACTERISTIC_UUID, notification_handler)# \* K% Q6 X _1 a; t4 S await asyncio.sleep(5.0, loop=loop) await client.stop_notify(CHARACTERISTIC_UUID)9 s" v' W# j! F( R- f7 @- q/ \ if __name__ == "__main__":8 Z% K0 ]; l k6 Z3 V if __name__ == "__main__": address = ('80:E1:26:00:68:7C') #你的地址 loop = asyncio.get_event_loop() loop.run_until_complete(run(address, loop, True))( e% N* W( ]$ X/ O; e6 e 返回了一下数据: 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04') 1f370014000004 U7 |! m% D/ { 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04')- Z; ?; n( b7 |# K- G+ Y: a. S 1f36001e000004' v2 O! i6 X0 C" s+ T9 Q 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04')# t0 D6 r* q9 I2 d4 Y 1f340028000004 : m2 ~1 t4 u+ B* y 其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。 HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10;8 f& ^" z( B2 x, |) R 4 小结 以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?: |5 N& Q' ?# \9 w 我相信,在后面一步一步的代码解析,就会解释这些现象。7 m- }3 m5 s: W ' q2 i( v4 Z9 c! ^/ X5 s 5 ^- R! }; [$ @7 p |
【NUCLEO-WB09KE评测】+3.蓝牙广播
Nucleo-STM32WB09KE测评-蓝牙调试并使用OLED显示数据
【NUCLEO-WB09KE评测】创建BLE工程和开启调试信息
【NUCLEO-WB09KE评测】+2.串口打印
【NUCLEO-WB09KE评测】+5.实现标准电量服务
【NUCLEO-WB09KE评测】BLE例程HeartRate及工具探索
STM32WB系列MCU低功耗测试
Nucleo-STM32WB09KE测评--IIC传感器读取
【NUCLEO-WB09KE评测】+4.蓝牙控制LED
【NUCLEO-WB09KE评测】+1.点灯