如何使用C++/WinRT的DataReader读取BLE只读特征值
C++/WinRT 读取BLE只读特征(rxService)的正确实现
你的rxService是只读特征,BLE设备会主动推送回复数据,核心操作是注册特征值变化的通知,再在回调里用DataReader解析数据,具体步骤如下:
1. 注册特征值变化通知并启用监听
给rxService注册ValueChanged事件,同时写入CCCD描述符启用设备的通知功能:
// 保存事件令牌,后续用于取消订阅 winrt::event_token rxValueChangedToken; // 注册特征值变化的回调函数 rxValueChangedToken = rxService.ValueChanged([this](auto const& sender, GattValueChangedEventArgs const& args) { // 设备推送数据时,调用处理函数解析 ProcessRxResponse(args.CharacteristicValue()); }); // 启用设备通知(必须成功写入CCCD才能收到推送) auto notifyStatus = co_await rxService.WriteClientCharacteristicConfigurationDescriptorAsync( GattClientCharacteristicConfigurationDescriptorValue::Notify); if (notifyStatus != GattCommunicationStatus::Success) { // 处理通知启用失败的情况,比如打印日志或提示用户 return; }
2. 实现数据解析函数
在回调里用DataReader读取设备返回的IBuffer,转成字符串处理:
void ProcessRxResponse(IBuffer const& dataBuffer) { Windows::Storage::Streams::DataReader reader(dataBuffer); // 设备发送的是ASCII/UTF-8字符串,对应设置编码为Utf8 reader.UnicodeEncoding = Windows::Storage::Streams::UnicodeEncoding::Utf8; // 读取所有未消费的字节为宽字符串 std::wstring deviceResponse = reader.ReadString(reader.UnconsumedBufferLength()); // 处理回复内容,示例: if (deviceResponse.find(L"+CMODE:") != std::wstring::npos) { // 解析查询到的参数值,比如提取"5"这类内容 } else if (deviceResponse == L"+CMODE:OK\n") { // 处理设置成功的逻辑 } }
3. 额外注意事项
- 编码匹配:如果设备发送纯ASCII字符串,用Utf8编码读取完全兼容;如果设备用其他编码,要对应修改
UnicodeEncoding的值。 - 取消订阅:当不需要监听设备回复时,记得取消事件注册并关闭通知,避免内存泄漏:
// 取消事件订阅 rxService.ValueChanged(rxValueChangedToken); // 关闭设备通知 co_await rxService.WriteClientCharacteristicConfigurationDescriptorAsync( GattClientCharacteristicConfigurationDescriptorValue::None); - 主动读取备选:如果设备不会主动推送(你的场景不适用,但可作为备选方案),可以调用
ReadValueAsync主动读取:auto readResult = co_await rxService.ReadValueAsync(); if (readResult.Status() == GattCommunicationStatus::Success) { ProcessRxResponse(readResult.Value()); }
内容的提问来源于stack exchange,提问作者ehardin
相关产品推荐
相关产品推荐

