首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++/WinRT GattCharacteristic ValueChanged事件从不触发/触发

C++/WinRT GattCharacteristic ValueChanged事件从不触发/触发
EN

Stack Overflow用户
提问于 2022-02-21 16:25:58
回答 1查看 348关注 0票数 0

事件似乎从未在一个非常简单的C++ / WinRT控制台应用程序中开火。

用于配置设备

  • 本地名称:TestDevice
  • 广告服务:FFFF
  • 特点:EEEE

下面的程序将简单地

  • 搜索设备TestDevice
  • 使用TestDevice ShortID FFFF查找服务
  • 使用shortID EEEE查找该服务的特性
  • 编写ClientCharacteristicConfigurationDescriptor GattClientCharacteristicConfigurationDescriptorValue to EEEE,它具有读、写和通知属性。
  • 将lambda强制转换为TypedEventHandler<GattCharacteristic,GattValueChangedEventArgs>ValueChanged,它应该在值更新时打印New Value

更新特征值不会触发ValueChanged事件。然而,同样的设备设置已经通过蓝牙堆栈进行了测试,并取得了成功。

代码语言:javascript
运行
复制
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Devices.Bluetooth.h>
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>

using winrt::Windows::Devices::Bluetooth::BluetoothConnectionStatus;
using winrt::Windows::Devices::Bluetooth::BluetoothLEDevice;
using winrt::Windows::Devices::Bluetooth::BluetoothUuidHelper;
using winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs;
using winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;

using namespace winrt;


class WinBleCentral
{
public:
    WinBleCentral()
    {
        bleWatcher.Received(
            [this](BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
            {
                hstring testHstring{ std::wstring_view(L"TestDevice") };
                if (testHstring == eventArgs.Advertisement().LocalName())
                {
                    this->bleWatcher.Stop();
                    std::cout << "Matched\n";
                    BluetoothLEDevice::FromBluetoothAddressAsync(eventArgs.BluetoothAddress()).Completed(
                        [this](IAsyncOperation<BluetoothLEDevice> sender, AsyncStatus status)
                        {
                            if (auto device = sender.GetResults(); device)
                            {
                                std::cout << "Connected\n";
                                winrt::guid serviceGUID = BluetoothUuidHelper::FromShortId(0xFFFF);

                                device.GetGattServicesForUuidAsync(serviceGUID).Completed(
                                    [this](IAsyncOperation<GattDeviceServicesResult> sender, AsyncStatus status)
                                    {
                                        GattDeviceServicesResult result = sender.get();
                                        if (result && status == winrt::Windows::Foundation::AsyncStatus::Completed)
                                        {
                                            winrt::guid charGUID = BluetoothUuidHelper::FromShortId(0xEEEE);
                                            std::cout << "Num Services: " << result.Services().Size() << '\n';
                                            for (auto&& service : result.Services())
                                            {
                                                service.GetCharacteristicsForUuidAsync(charGUID).Completed(
                                                    [this](IAsyncOperation<GattCharacteristicsResult>sender, AsyncStatus status)
                                                    {
                                                        std::cout << "Get Characteristics\n";
                                                        if (auto result = sender.GetResults(); result)
                                                        {
                                                            std::cout << "Num Characteristics: " << result.Characteristics().Size() << '\n';
                                                            for (auto character : result.Characteristics())
                                                            {
                                                                character.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue::Notify).Completed(
                                                                    [this, character](IAsyncOperation<GattCommunicationStatus>sender, AsyncStatus status)
                                                                    {
                                                                        character.ValueChanged([this](GattCharacteristic characteristic, GattValueChangedEventArgs const& args)
                                                                            {
                                                                                std::cout << "New Value!\n";
                                                                            });
                                                                    });
                                                            }
                                                        }
                                                    });
                                            }
                                        }
                                    }
                                );

                            }
                        });
                }
            });
        bleWatcher.Start();
    };

    BluetoothLEAdvertisementWatcher bleWatcher;
};

int main()
{
    WinBleCentral bleCentral;
    while (getchar() != '\n');
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-21 21:53:15

这似乎是由于GattCharacteristic对象超出了作用域。通过简单地保持对tha变量的引用,上述工作将如愿以偿。

下面是与上面相同的程序,为了提高可读性,去掉了Async方面的内容。我已经测试过了,在这两种情况下都显示了完全相同的行为。

代码语言:javascript
运行
复制
#include "pch.h"
#include <iostream>

#include <Windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Devices.Bluetooth.h>
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>

using winrt::Windows::Devices::Bluetooth::BluetoothConnectionStatus;
using winrt::Windows::Devices::Bluetooth::BluetoothLEDevice;
using winrt::Windows::Devices::Bluetooth::BluetoothUuidHelper;
using winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs;
using winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;

using namespace winrt;

class WinBleCentral
{
public:
 
    WinBleCentral()
    {
        std::cout << "Start\n";
        bleWatcher.Received(
            [this](BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
            {
                hstring testHstring{ std::wstring_view(L"TestDevice") };
                if (testHstring == eventArgs.Advertisement().LocalName())
                {
                    this->bleWatcher.Stop();
                    std::cout << "Matched\n";
                    auto device = BluetoothLEDevice::FromBluetoothAddressAsync(eventArgs.BluetoothAddress()).get();
                    std::cout << "Device\n";
                    winrt::guid serviceGUID = BluetoothUuidHelper::FromShortId(0xFFFF);
                    auto serviceResults = device.GetGattServicesForUuidAsync(serviceGUID).get();
                    std::cout << "Service Results\n";
                    winrt::guid charGUID = BluetoothUuidHelper::FromShortId(0xEEEE);
                    auto service = serviceResults.Services().GetAt(0);
                    std::cout << "Services\n";
                    auto characteristicResults = service.GetCharacteristicsForUuidAsync(charGUID).get();
                    std::cout << "Characteristic Results\n";
                    auto characteristic = characteristicResults.Characteristics().GetAt(0);
                    characteristics.push_back(characteristic);
                    std::cout << "Characterstic\n";
                    auto gattCommunicationStatus = characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue::Notify).get();
                    std::cout << "WriteClientCharacteristicConfiguration\n";
                    characteristic.ValueChanged([this](GattCharacteristic const& notifyingCharacteristic, GattValueChangedEventArgs args)
                        {
                            std::cout << "New Value!\n";
                        });
                }
            });
        bleWatcher.Start();
    }

    std::vector<GattCharacteristic> characteristics;
    BluetoothLEAdvertisementWatcher bleWatcher;
};


int main()
{
    WinBleCentral bleCentral;
    while (getchar() != '\n');
}

即使从未使用过std::vector<GattCharacteristic> characteristicscharacteristics.push_back(characteristic)的简单操作也足以保持引用的活力。这种行为是绝对没有预料到的。

为了保持整个UWP风格,我最初使用了IVectorAppend方法,但是整个东西在check_hresult(WINRT_IMPL_SHIM(winrt::Windows::Foundation::Collections::IVector<T>)->Append(impl::bind_in(value)));上崩溃,看起来是空指针。

针对上述情况,为了提高可读性,避免了所有错误检查。实际实现应该对所有异步操作进行健康检查,以确保数据实际存在。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71209738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档