简单逆向某蓝牙血氧仪通信协议,配合 ESP32 实现全天血氧监控

之前买了个血氧仪,带蓝牙数据传输功能,想使用它监控一下整晚睡眠时的血氧。

lepu-oximeter-re-1

但是在使用时才发现,如果想要持续监控,配套的 App 需要一直在前台保持激活状态,就是手机不能息屏,浪费电不说,在后续查看数据时发现 App 中查看也不太好用。

这时想到它既然是使用蓝牙传输数据的,那大概率是直接用了 BLE,如果传输没有加密的话,那不是可以直接用 ESP32-S3 直接来读取一下,再转发到 MQTT 服务器,就可以实现全天的血氧监控了,而且可以有全部数据点的详细数据。

注:本文仅供学习研究与互操作性分析之用。请仅在对目标设备与数据拥有合法权利或已获明确授权的前提下使用。禁止用于未授权访问、数据窃取、绕过安全机制等违法用途;一切后果由使用者自行承担。

拿 Lightblue 测试一下

说干就干,先在电脑上用 BLE 测试软件看看能不能抓到一些数据。

将手指放进血氧仪,待数据稳定之后,打开 Lightblue 看看能不能找到设备~

很快就找到一个 PC-60F 打头的设备。

lepu-oximeter-re-2

可以看到这个设备,有一个 Notify 的 Character,看看这个是不是

lepu-oximeter-re-3

可以看到在订阅这个 Character 之后,血氧仪在一直发送数据,这时把这些数据日志保存下来,看看能不能找到血氧数值在哪条消息里。

怎么逆向?

好吧,其实我用了一个笨方法,通过观察血氧仪的读数,再在日志中查找对应的数字,一般来说,血氧最大值 100%,那么用一个字节就可以表示了,应该是可以直接搜索到的。

在观察过程中,血氧仪显示 97%,那么在日志中搜索对应的 16 进制数 0x61:

lepu-oximeter-re-4

截取这段中有 3 条数据出现了 0x61,但是前一个字节不太一样,分别是 0x01 和 0x02,这个时候可以选择再继续观察后续数据,来确认哪一个是上报的血氧数据。

但是我选择了对比一下心率,当时看到的心率是 81,对应 16 进制数字为 0x51,那就跟 0x01 打头的记录对上了。

至于其他消息的内容具体是什么就没在去关注了 🙈

通过 ESP32-S3 中转数据到 MQTT

ESP32-S3 支持 BLE 5.0,连接血氧仪应该是没有任何问题的,使用 Arduino 框架也很方便,只需要调用 BLEDevice 就可以完成 BLE 设备的连接、订阅相关操作。

前面已经有了血氧仪数据的规律,这个时候只需要在 ESP32-S3 中订阅那个特定的 Character,并且过滤出前缀为 0xaa550f0801 的数据,再将随后 2 个字节的数据解析出来即可。

lepu-oximeter-re-5

再将数据通过 MQTT 传输到 MQTT Broker 即可:

lepu-oximeter-re-6

至于屏幕显示什么的,都是常规的使用 Adafruit SSD1306 库按设计的界面显示就行。

使用 MQTT 观测数据

本来想把数据存到 InfluxDB 再用 Grafana 来看,但是嫌太麻烦了没搞,先找了个 App 也能保存很多数据,先凑合用了。

lepu-oximeter-re-7

就这样差不多算是把整个链路跑通了,有啥问题可以在家实现全天血氧 + 心率监测了,可能就是血氧仪的电池得经常换 😂。

等等,我不是有 AI 吗?

前两天突然想起来,现在 AI 这么强大,不是可以直接用 AI 来尝试分析实际的通信协议吗?完全没必要自己去猜测。

把日志丢给 AI,没想到一次成功:

lepu-oximeter-re-8

最分析出来的协议:

lepu-oximeter-re-9

除了用 LEN 来作为包类型判断有点问题,其他基本完美,连 CRC 校验也可以猜测并且验证 😃,早知道就不用自己在那里猜关天了。

总结

现在借助于 AI,对于一些非开放但是协议没有加密的设备,完全可以实现自己的数据接收设备,实在太方便了。

希望此文对也想实现全天血氧监测的朋友们有所帮助。

发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>