You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter BLE自定义特征与服务:ESP32通信实现求助

问题分析与解决方案

你当前代码的核心问题是:自己手动创建的GattService和GattCharacteristic只是本地空对象,并没有和已连接的ESP32设备建立关联。bluetooth_low_energy库的读写方法需要的是从BLE设备实际发现、获取到的特征实例,不是你凭空构造的对象。

正确实现步骤

1. 连接设备后预存目标服务与特征

在设备连接成功的回调或流程中,调用discoverServices获取设备的所有服务和特征,筛选出你ESP32上定义的目标服务、特征,把它们保存到全局变量或状态管理(比如ValueNotifier、Provider)中:

// 假设已连接设备,保存设备实例
Peripheral connectedPeripheral;
// 预存目标特征
GattCharacteristic targetWriteChar;
GattCharacteristic targetReadChar;

// 设备连接成功后调用
void discoverAndSaveCharacteristics() async {
  if (connectedPeripheral == null) return;
  
  // 发现设备所有服务
  List<GattService> services = await connectedPeripheral.discoverServices();
  
  // 遍历找到目标服务(替换成你ESP32的服务UUID)
  GattService targetService = services.firstWhere(
    (service) => service.uuid.toString() == 'ffeeddcc-bbaa-9988-7766-554433221100',
    orElse: () => null,
  );
  
  if (targetService != null) {
    // 找到写特征(控制GPIO)
    targetWriteChar = targetService.characteristics.firstWhere(
      (char) => char.uuid.toString() == '你的写特征UUID' && char.properties.contains(GattCharacteristicProperty.write),
      orElse: () => null,
    );
    // 找到读特征(获取传感器数据)
    targetReadChar = targetService.characteristics.firstWhere(
      (char) => char.uuid.toString() == '你的读特征UUID' && char.properties.contains(GattCharacteristicProperty.read),
      orElse: () => null,
    );
  }
}

2. 按钮直接调用预存特征执行读写

按钮点击时,直接用预存的特征实例操作,无需重新创建:

// 控制GPIO置1的按钮
ElevatedButton(
  onPressed: () async {
    if (targetWriteChar == null) {
      // 提示未找到目标特征或未连接设备
      print('未连接设备或未找到目标特征');
      return;
    }
    
    // 发送指令"1"(转成Uint8List)
    Uint8List command = Uint8List.fromList(utf8.encode('1'));
    await CentralManager.instance.writeCharacteristic(
      targetWriteChar,
      command,
      writeType: GattCharacteristicWriteType.withResponse, // 根据ESP32配置选择
    );
    print('已发送GPIO置1指令');
  },
  child: const Text('GPIO置1'),
),

// 获取传感器数据的按钮
ElevatedButton(
  onPressed: () async {
    if (targetReadChar == null) {
      print('未连接设备或未找到目标特征');
      return;
    }
    
    Uint8List sensorData = await CentralManager.instance.readCharacteristic(targetReadChar);
    // 解析数据,比如转成字符串或数字
    String dataStr = utf8.decode(sensorData);
    print('传感器数据:$dataStr');
    // 更新UI显示数据
    // logs.value = [...logs.value, Log(LogType.read, sensorData)];
  },
  child: const Text('获取传感器数据'),
),

额外注意事项

  • 确保ESP32端定义的服务UUID、特征UUID和Flutter端完全一致,大小写也要匹配。
  • 操作前检查设备是否处于已连接状态,避免空指针异常。
  • 安卓端需要申请BLE相关权限(BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION等,根据系统版本调整)。

内容的提问来源于stack exchange,提问作者Jorge Monzon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:54:59