wshuo 发表于 2021-8-16 20:09

关于led蓝牙控制器ble通信分析

### 前言
前几天在网上买了一个led蓝牙控制器,可以用手机**app**通过蓝牙连接控制**rgb** **led**灯,当然这个也是属于ble通信。之前我写过一篇体重称蓝牙通信的,不过那个较为简单,数据也是靠分析出来的。
这次通过手机蓝牙抓包,对蓝牙通信数据进行分析,然后通过**python**的**bluepy**库实现了通信,从而可以实现电脑控制**rgb**灯的效果。

### 初步分析
这里我用的是手机上的软件,**BLE Scanner**, 可以查看到低功耗蓝牙及与其通信。   
连接到对应的服务:
![请添加图片描述](https://img-blog.csdnimg.cn/351bc3973a3543c7bce399eed0cf26b8.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Nob3V6aG91OTcwMQ==,size_16,color_FFFFFF,t_70)
我们可以看到,有2个服务,3个 Characteristic , 而且只有一个characteristic 有写入权限,那么此时可以确定控制rgb灯带必然是与最后这个characteristic 通信。数据包分析会进一步证明。

一个物理ble蓝牙设备包含多个server, 而一个server有包含多个 characteristic, 进行具体通信的时候都是对 其中的characteristic进行读取和写入,从而达到通信的目的。
### 手机蓝牙数据抓包
我用的是小米手机抓取的蓝牙数据包,开发者模式中的那个抓包一直不好使,这个跟手机品牌有关,还好小米手机有一个测试抓包用的功能,在拨号键中输入 **\*\#\*\#5959#\*\#\***:

![请添加图片描述](https://img-blog.csdnimg.cn/f63046952e264208afd3072003f3a5e0.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Nob3V6aG91OTcwMQ==,size_16,color_FFFFFF,t_70)
   
然后可以进入app, 进行一些修改,进行一些蓝牙通信:
![请添加图片描述](https://img-blog.csdnimg.cn/dd850e8068f849d0946d066fd9e8c3a5.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Nob3V6aG91OTcwMQ==,size_16,color_FFFFFF,t_70)
   
通信结束后,再次输入:**\*\#\*\#5959#\*\#\*** 结束抓包。

蓝牙数据包存储在 `/sdcard/MIUI/debug_log/` 目录下,是一个压缩包,将其转移到电脑:
```shell
adb pull /sdcard/MIUI/debug_log/bugreport-2021-08-16-181040.zip .
```

解压,在**common**文件下可以找到蓝牙的数据包:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f40ca19ef4714cf0ac9e024c15bac700.png)
   
这个文件可以在wireshark中打开。
### 蓝牙数据包分析
![在这里插入图片描述](https://img-blog.csdnimg.cn/ea7c1e205e3d4b66baf7ee12d14048db.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Nob3V6aG91OTcwMQ==,size_16,color_FFFFFF,t_70)
这里我简单写了一条过滤命令:`bluetooth.dst == be:58:50:00:69:f2`,指定目的蓝牙mac地址。
可以看到我选中的是 Write Command, 可以确定是这个数据包进行修改了rgb灯效,找到 Handle:
![在这里插入图片描述](https://img-blog.csdnimg.cn/c2ed202715db4a66917c9e200247111f.png)
可以看到 service uuid为:0xfff0, Characteristic uuid为:0xfff3, 对应我们前面初步分析中的结论。也就是最后一个characteristic 实现控制rgb灯, 而这个通信的数据就是: 7e070503ff003710ef 。

### python 代码实现:
```python
from bluepy.btle import Peripheral
p = Peripheral("be:58:50:00:69:f2")
p.getCharacteristics(uuid="0000fff3-0000-1000-8000-00805f9b34fb").write(b"\x7e\x07\x05\x03\xff\x00\x37\x10\xef")

```
uuid 是通过 **BLE Scanner**得到的,当然你不知道uuid的话也可以先获取所有的server, 然后遍历所有 server中的所有 Characteristic得到所有的 Characteristic的 uuid。
执行代码后,发现灯的颜色已经改变了。(linux有时需要root运行,否则会报错权限不足)

通过反复抓包以及分析,最后我得到几个 灯效 的数据,还有一个速度的控制:
```python
data = {
"静态黄色":b"\x7e\x05\x03\x84\x03\xff\xff\x00\xef",
"静态紫色":b"\x7e\x05\x03\x85\x03\xff\xff\x00\xef",
"静态白色":b"\x7e\x05\x03\x86\x03\xff\xff\x00\xef",
"七色跳变":b"\x7e\x05\x03\x88\x03\xff\xff\x00\xef",
"三色跳变":b"\x7e\x05\x03\x87\x03\xff\xff\x00\xef",
"三色渐变":b"\x7e\x05\x03\x89\x03\xff\xff\x00\xef",
"七色渐变":b"\x7e\x05\x03\x8a\x03\xff\xff\x00\xef",
}
```
结合PyQt5 简单写一个软件控制灯效及速度:
```python
import re
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from bluepy.btle import Peripheral


data = {
"静态黄色":b"\x7e\x05\x03\x84\x03\xff\xff\x00\xef",
"静态紫色":b"\x7e\x05\x03\x85\x03\xff\xff\x00\xef",
"静态白色":b"\x7e\x05\x03\x86\x03\xff\xff\x00\xef",
"七色跳变":b"\x7e\x05\x03\x88\x03\xff\xff\x00\xef",
"三色跳变":b"\x7e\x05\x03\x87\x03\xff\xff\x00\xef",
"三色渐变":b"\x7e\x05\x03\x89\x03\xff\xff\x00\xef",
"七色渐变":b"\x7e\x05\x03\x8a\x03\xff\xff\x00\xef",
}

class MyMainWindow(QWidget):
    def __init__(self):
      super(MyMainWindow, self).__init__()
      p = Peripheral("be:58:50:00:69:f2")
      self.characteristic = p.getCharacteristics(uuid="0000fff3-0000-1000-8000-00805f9b34fb")
      vlayout = QVBoxLayout()
      hlyaout = QHBoxLayout()
      self.label = QLabel('0')

      self.combox = QComboBox()
      self.combox.addItems()
      self.combox.currentIndexChanged['QString'].connect(self.updateMode)
      self.slider = QSlider()
      self.slider.setOrientation(1)
      self.slider.setMaximum(100)
      self.slider.valueChanged['int'].connect(self.updateSpeed)
      
      hlyaout.addWidget(self.slider)
      hlyaout.addWidget(self.label)

      vlayout.addWidget(self.combox)
      vlayout.addLayout(hlyaout)

      self.setLayout(vlayout)


    def updateSpeed(self,speed):
      self.label.setText(str(speed))
      WriteData = b"\x7e\x04\x02%s\xff\xff\xff\x00\xef" % chr(speed).encode()
      # print(WriteData)
      self.characteristic.write(WriteData,withResponse=False)

    def updateMode(self,mode):
      # print(data)
      self.characteristic.write(data,withResponse=False)

if __name__=='__main__':
    app = QApplication(sys.argv)
    mywin = MyMainWindow()
    mywin.show()
    sys.exit(app.exec_())
```

![在这里插入图片描述](https://img-blog.csdnimg.cn/319a7b0483b74bedb5fd96d785d2b55c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Nob3V6aG91OTcwMQ==,size_16,color_FFFFFF,t_70)

Monitor 发表于 2021-8-17 09:07

门锁也可以参考这个方法吧,很简单的那种门锁,不是家里大门的

约定的童话 发表于 2021-10-25 16:41

大佬,已知蓝牙名称及UUID等:
蓝牙名:YX_***(*是MAC码)
serviceId:0000FFB0-0000-1000-8000-00805F9B34FB
notifyId:0000FFB2-0000-1000-8000-00805F9B34FB
writeId:0000FFB1-0000-1000-8000-00805F9B34FB

如何用PC连接这个蓝牙形成COM口,这样方便我接来下用VB控制这个蓝牙?

youshi 发表于 2022-11-30 16:42

约定的童话 发表于 2021-10-25 16:41
大佬,已知蓝牙名称及UUID等:
蓝牙名:YX_***(*是MAC码)
serviceId:0000FFB0-0000-1000-8000-00805F9 ...

网上有usb转ble的小板,也挺便宜。有一些协议,根据协议就可以连接 发送和接收。或者有编程基础,可以用esp32设备自己做个也行

约定的童话 发表于 2022-11-30 19:02

youshi 发表于 2022-11-30 16:42
网上有usb转ble的小板,也挺便宜。有一些协议,根据协议就可以连接 发送和接收。或者有编程基础,可以用e ...

最后采用的ESP8266搞定了,感谢大佬答疑

oneperfect 发表于 2023-2-15 17:39

这是我需要的,留个足迹,感谢

bailiang123 发表于 2023-2-15 22:00

第三方股份合计看了看交换机
页: [1]
查看完整版本: 关于led蓝牙控制器ble通信分析