win10下pyqt5低功耗蓝牙系列二:基本控制流程及代码

本文介绍了在Windows 10环境下,使用PyQT5进行低功耗蓝牙(BLE)的基本控制流程,包括设备发现、连接、服务与特性识别以及读写操作。详细阐述了发现设备、连接设备并发现服务的过程,同时提供了关键代码示例。
摘要由CSDN通过智能技术生成

1、基本界面

 

2、相关资料:

Bluetooth Low Energy Overview | Qt Bluetooth 5.15.8

Qt Bluetooth 5.15.8

3、基本控制流程

BLE设备发现流程包括:

1、发现设备;

2、连接设备;

3、发现服务;

4、发现特性;

5、读写操作;

6、断开连接;

3.1、发现设备流程

该流程代码如下:

    def start_scan(self):
        try:
            self.discovery_agent = QtBluetooth.QBluetoothDeviceDiscoveryAgent()
            self.discovery_agent.setLowEnergyDiscoveryTimeout(5000)
            self.discovery_agent.deviceDiscovered.connect(self.device_discovered)
            self.discovery_agent.finished.connect(self.discovery_finished)

            self.discovery_agent.start()
            if self.discovery_agent.isActive():
                print("scanning")
        except Exception as e:
            return str(e)
        else:
            return None

发现设备信号的槽函数:

    def device_discovered(self, info: QtBluetooth.QBluetoothDeviceInfo):
        # 我们只关心BLE,只对搜索到的BLE设备做处理
        if info.coreConfigurations() & QtBluetooth.QBluetoothDeviceInfo.CoreConfiguration.LowEnergyCoreConfiguration:
            self.DiscoverySignal.emit(info)

这里我们将发现设备的设备信息发送到ui界面,显示在QComboBox中,并将设备信息保存到该QComboBox中,如:

    def discovery_device(self, info: QtBluetooth.QBluetoothDeviceInfo):
        print("find device:" + info.name())
        self.comboBox_device.addItem(info.name(), info)

需要使用该QComboBox中的设备信息时,直接读取对于项目数据即可,例如:

    def connect_device(self):
        data = self.comboBox_device.itemData(self.comboBox_device.currentIndex())
        self.my_ble.connect_device(data)

3.2、连接设备及发现服务

 在设备连接成功的槽函数中可以直接启动发现服务,该流程代码如下:

    def connect_device(self, device_info: QtBluetooth.QBluetoothDeviceInfo):
        if self.low_energy_controller is not None:
            if self.low_energy_controller.state() == QtBluetooth.QLowEnergyController.ControllerState:
                self.low_energy_controller.disconnectFromDevice()

        del self.low_energy_controller
        self.low_energy_controller = QtBluetooth.QLowEnergyController.createCentral(device_info)
        self.low_energy_controller.connected.connect(self.controller_connected)
        self.low_energy_controller.disconnected.connect(self.controller_disconnected)
        self.low_energy_controller.serviceDiscovered.connect(self.service_discovered)
        self.low_energy_controller.discoveryFinished.connect(self.service_discover_finished)
        self.low_energy_controller.error.connect(self.controller_error)
        self.low_energy_controller.connectToDevice()

连接成功/连接完成信号的槽函数如下,这里在连接设备完成后直接启动了发现服务:

    def controller_connected(self):
        self.low_energy_controller.discoverServices()

断开连接信号的槽函数:

    def controller_disconnected(self):
        print("device disconnected!")
        del self.low_energy_controller
        del self.service

发现服务信号的槽函数,发现服务本质是找出服务的uuid,这里将发现的服务uuid发给了ui界面:

    def service_discovered(self, uuid: QtBluetooth.QBluetoothUuid):
        self.ServiceFoundSignal.emit(uuid)

发现服务完成信号的槽函数:

    def service_discover_finished(self):
        print("service discovery finished")

控制器错误信号槽函数:

    def controller_error(self, err_msg):
        print("Error:" + str(err_msg))

3.3、发现特性

特性(characteristic)

操作BLE设备实质是在操作特性,在查找完设备支持的服务之后,通信之前,需要发现对应服务支持的特性;特性分为可读特性、可写特性;

如果可读特性中具有通知功能,在读取该特性时需要先找到其描述符(descriptor),打开通知功能方可读取正确;

可写特性有三种写模式:WriteWithResponse、WriteWithoutResponse、WriteSigned;

描述符(descriptor)

客户端特性配置描述符,在获取了具有通知功能的可读特性后,向描述符写入正确的值,可启用通知;

 该流程代码如下:

    def connect_service(self, uuid: QtBluetooth.QBluetoothUuid):
        del self.service
        self.service = self.low_energy_controller.createServiceObject(uuid)
        if self.service:
            if self.service.state() == QtBluetooth.QLowEnergyService.ServiceState.DiscoveryRequired:
                self.service.stateChanged.connect(self.state_changed)
                self.service.characteristicChanged.connect(self.characteristic_changed)
                self.service.characteristicRead.connect(self.characteristic_read)
                self.service.characteristicWritten.connect(self.characteristic_written)
                self.service.descriptorWritten.connect(self.descriptor_written)
                self.service.descriptorRead.connect(self.descriptor_read)

                self.service.discoverDetails()
            elif self.service.state() == QtBluetooth.QLowEnergyService.ServiceState.ServiceDiscovered:
                self.state_changed(self.service.state())
        else:
            print("ERR: Cannot open service")

服务状态改变信号的槽函数,这里将发现的服务特性发送给了ui界面:

    def state_changed(self, state: QtBluetooth.QLowEnergyService.ServiceState):
        if state == QtBluetooth.QLowEnergyService.ServiceState.DiscoveringServices:
            print("state changed to: DiscoveringServices")
        elif state == QtBluetooth.QLowEnergyService.ServiceState.ServiceDiscovered:
            print("state changed to: ServiceDiscovered")
            characteristics = self.service.characteristics()
            for ch in characteristics:
                self.CharacteristicSignal.emit(ch)

其余信号的槽函数如下:

    def characteristic_changed(self, ch: QtBluetooth.QLowEnergyCharacteristic, value: QtCore.QByteArray):
        print("BLE设备-" + ch.uuid().toString() + "\t 特性值发生变化:" + str(value.toHex()))
        self.ReadSignal.emit(value)

    def characteristic_read(self, ch: QtBluetooth.QLowEnergyCharacteristic, value: QtCore.QByteArray):
        print("BLE设备-" + ch.uuid().toString() + "\t 特性值读取值:" + str(value.toHex()))
        self.ReadSignal.emit(value)

    def characteristic_written(self, ch: QtBluetooth.QLowEnergyCharacteristic, value: QtCore.QByteArray):
        print("BLE设备-" + ch.uuid().toString() + "\t 特性值写入值:" + str(value.toHex()))

    def descriptor_written(self, descriptor: QtBluetooth.QLowEnergyDescriptor, value: QtCore.QByteArray):
        print(descriptor.name() + " - " + descriptor.uuid().toString() + "\t 描述符写入值:" + str(value.toHex()))

    def descriptor_read(self, descriptor: QtBluetooth.QLowEnergyDescriptor, value: QtCore.QByteArray):
        print(descriptor.name() + " - " + descriptor.uuid().toString() + "\t 描述符读取值:" + str(value.toHex()))

3.4、读写操作

在对特性操作前,最好先判断其属性,可支持的属性有:

    class PropertyType(int):
        Unknown = ... # type: QLowEnergyCharacteristic.PropertyType
        Broadcasting = ... # type: QLowEnergyCharacteristic.PropertyType
        Read = ... # type: QLowEnergyCharacteristic.PropertyType
        WriteNoResponse = ... # type: QLowEnergyCharacteristic.PropertyType
        Write = ... # type: QLowEnergyCharacteristic.PropertyType
        Notify = ... # type: QLowEnergyCharacteristic.PropertyType
        Indicate = ... # type: QLowEnergyCharacteristic.PropertyType
        WriteSigned = ... # type: QLowEnergyCharacteristic.PropertyType
        ExtendedProperty = ... # type: QLowEnergyCharacteristic.PropertyType

读写的本质是对特性的读写,对于具有Notify属性功能的特性,必须先找到其描述符(descriptor),打开该特性的通知功能方可读取正确;

读操作代码如下:

    def read_characteristic(self, characteristic: QtBluetooth.QLowEnergyCharacteristic):
        if characteristic.isValid():
            if characteristic.properties() & QtBluetooth.QLowEnergyCharacteristic.PropertyType.Read:
                self.service.readCharacteristic(characteristic)

            if characteristic.properties() & QtBluetooth.QLowEnergyCharacteristic.PropertyType.Notify:
                descriptor = characteristic.descriptors()
                for d in descriptor:
                    self.service.writeDescriptor(d, QtCore.QByteArray.fromHex(str("0100").encode()))
                    

向描述符中写0x0100表示打开Notify功能,写0x0000表示关闭Notify功能;

写操作代码如下:

    def write_characteristic(self, characteristic: QtBluetooth.QLowEnergyCharacteristic, data: str):
        if characteristic.isValid():
            if characteristic.properties() == QLowEnergyCharacteristic.PropertyType.Write \
                    or characteristic.properties() == QLowEnergyCharacteristic.PropertyType.WriteNoResponse:
                self.service.writeCharacteristic(characteristic, QtCore.QByteArray(data))

4、全部代码

基于win10的pyqt5实现BLE调试助手源码-Python文档类资源-CSDN下载

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值