BLE蓝牙串口通信求助:桌面端无法实现电池数据交互
桌面端BLE电池通信解决方案
方案一:修复Bleak连接问题
- 排查连接超时/OS错误的常见点:
- 用系统工具确认设备BLE广播正常(Windows蓝牙设置、macOS Bluetooth Explorer、Linux
bluetoothctl scan on) - 远离蓝牙/WiFi信号源,减少干扰
- 调整Bleak连接超时参数(代码中设置
timeout=30,默认10秒可能不够) - 配置OS权限:Windows确保蓝牙服务开启;macOS给终端/IDE授予蓝牙权限;Linux执行
sudo setcap cap_net_raw+eip <你的Python路径>添加蓝牙权限
- 用系统工具确认设备BLE广播正常(Windows蓝牙设置、macOS Bluetooth Explorer、Linux
- 可运行的Bleak读写示例代码:
import asyncio from bleak import BleakClient, BleakScanner # 替换为你的设备信息 DEVICE_NAME = "你的电池设备名称" SERVICE_UUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" WRITE_UUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" READ_UUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" COMMAND = b"\xEA\xD1\x01\x04\xFF\x02\xF9\xF5" async def run(): # 扫描目标设备 devices = await BleakScanner.discover(timeout=10) target_device = next((d for d in devices if d.name == DEVICE_NAME), None) if not target_device: print("未找到目标电池设备") return # 建立连接并执行读写操作 async with BleakClient(target_device, timeout=30) as client: print(f"设备连接状态: {client.is_connected}") # 发送指令(response=True确保设备收到指令后返回确认) await client.write_gatt_char(WRITE_UUID, COMMAND, response=True) print("指令已发送") # 尝试主动读取返回数据 response = await client.read_gatt_char(READ_UUID) print(f"主动读取返回: {[hex(b) for b in response]}") # 若设备用通知模式返回数据,启用通知监听 def notify_handler(sender, data): print(f"收到通知数据: {[hex(b) for b in data]}") await client.start_notify(READ_UUID, notify_handler) await asyncio.sleep(5) # 等待通知数据 await client.stop_notify(READ_UUID) asyncio.run(run())
- 注意:部分设备需要先开启通知再发送指令,可调整代码顺序测试
方案二:用系统原生工具调试通信流程
- Linux/macOS(BlueZ工具):
- 终端执行
bluetoothctl进入交互模式 - 输入
scan on扫描设备,记录目标设备MAC地址 - 输入
connect <MAC地址>建立连接 - 输入
menu gatt进入GATT菜单 - 输入
select-attribute <WRITE_UUID>选中写特征 - 输入
write ea d1 01 04 ff 02 f9 f5发送指令 - 输入
select-attribute <READ_UUID>选中读特征,输入read获取返回数据
- 终端执行
- Windows(微软BluetoothLEExplorer工具):
可视化扫描设备、连接GATT服务,手动测试指令发送与数据接收,确认通信逻辑后再转化为代码
方案三:修复Arduino Nano 33的收发问题
- 若想用Arduino做中转,检查以下配置:
- 确保ArduinoBLE库正确安装,代码中正确订阅读特征的通知
- 示例代码:
#include <ArduinoBLE.h> BLEDevice batteryDevice; BLECharacteristic writeChar; BLECharacteristic readChar; // 替换为你的UUID信息 const char* serviceUUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; const char* writeUUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; const char* readUUID = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; byte command[] = {0xEA, 0xD1, 0x01, 0x04, 0xFF, 0x02, 0xF9, 0xF5}; void setup() { Serial.begin(115200); while (!Serial); if (!BLE.begin()) { Serial.println("BLE初始化失败"); while (1); } BLE.scanForUuid(serviceUUID); } void loop() { if (!batteryDevice.connected()) { batteryDevice = BLE.available(); if (batteryDevice && batteryDevice.hasService(serviceUUID)) { Serial.println("找到目标设备,尝试连接..."); if (batteryDevice.connect()) { Serial.println("连接成功"); BLEService service = batteryDevice.service(serviceUUID); writeChar = service.characteristic(writeUUID); readChar = service.characteristic(readUUID); if (readChar.canNotify()) { readChar.setEventHandler(BLEWritten, readCallback); readChar.subscribe(); } } else { Serial.println("连接失败"); } } } else { writeChar.writeValue(command, sizeof(command)); Serial.println("指令已发送"); delay(1000); } } void readCallback(BLEDevice central, BLECharacteristic characteristic) { byte* data = characteristic.value(); int len = characteristic.valueLength(); Serial.print("收到返回数据: "); for (int i=0; i<len; i++) { Serial.printf("%02X ", data[i]); } Serial.println(); }
- 检查串口波特率匹配,部分设备需要发送心跳包维持连接,可添加定时空指令发送逻辑
方案四:BLE转虚拟串口工具
- 用第三方工具将BLE设备映射为虚拟COM口,直接用串口逻辑读写(和Android端操作一致):
- 安装BLE2Serial类工具(如Serial Bluetooth Terminal桌面版)
- 扫描并连接电池设备,绑定对应的GATT读写特征到虚拟COM口
- 用Python的PySerial库操作:
import serial import time # 替换为你的虚拟COM口和波特率 ser = serial.Serial('COM3', 9600, timeout=5) command = b"\xEA\xD1\x01\x04\xFF\x02\xF9\xF5" ser.write(command) time.sleep(0.5) response = ser.read(ser.in_waiting) print(f"返回数据: {[hex(b) for b in response]}") ser.close()
内容的提问来源于stack exchange,提问作者periodicace
相关产品推荐
相关产品推荐

