打印

通过蓝牙和esp32通信

[复制链接]
26|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2025-5-25 03:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可以连接和写入:

PC端python:

import asyncio
import json
from bleak import BleakClient, discover

class BluetoothInterface:
    def __init__(self, device_name="ESP32-led", tx_uuid=None, rx_uuid=None):
        """
        初始化蓝牙接口
        
        :param device_name: 目标设备名称,默认"ESP32-led"
        :param tx_uuid: 发送数据的Characteristic UUID
        :param rx_uuid: 接收数据的Characteristic UUID
        """
        self.device_name = device_name
        self.tx_uuid = tx_uuid or "00001101-0000-1000-8000-00805F9B34FB"
        self.rx_uuid = rx_uuid or "00001101-0000-1000-8000-00805F9B34FB"
        self.client = None
        self.connected = False
        self.receive_callback = None

    async def connect(self):
        """连接到蓝牙设备"""
        devices = await discover()
        for d in devices:
            if d.name == self.device_name:
                self.device_address = d.address
                break
        else:
            raise Exception(f"未找到设备: {self.device_name}")

        self.client = BleakClient(self.device_address)
        try:
            await self.client.connect()
            self.connected = True
            print("蓝牙连接成功")
        except Exception as e:
            print(f"连接失败: {str(e)}")
            self.connected = False

    async def disconnect(self):
        """断开蓝牙连接"""
        if self.connected:
            await self.client.disconnect()
            self.connected = False
            print("蓝牙已断开")

    async def send_data(self, data):
        """发送JSON数据"""
        if not self.connected:
            raise Exception("未连接设备")
        
        try:
            json_str = json.dumps(data) + "\r\n"  # 添加帧结束符
            await self.client.write_gatt_char(self.tx_uuid, json_str.encode('utf-8'))
            print(f"发送数据: {json_str.strip()}")
        except Exception as e:
            print(f"发送失败: {str(e)}")

    def register_receive_callback(self, callback):
        """注册数据接收回调函数"""
        self.receive_callback = callback

    async def _receive_loop(self):
        """内部接收循环"""
        while self.connected:
            try:
                data = await self.client.read_gatt_char(self.rx_uuid)
                cleaned_data = data.decode('utf-8').strip('\x0d\x0a')
                if cleaned_data:
                    json_data = json.loads(cleaned_data)
                    if self.receive_callback:
                        self.receive_callback(json_data)
            except Exception as e:
                print(f"接收错误: {str(e)}")
                await asyncio.sleep(1)

    async def start_receive(self):
        """启动数据接收"""
        if self.connected:
            asyncio.create_task(self._receive_loop())

async def main():
    # 配置UUID(根据实际设备修改)
    DEVICE_NAME = "ESP32-led"
    TX_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb"  # 替换为实际发送UUID
    RX_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb"  # 替换为实际接收UUID

    interface = BluetoothInterface(
        device_name=DEVICE_NAME,
        tx_uuid=TX_UUID,
        rx_uuid=RX_UUID
    )

    await interface.connect()
    interface.register_receive_callback(print)  # 打印接收数据

    try:
        await interface.start_receive()
        
        while True:
            status = input("请输入状态(start/listening/thinking/speaking/stop): ").strip()
            score = input("请输入评分(0-10): ").strip()
            
            # 构造数据包
            data_packet = {
                "status": status,
                "score": score
            }
            
            # 发送数据
            await interface.send_data(data_packet)
            await asyncio.sleep(0.5)  # 防止快速发送导致丢包
            
    except KeyboardInterrupt:
        print("\n程序终止")
    finally:
        await interface.disconnect()

if __name__ == "__main__":
    # 运行主程序
    asyncio.run(main())


esp32:
#include <ArduinoJson.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

// 根据实际硬件定义LED引脚
#ifndef LED_BUILTIN
#define LED_BUILTIN 2  // ESP32默认LED引脚
#endif

// 配置与Python端一致的UUID
#define SERVICE_UUID        "00001101-0000-1000-8000-00805F9B34FB"  // 服务UUID
#define CHARACTERISTIC_UUID_RX "0000ffe1-0000-1000-8000-00805F9B34FB"  // 接收特征UUID

BLEServer* pServer = NULL;
BLECharacteristic* pRxCharacteristic;

// 接收数据缓冲区
String receivedData = "";

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    Serial.println("设备已连接");
  };
  
  void onDisconnect(BLEServer* pServer) {
    Serial.println("设备已断开");
  }
};

void blue_setup() {
  Serial.begin(115200);
  
  // 创建BLE设备
  BLEDevice::init("ESP32-led");
  
  // 创建服务器
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  
  // 创建服务
  BLEService* pService = pServer->createService(SERVICE_UUID);
  
  // 创建接收特征(修改此处UUID)
  pRxCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID_RX,
    BLECharacteristic::PROPERTY_WRITE_NR   // 支持无响应写入
  );
  
  // 启动服务
  pService->start();
  
  // 开始广播
  pServer->getAdvertising()->start();
  Serial.println("等待Python设备连接...");
}



void processReceivedData(String data) {
  // 去除可能的多余字符
  data.trim();
  
  // 解析JSON
  DynamicJsonDocument doc(2048);  // 使用DynamicJsonDocument替代(更灵活)
  DeserializationError error = deserializeJson(doc, data);
  
  if (error) {
    Serial.println("JSON解析错误: " + String(error.c_str()));
    return;
  }
  
  // 提取字段
  String status = doc["status"].as<String>();
  int score = doc["score"].as<int>();
  
  // 验证数据有效性
  if (status.isEmpty() || score < 0 || score > 10) {
    Serial.println("数据验证失败");
    return;
  }
  
  // 处理有效数据
  Serial.print("收到指令: ");
  Serial.print("Status=");
  Serial.print(status);
  Serial.print(", Score=");
  Serial.println(score);
  
  // 根据状态执行操作示例
  if (status == "start") {
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("疗愈开始");
  } else if (status == "stop") {
    digitalWrite(LED_BUILTIN, LOW);
    Serial.println("疗愈停止");
  }
  
  // 其他状态处理...
}

// BLE写入回调
class RxCharacteristicCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String rxValue = pCharacteristic->getValue().c_str();  // 直接转换为String
   
    if (rxValue.length() > 0) {
      receivedData += rxValue;
      Serial.println(rxValue);
    }
  }
};

void initCallbacks() {
  pRxCharacteristic->setCallbacks(new RxCharacteristicCallbacks());
}

void data_process() {
  // 处理接收数据
  if (receivedData.length() > 0) {
    Serial.println("on data recv\n");
    // 检查帧结束符
    if (receivedData.endsWith("\r\n")) {
      processReceivedData(receivedData);
      receivedData = "";
    }
  }
  delay(10);  // 避免空循环占用过高CPU
}



使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1442

主题

12772

帖子

53

粉丝