前言

前几天买一个带蓝牙的体重秤,功能就是可以通过手机app连接,然后每一次称重都会记录下来,然后进行一些计算(体脂等),但是我不想用手机来操作,我习惯用电脑,就想写一个软件来与体重秤通信,记录我的每一次称重,简单查询了一下,体重秤的蓝牙都属于蓝牙低能耗(BLE),而python 中的类库只有一个bluepy可以实现这方面的功能,而这个库的安装远没我想象的简单,各种报错,并且windows用不了这个库,因为windows中没有gattlib这个玩意。

安装 bluepy库

简单的报错我就不说了,我只说一个我当时解决很久的一个报错,也就是安装 gattlib 的报错。
可以参考我之前写的一篇文章
不出意料bluepy就可以安装成功了。
bluepy文档地址

代码解析

代码还是很简单的,因为模式是public, 直接就是广播的数据。也不需要连接。

from bluepy.btle import Scanner, DefaultDelegate,Peripheral
import re class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self) def handleDiscovery(self, dev, isNewDev, isNewData):
print(dev.addr,dev.rawData) scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(0,passive=True)

这段代码主要功能就是扫描并接受广播的数据。
这里简单说明代码的handleDiscovery中几个参数的意义:

参数 意义
dev 扫描到的设备对象,可以根据这个设备对象获取到很多信息
isNewDev 是否为新扫描到的设备,如果是则为True,否则则为False
isNewData 是否为新数据,如果是则为True,否则则为False

另外在 handelDiscovery 函数中,可以监听新扫描到的设备以及其广播的数据,都是通过dev这个对象获取的,例如:
dev 这个对象的实质是bluepy.btle.ScanEntry object
根据官方文档:
下面列出的所有属性都是只读的。

属性名 意义
addr 设备MAC地址(以冒号分隔的十六进制字符串)。
addrType 设备地址类型-ADDR_TYPE_PUBLIC或ADDR_TYPE_RANDOM之一。
iface 0=/dev/hci0可以看到广告信息的蓝牙接口编号。
rssi 最近从设备接收到的广播的接收信号强度指示。这是一个以dB为单位的整数值,其中0 dB是最大(理论)信号强度,而更多的负数表示信号较弱。
connectable 布尔值-True如果设备支持连接,False 则为其他值(通常用于广告“信标”)。
updateCount 到目前为止,从设备接收到的广告包数量的整数计数(因为在找到它的对象上调用了clear()Scanner)。

翻译的不怎么地道,因为我用网页翻译的,不过大致还是能看懂的。
这些属性你都可以通过dev.来访问到,例如访问mac地址:print(dev.addr)

另外这里有几个官方文档里面没写的几个属性(我通过dir函数找的),这也是我需求中要使用的:

参数 意义
rawData 广播的数据

主要就是这个rawData,是广播得到的数据。

分析广播的数据

当体重稳定后得到广播的数据为:
b'\x02\x01\x04\x04\tADV\x16\xff\xca \x0bA\xaf/\x81\x01\x05-\x1d\xa6\x17pk\xedg8\xd8\xa8\x83'
经过我反复的几次测试后,得到:

意义
- 这里显示-是因为自动转换了ascii对应的字符(对应的数字就是45)。每一次计数,当达到\xff则从\x00重新记录,也就是最大计数可以达到255
\x1d\xa6 俩个字节表示体重

这里说一下体重这个表示的方法,例子中的是 \x1d (29)和 \xa6(166), 这俩数字是连续的,后面数字每达到 \xff(255)后,256开始给前面数字进一,所以,这段数字实际表示的就是:256x29+166=7590 除以100,得到75.9 kg(也就是我的体重)。

那么到此代码就很容易写了,代码最终实现:

from bluepy.btle import Scanner, DefaultDelegate,Peripheral
import re class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self) def handleDiscovery(self, dev, isNewDev, isNewData):
if dev.addr == "ed:67:38:d8:a8:83": # 体重秤的MAC地址
if isNewData:
result = re.findall(br"\x02\x01\x04\x04\tADV\x16\xff\xca \x0bA\xaf/\x81\x01\x05(.*?)\x17p",dev.rawData)
if result:
result = result[0]
print((result[1]*256+ result[2])/100," kg") scanner = Scanner().withDelegate(ScanDelegate())
devices = scanner.scan(0,passive=True)

其他

我最终是要写一个图像化界面的(PyQt5),其实也很简单:只需要将扫描线程的代码放到QThread线程里面,然后先实例化ScanDelegate()一个对象,用动态属性绑定的方式将 signal绑定到 ScanDelegate实例化的对象中以便后续称重后使用其触发信号。或者直接在实例化的过程中就将这个信号传递过去,然后在构造函数中进行绑定。

关于python实现与体重秤蓝牙ble通信研究(Linux)的更多相关文章

  1. ESP32:蓝牙BLE控制M3508电机

    ESP32:蓝牙BLE控制M3508电机 先给各位朋友拜个年,祝大家新春快乐,事事顺利,身体健康啊! 还是熟悉的3508,内容概述: ESP32主控 蓝牙BLE通信 使用实时系统(FreeRTOS) ...

  2. 蓝牙BLE传输性能及延迟分析

    BLE传输性能主要受以下几个因素影响:操作类型,Connection Interval,每个Connection Event内发送的帧数.每一帧数据的长度.具体参见如下链接: https://devz ...

  3. 蓝牙BLE实用教程

    蓝牙BLE实用教程 Bluetooth BLE 欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Re ...

  4. 微信蓝牙BLE接入调试指引 硬件篇

    1 平台框架简介 微信蓝牙BLE由三个模块组成,分别是蓝牙设备.微信和第三方服务器,如下图: 蓝牙设备与微信之间的通信是通过蓝牙GATT协议进行. 微信与第三方服器之间的通信是通过网络http 接口进 ...

  5. 【转】蓝牙ble app开发(三) -- 抓包

    原文网址:http://blog.csdn.net/lckj686/article/details/43156617 关于android 蓝牙app开发抓包的重要性在 android 蓝牙ble ap ...

  6. Android4.3 蓝牙BLE初步

    一.关键概念: Generic Attribute Profile (GATT) 通过BLE连接,读写属性类小数据的Profile通用规范.现在所有的BLE应用Profile都是基于GATT的.   ...

  7. 【转】Android4.3 蓝牙BLE初步

    原文网址:http://www.cnblogs.com/savagemorgan/p/3722657.html 一.关键概念: Generic Attribute Profile (GATT) 通过B ...

  8. 蓝牙(BLE)应用框架接口设计和应用开发——以TI CC2541为例

    本文从功能需求的角度分析一般蓝牙BLE单芯片的应用框架(SDK Framework)的接口设计过程,并以TI CC2541为例说明BLE的应用开发方法. 一.应用框架(Framework) 我们熟知的 ...

  9. 低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端

    低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端 Android对外模模式(peripheral)的支持 从Android5.0开始才支持 关键术语和概念 以下是关键BLE术语和 ...

  10. 深入浅出低功耗蓝牙(BLE)协议栈

    深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...

随机推荐

  1. v-contextmenujs 右键菜单点击

    忙碌了一晚上的"枫师傅"用上了新插件v-contextmenujs,这个插件就按照他的文档来就行 我的使用: <!-- 这里是demo.vue,之所以选择html是为了代码高 ...

  2. Nginx支持web界面执行bash|python等系统命令和脚本,可以传递参数

    文章转载自:https://me.jinchuang.org/archives/114.html ,有修改 步骤总结 1.安装好nginx,假设其html根路径为/usr/share/nginx/ht ...

  3. Kibana:如何让用户匿名访问 Kibana 中的 Dashboard

    文章转载自:https://elasticstack.blog.csdn.net/article/details/118152293 有一个很好的 Dashboard,我们想分析这个 Dashboar ...

  4. 中小制造企业需要ERP和MES吗?

    并不是所有中小制造企业都需要ERP和MES,这个取决于你的规模和管理思维与模式!匹配很重要,不同规模的企业做不同的选择!比如你大型企业,一般是要使用ERP的,其工厂也应该需要上MES系统,ERP主要用 ...

  5. The XOR Largest Pair (trie树)

    题目描述 在给定的 NN 个整数 A_1,A_2,--,A_NA1​,A2​,--,AN​ 中选出两个进行xor运算,得到的结果最大是多少?xor表示二进制的异或(^)运算符号. 输入格式 第一行输入 ...

  6. 分享个好东西两行前端代码搞定bilibili链接转视频!

    只需要在您的要解析B站视频的页面的</body>前面加上下面两行代码即可,脚本会在客户端浏览器里解析container所匹配到的容器里的B站超链接 (如果不是外围有a标签的超链接只是纯粹的 ...

  7. (数据科学学习手札145)在Python中利用yarl轻松操作url

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,在诸如网络爬虫.web应用开发 ...

  8. Spring 深入——IoC 容器 02

    IoC容器的实现学习--02 目录 IoC容器的实现学习--02 回顾 IoC 容器的初始化过程: BeanDefinition 的 Resource 定位 小结: 回顾 前面学习了 IoC 模式的核 ...

  9. C语言基础--数组

    数组 概念:在内存中连续存储的具有相同数据类型的一组数据的集合. 注意: 数组中的数据类型必须都是一致的 数组在内存中必须是连续的存储空间 定义数组时候的注意事项: 定义数组的时候,[]里面的值不能是 ...

  10. AIR32F103(三) Linux环境基于标准外设库的项目模板

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...