Временные проблемы при попытке подключения C ++ / winRT BLE? - PullRequest
0 голосов
/ 20 апреля 2019

Я использую C ++ / winRT UWP для обнаружения и подключения к устройствам с низким энергопотреблением Bluetooth. Я использую средство отслеживания рекламы для поиска рекламы на устройствах, которые я могу поддерживать. Это работает.

Затем я выбираю один для подключения. Процедура подключения немного странная, если подумать, но в соответствии с документацией Microsoft один из них вызывает метод FromBluetoothAddressAsync () с BluetoothAddress, и происходят две вещи; Вы получаете BluetoothLEDevice И предпринимается попытка подключения. Нужно зарегистрировать обработчик для события изменения статуса подключения, НО вы не сможете сделать это, пока не получите BluetoothLEDevice.

Есть ли проблема синхронизации, вызывающая исключение? Соединение уже произошло, ДО того, как я получу объект BluetoothLEDevice? Ниже приведен код, а под ним - журнал:

void BtleHandler::connectToDevice(BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
    OutputDebugStringA("Connect to device called\n");
    // My God this async stuff took me a while to figure out! See https://msdn.microsoft.com/en-us/magazine/mt846728.aspx

    IAsyncOperation<Windows::Devices::Bluetooth::BluetoothLEDevice> async =  // assuming the address type is how I am to behave ..
     BluetoothLEDevice::FromBluetoothAddressAsync(eventArgs.BluetoothAddress(), BluetoothAddressType::Random);
    bluetoothLEDevice = async.get();
    OutputDebugStringA("BluetoothLEDevice returned\n");
    bluetoothLEDevice.ConnectionStatusChanged({ this, &BtleHandler::onConnectionStatusChanged });

    // This method not only gives you the device but it also initiates a connection
}

Приведенный выше код генерирует следующий журнал:

New advertisment/scanResponse with UUID 00001809-0000-1000-8000-00805F9B34FB
New ad/scanResponse with name Philips ear thermometer and UUID 00001809-0000-1000-8000-00805F9B34FB
Connect to device called 
ERROR here--> onecoreuap\drivers\wdm\bluetooth\user\winrt\common\bluetoothutilities.cpp(509)\Windows.Devices.Bluetooth.dll!03BEFDD6: (caller: 03BFB977) ReturnHr(1) tid(144) 80070490 Element not found.
ERROR here--> onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(428)\Windows.Devices.Bluetooth.dll!03BFB9B7: (caller: 03BFAF01) ReturnHr(2) tid(144) 80070490 Element not found.
BluetoothLEDevice returned
Exception thrown at 0x0F5CDF2F (WindowsBluetoothAdapter.dll) in BtleScannerTest.exe: 0xC0000005: Access violation reading location 0x00000000.

Похоже, что есть проблема синхронизации. Но если это так, я понятия не имею, как это решить. Я не могу зарегистрироваться на событие, если у меня нет объекта BluetoothLEDevice! Я не могу найти способ получить объект BluetoothLEDevice без вызова соединения.

================================ ОБНОВЛЕНИЕ ============== ===============

Изменил методы на IAsyncAction и использовал co_await, как предложено @IInspectable. Нет разницы. Проблема состоит в том, что зарегистрированный обработчик находится вне области видимости или что-то не так с ним. Я попытался использовать get_strong () вместо «this» при регистрации, но компилятор не принял его (указанный идентификатор get_strong () не определен). Однако, если я закомментировал регистрацию, исключение не выдается, но я все равно получаю эти сообщения журнала

onecoreuap\drivers\wdm\bluetooth\user\winrt\common\bluetoothutilities.cpp(509)\Windows.Devices.Bluetooth.dll!0F27FDD6: (caller: 0F28B977) ReturnHr(3) tid(253c) 80070490 Element not found.
onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(428)\Windows.Devices.Bluetooth.dll!0F28B9B7: (caller: 0F28AF01) ReturnHr(4) tid(253c) 80070490 Element not found.

Но программа продолжает работать, и я продолжаю обнаруживать и подключаться. Но поскольку я не могу получить событие подключения, на данном этапе это бесполезно.

Ответы [ 2 ]

0 голосов
/ 22 апреля 2019

Я ненавижу свой ответ. Но после асинхронизации и совместной обработки всего под солнцем, я не могу решить эту проблему:

Этот метод

bluetoothLEDevice = co_await BluetoothLEDevice::FromBluetoothAddressAsync(eventArgs.BluetoothAddress(), BluetoothAddressType::Random);

возвращает NULL. Этого не должно быть, и я мало что могу с этим поделать. Я прочитал это как сломанный API BLE.

BTLE Central должен быть в состоянии сделать следующее

  • Обнаружьте устройство, если оно новое, тогда:
  • Если пользователь выбирает подключение, подключиться к устройство
  • выполнить обнаружение службы
  • чтение / запись / разрешение характеристики по мере необходимости
  • обрабатывать указания / уведомления

Если в любое время, когда периферийное устройство отправляет запрос безопасности или недостаточная ошибка аутентификации, начните сопряжение

повторите действие, вызвавшее недостаточную аутентификацию.

При отключении сохраняйте сопряженное и связанное состояние, если устройство является пригодным для работы.

При повторном обнаружении устройства, если оно не подключено (устройство не является платным)

  • повторить выше

Если в паре и связаны

  • начать шифрование
  • работа с устройством; нет необходимости повторно включать или выполнять обнаружение службы

========================= ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ ==================== ===============

Это то, что показывает журнал, когда метод вызывается

Connect to device called
onecoreuap\drivers\wdm\bluetooth\user\winrt\common\bluetoothutilities.cpp(509)\Windows.Devices.Bluetooth.dll!0496FDD6: (caller: 0497B977) ReturnHr(1) tid(3b1c) 80070490 Element not found.
onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(428)\Windows.Devices.Bluetooth.dll!0497B9B7: (caller: 0497AF01) ReturnHr(2) tid(3b1c) 80070490 Element not found.
BluetoothLEDevice returned is NULL. Can't register

Поскольку устройство BluetoothLED имеет значение NULL, я не пытаюсь зарегистрироваться.

================= ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ ===================

Я должен также добавить, что при прослушивании по воздуху выясняется, что никогда не происходит событие соединения. Хотя предполагается, что метод инициирует соединение, а также возвращает объект BluetoothLEDevice, в конечном итоге он не делает ни того, ни другого. Моя догадка заключается в том, что этот метод требует более предварительной настройки системы, чем это делает только DeviceWatcher. AdvertisingWatcher, вероятно, не.

0 голосов
/ 20 апреля 2019

В BLE всегда нужно ждать завершения каждой операции.
Я не эксперт в C ++, но в C # процедура асинхронного подключения возвращает bool, если она прошла успешно.
В C ++ IAsyncOperation не имеет возвращаемого типа, поэтому нет способа узнать, была ли процедура подключения успешной или завершенной.
Вам нужно будет дождаться IAsyncOperation и убедиться, что у вас есть объект BluetoothLEDevice, прежде чем присоединять обработчик событий.
Чтобы дождаться IAsyncOperation, есть вопрос / ответ о том, как ждать anIAsyncOperation: Как ждать IAsyncAction? Как ждать IAsyncAction?

...