0 前言8 m; |$ j' c! q% j9 x2 n 自己的主要目的是学习BLE相关的知识,以及其具体的应用。因此不会像前一小节那样,组成那么长链路的系统。为最佳的学习BLE,就需要组成最小的闭环回路。9 y* v- j: E, l, { 0 o% }: h( o Y! N 1 最小闭环回路 最小闭环系统,就是STM32WB的开发板和笔记本组成的系统。现在基本的笔记本自带蓝牙。 1 ! H6 [9 z0 D: I0 s5 a 7 R5 N2 I: \5 s6 Y* ~3 [; H 2 系统软件环境. T4 m D6 A8 {! ] 在开发板中的软件使用的是:P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_HeartRate项目工程。. `# G5 ? G! o4 ` 笔记本使用上位机是自己编写的python代码。 2 我们将开发板当作外围设备。将笔记本作为中心设备。9 }1 Y9 Y7 e8 x4 @. f2 ^; f ! y' a. S& l8 K5 P. X; k- d* X 3 连接实验 3.1 发现设备 下载好单片机程序,给单片机上电。- _- ?6 [$ \! w( \- q3 x( a 在笔记本设置中打开蓝牙,并点击添加蓝牙。 3 5 }. \" W; E% _" a- ` : H* p0 L5 i5 j8 `0 x' B7 L& M c 可以看到我们的设备HRSTM。; p* D/ R0 \' P+ Z. x 接下来使用我编写好代码:+ Z* j3 U; W' B$ | import bleak.backends.dotnet.discovery as Discovery% M- O' V& b( j import asyncio async def run(): devices = await Discovery.discover() for d in devices: print(d) loop = asyncio.get_event_loop() loop.run_until_complete(run())) u: H1 c: q- D/ Y: B , n8 s2 @( s! t. H$ q( l. G; u6 B 在输出窗口可以看到可以被发现了的蓝牙: B8:7C:6F:47:81:BF: MiKettle- e) o ]1 b5 \6 G 6B:96:A5:AF:06:A7: Apple, Inc. (b'\x10\x05Q\x1c\x82.\xec') 80:E1:26:00:68:7C: HRSTM6 }7 D2 x4 t0 W* t/ f. f$ o6 W 8 n- G+ ^/ P, X& K; V 我们也可以看到我们的蓝牙应用HRSTM。其中,一个很重要的东西就是设备的ID,这个是我们连接的一个关键,就和电话号码一样,而HRSTM就是持有人的别名。, T; ]9 S- E2 s& l7 D' A& Q 5 K4 Z4 C% D; i 3.2 连接和发现服务 接下来,我们应用上面的地址,来连接和发现一下HRSTM有哪些服务:4 x# m5 p* k0 d async with BleakClient(address, loop=loop) as client:+ c7 E& h% r9 M: C x = await client.is_connected() log.info("Connected: {0}".format(x)) log.info("[Service] {0}: {1}".format(service.uuid, service.description)) for char in service.characteristics:! S3 ~. N" A( w& q9 T. c4 y0 S if "read" in char.properties: try: value = bytes(await client.read_gatt_char(char.uuid))- J4 m) L$ F/ i4 p7 P6 N# I$ U except Exception as e: value = str(e).encode()/ n4 A. N$ z- J; H5 Y; T else:) z% _9 y9 X2 C1 N( b7 Y value = None log.info(' T0 h1 p5 u, S "\t[Characteristic] {0}: ({1}) | Name: {2}, Value: {3} ".format( char.uuid, ",".join(char.properties), char.description, value ) ) for descriptor in char.descriptors:8 C' A0 s$ s! G: S3 B3 N value = await client.read_gatt_descriptor(descriptor.handle) log.info( "\t\t[Descriptor] {0}: (Handle: {1}) | Value: {2} ".format( descriptor.uuid, descriptor.handle, bytes(value)1 a) ]' L" Q9 r4 Y ) ): z8 j& }9 J& N5 q- ^4 [- }* D6 P / U) n) W7 u+ z3 \5 J7 ] 输出的结果:5 n5 D3 v. V8 K! d7 x5 a Connected: True0 Q( d1 g: S3 y: ?) @; u- k5 b$ s" u: e [Service] 00001801-0000-1000-8000-00805f9b34fb: Generic Attribute Profile [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb: (indicate) | Name: , Value: None6 K2 m) J7 e! E$ {- c [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 4) | Value: b'\x02\x00'# m/ R& i% g: N$ _6 s% J [Service] 00001800-0000-1000-8000-00805f9b34fb: Generic Access Profile* P& z/ ^; R1 m" ?9 ^; I& P0 e [Characteristic] 00002a00-0000-1000-8000-00805f9b34fb: (read,write-without-response,write,authenticated-signed-writes) | Name: , Value: b'STM32WB'* p( Q/ O% i- K! ] [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'1 A& l% F8 H1 p* Q: t3 _ [Service] 0000180a-0000-1000-8000-00805f9b34fb: Device Information" e9 t( l& I, Q, b6 O2 D4 W [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'STM\x00'1 _6 ]/ J6 O& o/ m' x0 X [Service] 0000180d-0000-1000-8000-00805f9b34fb: Heart Rate2 O: I) }+ _# z$ c& R( ~, K [Characteristic] 00002a37-0000-1000-8000-00805f9b34fb: (notify) | Name: , Value: None [Descriptor] 00002902-0000-1000-8000-00805f9b34fb: (Handle: 18) | Value: b'\x00\x00'9 _7 M3 }) [7 w) @% ?4 i0 R [Characteristic] 00002a38-0000-1000-8000-00805f9b34fb: (read) | Name: , Value: b'\x04'4 ~5 R" N/ z5 P [Characteristic] 00002a39-0000-1000-8000-00805f9b34fb: (write) | Name: , Value: None 8 a7 Y8 ~/ X) U+ W/ ~ z 观察,返回的信息,我们大致可以通过,服务、特性、描述等知道其性能和功能。其中,发现UUID都是单片机中定义好的,在UUID.h 文件目录下:3 p7 H% W8 Y" c% J /* UUIDs for Heart Rate Service */ #define HEART_RATE_SERVICE_UUID (0x180D) #define CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID (0x2902) #define HEART_RATE_MEASURMENT_UUID (0x2A37) #define SENSOR_LOCATION_UUID (0x2A38) #define CONTROL_POINT_UUID (0x2A39) 3.3 通知和获取数据# ^, a3 M! H1 G9 w- q( k 通过STM的蓝牙软件,发现软件是有数据传递的。" Y' _7 {% V+ y# ^6 W 4 其采用的方式是通知的方式,我是用了一下程序:0 [& l& G# w; o0 |% } J( _ 3 t3 K' Y$ @. d- o1 W$ o def notification_handler(sender, data):' ]2 V- M u) \2 t% }2 y3 n # strs=data.hex0 e* _" k4 L4 O! P* @; @8 Q: k: z print(f"{sender}: {data}") byarray = bytearray(data) print(byarray.hex())3 Z$ N$ t0 q: N) d8 ^! R , S2 c" ^6 P9 N: {9 G" c async def run(address, loop, debug=False): async with BleakClient(address, loop=loop) as client: x = await client.is_connected()& d$ y! z8 M: \9 e1 u await client.start_notify(CHARACTERISTIC_UUID, notification_handler)6 c" O M% Z1 T4 H) W3 ] await asyncio.sleep(5.0, loop=loop) await client.stop_notify(CHARACTERISTIC_UUID) if __name__ == "__main__":/ O% i$ C" D! ^( g9 k- l if __name__ == "__main__": address = ('80:E1:26:00:68:7C') #你的地址 loop = asyncio.get_event_loop() u" d' f1 {# s! m- k4 y5 v loop.run_until_complete(run(address, loop, True))! j# w8 a! O1 I 返回了一下数据: 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f7\x00\x14\x00\x00\x04'). N0 l8 p: O( C% t+ P4 I! a 1f3700140000047 |2 J% s8 ^6 E/ a2 N4 k 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f6\x00\x1e\x00\x00\x04') 1f36001e000004, I: ~) \2 n: \5 D7 B 00002a37-0000-1000-8000-00805f9b34fb: bytearray(b'\x1f4\x00(\x00\x00\x04') 1f340028000004 4 i7 x9 x7 z5 w5 K0 L 其中00002a37是HEART_RATE_MEASURMENT_UUID ,数据是十六进制的1f36001e000004,其中0x36是心跳,1e是能量消耗,我将能量变化修改为,每次+10,从每次读回的值就可以看到。% ] L, E& P( Q HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 10;4 X1 Z8 X1 C: W$ B 4 小结' I! a3 J, ~ O/ h& y& D8 k 以上步骤,从发现蓝牙,连接蓝牙,获取蓝牙服务,以及获取数据。其实,实验中还有许多的小问题,比如指示灯的闪烁,为啥STM官方的APP可以直接连接,自己的却不行?0 l! ?& c' N7 r- ]9 u2 n' v 我相信,在后面一步一步的代码解析,就会解释这些现象。 ; m6 _) t. _% p) [. O$ ` 6 ^. ^$ H5 S* Q7 v9 } - l$ Y, |) |' ^6 D1 j0 u" F & j/ x: |3 _5 ?9 a+ B |
4月25日培训|基于ST 双核多协议STM32WB55的Matter方案开发
实战经验 | 关于STM32WB OTA 速率提升引发的讨论
基于STM32WB55的配置串口打印Debug经验分享
基于创建STM32WBA BLE_Custom工程经验分享
来看直播了,就在明天 | STM32 Matter 解决方案,轻松实现智能家居无缝连接
基于STM32WB55开发之套件概述(1)
基于STM32WB55开发之监测STM32WB连接状态(1)
基于STM32WB55开发之修改蓝牙地址(2)
STM32WB基于Custom Template实现客户定制BLE私有协议
如何基于STM32WB一次性烧写FUS+STACK+APP