吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1908|回复: 5
收起左侧

[Python 转载] 关于python实现与体重秤蓝牙ble通信研究(Linux)

[复制链接]
wshuo 发表于 2020-11-20 15:10
本帖最后由 wshuo 于 2020-11-20 15:16 编辑

前言

前几天买一个带蓝牙的体重秤,功能就是可以通过手机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实例化的对象中以便后续称重后使用其触发信号。或者直接在实例化的过程中就将这个信号传递过去,然后在构造函数中进行绑定。

免费评分

参与人数 6吾爱币 +15 热心值 +5 收起 理由
火绒 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
苏紫方璇 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
52P + 1 + 1 用心讨论,共获提升!
Laign + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lijp900214 + 1 + 1 谢谢@Thanks!
longfei9527 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lijp900214 发表于 2020-11-20 15:29
膜拜啊,之前弄了个菲讯的体脂秤,后来斐讯倒了,APP也不能用了,感觉可以试着借鉴一下
longfei9527 发表于 2020-11-20 15:21
本帖最后由 longfei9527 于 2020-11-20 15:22 编辑

比较少用Python, 膜拜一下大佬的技术分享
Laign 发表于 2020-11-20 15:41
楼主太历害了,刚刚接触Python,还不能实际应用,有机会学习一下楼主的操作
筱木头 发表于 2020-11-20 15:51
很厉害,我能看懂一半。。。好羡慕,俺刚入门,哈哈
52P 发表于 2020-11-20 16:01
斐讯那个体脂秤用WIFI的怎么搞?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 23:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表