Есть ли событие Windows, чтобы узнать, сопрягается ли устройство Bluetooth?

Я создаю приложение, которое позволяет мне подключаться к устройству Bluetooth. Прямо сейчас я пытаюсь найти событие в C#, которое позволяет мне определять, когда устройство добавляется или готово к добавлению (см. Img: всплывающее окно Windows 10)

Есть ли событие Windows, чтобы узнать, сопрягается ли устройство Bluetooth?

Кто-нибудь знает, кого я ищу?

docs.microsoft.com/en-us/windows/uwp/devices-sensors/…, раздел «Custom Pairing»
Cee McSharpface 24.10.2018 14:02

Это очень помогло. Похоже, что все, что мне нужно, есть в сборке windows.Devices.Enumeration.

Jordec 24.10.2018 14:29

В зависимости от типа вашего приложения есть несколько способов. Для UWP вы должны использовать Device Enumerator, чтобы получать уведомления об изменениях в оборудовании. Пользовательское сопряжение не позволяет обрабатывать сопряжение, появившееся вне приложения. Для классического приложения лучше использовать Native Bluetooth API, который позволяет обрабатывать все необходимые события. Также вы можете взглянуть на Cofiguration Manager. Или захватите сообщение WM_DEVICECHANGE.

Mike Petrichenko 24.10.2018 14:57

Ах, да, windows.Devices.Enumeration пригодится мне только в UWP, но мне он нужен в классическом приложении. @MikePetrichenko, кстати, что вы имеете в виду под Configuration Manager?

Jordec 24.10.2018 16:44
CFG Manager API. Или лучше использовать Classic Bluetooth API. Намного лучше. Или простой запрос WMI.
Mike Petrichenko 24.10.2018 16:56

Я попытался переопределить метод WndProc и попытаться отфильтровать Msg для WD_DEVICECHANGE, но по какой-то причине я не могу заставить его срабатывать. Это должно быть возможно, когда устройство Bluetooth пытается подключиться, я получаю сообщение, верно?

Jordec 26.10.2018 07:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
6
1 298
1

Ответы 1

Я немного опоздал, но вот несколько отрывков о том, что я делаю в простом Raw API (на C++), используя сообщения WM_DEVICECHANGE.

  • вам нужно перехватывать сообщения WM_DEVICECHANGE (очевидно)
  • сначала вам нужно «зарегистрировать» соответствующие идентификаторы GUID:
  • GUID_BTHPORT_DEVICE_INTERFACE {0850302A-B344-4fda-9BE9-90576B8D46F0} для перехвата событий о самом Радио
  • GUID_BTH_DEVICE_INTERFACE {00F40965-E89D-4487-9890-87C3ABB211F4} для перехвата событий о любых устройствах Bluetooth и / или
  • GUID_BLUETOOTHLE_DEVICE_INTERFACE {781aee18-7733-4ce4-add0-91f41c67b592} для перехвата событий о BLE устройств.

(Это «GUID интерфейса» на случай, если они вам понадобятся с подпрограммами SetupAPIxx / CM_xx)

Я использую следующий код для их «регистрации»:

HDEVNOTIFY UDeviceInfoHandler::RegisterDeviceNotification(  HWND    hwnd,
                                                            GUID    InterfaceClassGuid,
                                                            DWORD   flags)
{
    DEV_BROADCAST_DEVICEINTERFACE DevFilter;
    ::ZeroMemory(&DevFilter, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
    DevFilter.dbcc_size = sizeof( DEV_BROADCAST_DEVICEINTERFACE );
    DevFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    DevFilter.dbcc_classguid = InterfaceClassGuid;
    return ::RegisterDeviceNotification(hwnd,       //events recipient
                                        &DevFilter, //type of device
                                        flags);     //type of recipient handle
}

bool UDeviceInfoHandler::UnregisterDeviceNotification(HDEVNOTIFY hdevnotify)
{
    return TRUE==::UnregisterDeviceNotification(hdevnotify);
}

На этом этапе вы сможете

  • чтобы увидеть, как появляется / исчезает 'Радио' (например, играя с галочкой 'Активировать Bluetooth' в Настройках)
  • чтобы увидеть появление / исчезновение виртуальных COM-портов BT2.x
  • чтобы увидеть, как BLE-устройства появляются / исчезают, ПРИ условии, что они уже 'сопряжены' (то есть, вкратце, добавлены в реестр)

обрабатывая

  • DBT_DEVICEARRIVAL | DBT_DEVTYP_DEVICEINTERFACE и
  • DBT_DEVICEREMOVECOMPLETE | DBT_DEVTYP_DEVICEINTERFACE

сообщения в обработчике WM_DEVICECHANGE.

Если вам нужно получить доступ к сообщениям DBT_CUSTOMEVENT, относящимся к Radio / Devices, вам сначала нужно «зарегистрировать» некоторые «события» также для WM_DEVICECHANGE, но для «HANDLE» Radio. Вы можете зарегистрировать GUID следующих событий

  • GUID_BLUETOOTH_RADIO_IN_RANGE
  • GUID_BLUETOOTH_RADIO_OUT_OF_RANGE
  • GUID_BLUETOOTH_L2CAP_EVENT
  • GUID_BLUETOOTH_HCI_EVENT
  • GUID_BLUETOOTH_HCI_VENDOR_EVENT

Используйте что-нибудь вроде

void UBthDeviceInfoHandler::RegisterBthNotifications(HWND hwnd,const UGuidItems& guids)
{
    BLUETOOTH_FIND_RADIO_PARAMS radio_params;
    radio_params.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS);

    HANDLE hRadio;
    HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&radio_params, &hRadio);
    if (hFind != INVALID_HANDLE_VALUE) 
    {
        do 
        {
            //for every events Guid you need
            HDEVNOTIFY hdevnotify=
                RegisterHandleNotification( hwnd,
                                            hRadio,
                                            Guid,
                                            DEVICE_NOTIFY_WINDOW_HANDLE);
            if (hdevnotify!=NULL){
                  //insert code here
            }
            else{
                  //error handling
            }
            //end for
        } while (BluetoothFindNextRadio(hFind, &hRadio));

        BluetoothFindRadioClose(hFind);
    }
}

На этом этапе вы сможете получать эти события, обрабатывая портирование DBT_CUSTOMEVENT | DBT_DEVTYP_HANDLE обработчика WM_DEVICECHANGE с чем-то вроде

    [...]
    #if (WINVER >= 0x040A)
            case DBT_CUSTOMEVENT:
            //@see https://msdn.microsoft.com/en-us/library/aa363217(v=vs.85).aspx
                if (lParam!=0){
                    PDEV_BROADCAST_HDR phdr = reinterpret_cast<PDEV_BROADCAST_HDR> (lParam);
                    switch (phdr->dbch_devicetype){
                        case DBT_DEVTYP_HANDLE:
                            {
            //@see https://docs.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wm-devicechange-messages

                                //typedef struct _DEV_BROADCAST_HANDLE {
                                //  DWORD       dbch_size;
                                //  DWORD       dbch_devicetype;
                                //  DWORD       dbch_reserved;
                                //  HANDLE      dbch_handle;     // file handle used in call to RegisterDeviceNotification
                                //  HDEVNOTIFY  dbch_hdevnotify; // returned from RegisterDeviceNotification
                                //  //
                                //  // The following 3 fields are only valid if wParam is DBT_CUSTOMEVENT.
                                //  //
                                //  GUID        dbch_eventguid;
                                //  LONG        dbch_nameoffset; // offset (bytes) of variable-length string buffer (-1 if none)
                                //  BYTE        dbch_data[1];    // variable-sized buffer, potentially containing binary and/or text data
                                //} DEV_BROADCAST_HANDLE, *PDEV_BROADCAST_HANDLE;

                                PDEV_BROADCAST_HANDLE phndl=reinterpret_cast<PDEV_BROADCAST_HANDLE>(phdr);
                                CustomHandleEvent(*phndl);

                            }
                            break;


                  default:
                        break;
                }
            }//endif lParam!=0
            break;
    #endif // WINVER >= 0x040A

| dbch_eventguid | поле, являющееся одним из тех событий GUID_BLUETOOTH_RADIO_IN_RANGE и т. д.

Что ж, это только обзор того, что я обнаружил до сих пор. Тем не менее, любые улучшения / предложения / дополнения более чем приветствуются. В настоящее время я борюсь с несколькими недокументированными CUSTOM_EVENTS, GUID которых

//When the Bluetooth radio handle is opened, call the RegisterDeviceNotification function and
//register for notifications on the handle using DBT_DEVTYP_HANDLE as the devicetype.
//When registered, the following GUIDs are sent, 
//and the DEV_BROADCAST_HANDLE::dbch_data member is the associated buffer.

//this unknow event happens while looking for nearby devices in Settings.
DEFINE_GUID(GUID_UNKNOWN_EVENT_GUID1,0x1BBD4010, 0x498C, 0x4E85, 0x85, 0x1B, 0xEA, 0xA0, 0x57, 0x15, 0xC3, 0x7A);

//
DEFINE_GUID(GUID_UNKNOWN_EVENT_GUID2,0xD4EB6503, 0xC001, 0x441A, 0xAE, 0x42, 0xEE, 0x0D, 0xC9, 0x6C, 0x18, 0x85);

//happening when opening Settings|Bluetooth panel
DEFINE_GUID(GUID_UNKNOWN_EVENT_GUID3,0x7A7637FF, 0x531C, 0x4205, 0x97, 0x80, 0x3F, 0x33, 0x5F, 0x65, 0xAD, 0xDD);
//nameoffset=-1 datalen=8

//Settings|Devices -> Bluetooth activation/deactivation
DEFINE_GUID(GUID_UNKNOWN_EVENT_GUID4,0xB74983CD, 0xC2D9, 0x4E38, 0xB8, 0x0E, 0x54, 0x72, 0xFC, 0x10, 0x8B, 0x4B);
//nameoffset=-1 datalen=8

Надеюсь это поможет!

Другие вопросы по теме