Bluetooth low energy-Программирование windows
Я новичок в разработке приложений для Windows. В настоящее время я работаю над проектом по написанию коммуникационного уровня с использованием Bluetooth low energy, который должен работать как на windows 8.1, так и на windows 10. Ниже приведен код, который я использовал для запуска списка служб BLE,
#include "stdafx.h" #include <stdio.h> #include <windows.h> #include <setupapi.h> #include <devguid.h> #include <regstr.h> #include <bthdef.h> #include <bluetoothleapis.h> #pragma comment(lib, "SetupAPI") #pragma comment(lib, "BluetoothApis.lib") #define TO_SEARCH_DEVICE_UUID "{0000b81d-0000-1000-8000-00805f9b34fb}" void EventNotif(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context) { printf("notification obtained "); PBLUETOOTH_GATT_VALUE_CHANGED_EVENT ValueChangedEventParameters = (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT)EventOutParameter; HRESULT hr; if (0 == ValueChangedEventParameters->CharacteristicValue->DataSize) { hr = E_FAIL; printf("datasize 0\n"); } else { printf("char "); unsigned heart_rate; if (0x01 == (ValueChangedEventParameters->CharacteristicValue->Data[0] & 0x01)) { heart_rate = ValueChangedEventParameters->CharacteristicValue->Data[1] * 256 + ValueChangedEventParameters->CharacteristicValue->Data[2]; } else { heart_rate = ValueChangedEventParameters->CharacteristicValue->Data[1]; } printf("%d\n", heart_rate); } } HANDLE GetBLEHandle(__in GUID AGuid) { HDEVINFO hDI; SP_DEVICE_INTERFACE_DATA did; SP_DEVINFO_DATA dd; GUID BluetoothInterfaceGUID = AGuid; HANDLE hComm = NULL; hDI = SetupDiGetClassDevs(&BluetoothInterfaceGUID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (hDI == INVALID_HANDLE_VALUE) return NULL; did.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); dd.cbSize = sizeof(SP_DEVINFO_DATA); for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDI, NULL, &BluetoothInterfaceGUID, i, &did); i++) { SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData; DeviceInterfaceDetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); DWORD size = 0; if (!SetupDiGetDeviceInterfaceDetail(hDI, &did, NULL, 0, &size, 0)) { int err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) break; PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, size); pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail(hDI, &did, pInterfaceDetailData, size, &size, &dd)) break; hComm = CreateFile( pInterfaceDetailData->DevicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); GlobalFree(pInterfaceDetailData); } } SetupDiDestroyDeviceInfoList(hDI); return hComm; } int main(int argc, char *argv[], char *envp[]) { GUID AGuid; CLSIDFromString(TEXT(TO_SEARCH_DEVICE_UUID), &AGuid); HANDLE hLEDevice = GetBLEHandle(AGuid); USHORT serviceBufferCount; HRESULT hr = BluetoothGATTGetServices( hLEDevice, 0, NULL, &serviceBufferCount, BLUETOOTH_GATT_FLAG_NONE); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { printf("BluetoothGATTGetServices - Buffer Size %d", hr); } PBTH_LE_GATT_SERVICE pServiceBuffer = (PBTH_LE_GATT_SERVICE) malloc(sizeof(BTH_LE_GATT_SERVICE) * serviceBufferCount); if (NULL == pServiceBuffer) { printf("pServiceBuffer out of memory\r\n"); } else { RtlZeroMemory(pServiceBuffer, sizeof(BTH_LE_GATT_SERVICE) * serviceBufferCount); } USHORT numServices; hr = BluetoothGATTGetServices( hLEDevice, serviceBufferCount, pServiceBuffer, &numServices, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetServices - Buffer Size %d", hr); } USHORT charBufferSize; hr = BluetoothGATTGetCharacteristics( hLEDevice, pServiceBuffer, 0, NULL, &charBufferSize, BLUETOOTH_GATT_FLAG_NONE); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { printf("BluetoothGATTGetCharacteristics - Buffer Size %d", hr); } PBTH_LE_GATT_CHARACTERISTIC pCharBuffer; if (charBufferSize > 0) { pCharBuffer = (PBTH_LE_GATT_CHARACTERISTIC) malloc(charBufferSize * sizeof(BTH_LE_GATT_CHARACTERISTIC)); if (NULL == pCharBuffer) { printf("pCharBuffer out of memory\r\n"); } else { RtlZeroMemory(pCharBuffer, charBufferSize * sizeof(BTH_LE_GATT_CHARACTERISTIC)); } USHORT numChars; hr = BluetoothGATTGetCharacteristics( hLEDevice, pServiceBuffer, charBufferSize, pCharBuffer, &numChars, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetCharacteristics - Actual Data %d", hr); } if (numChars != charBufferSize) { printf("buffer size and buffer size actual size mismatch\r\n"); } } PBTH_LE_GATT_CHARACTERISTIC currGattChar; for (int ii = 0; ii <charBufferSize; ii++) { currGattChar = &pCharBuffer[ii]; USHORT charValueDataSize; PBTH_LE_GATT_CHARACTERISTIC_VALUE pCharValueBuffer; USHORT descriptorBufferSize; hr = BluetoothGATTGetDescriptors( hLEDevice, currGattChar, 0, NULL, &descriptorBufferSize, BLUETOOTH_GATT_FLAG_NONE); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { printf("BluetoothGATTGetDescriptors - Buffer Size %d", hr); } PBTH_LE_GATT_DESCRIPTOR pDescriptorBuffer; if (descriptorBufferSize > 0) { pDescriptorBuffer = (PBTH_LE_GATT_DESCRIPTOR) malloc(descriptorBufferSize * sizeof(BTH_LE_GATT_DESCRIPTOR)); if (NULL == pDescriptorBuffer) { printf("pDescriptorBuffer out of memory\r\n"); } else { RtlZeroMemory(pDescriptorBuffer, descriptorBufferSize); } //////////////////////////////////////////////////////////////////////////// // Retrieve Descriptors //////////////////////////////////////////////////////////////////////////// USHORT numDescriptors; hr = BluetoothGATTGetDescriptors( hLEDevice, currGattChar, descriptorBufferSize, pDescriptorBuffer, &numDescriptors, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetDescriptors - Actual Data %d", hr); } if (numDescriptors != descriptorBufferSize) { printf("buffer size and buffer size actual size mismatch\r\n"); } for (int kk = 0; kk<numDescriptors; kk++) { PBTH_LE_GATT_DESCRIPTOR currGattDescriptor = &pDescriptorBuffer[kk]; //////////////////////////////////////////////////////////////////////////// // Determine Descriptor Value Buffer Size //////////////////////////////////////////////////////////////////////////// USHORT descValueDataSize; hr = BluetoothGATTGetDescriptorValue( hLEDevice, currGattDescriptor, 0, NULL, &descValueDataSize, BLUETOOTH_GATT_FLAG_NONE); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { printf("BluetoothGATTGetDescriptorValue - Buffer Size %d", hr); } PBTH_LE_GATT_DESCRIPTOR_VALUE pDescValueBuffer = (PBTH_LE_GATT_DESCRIPTOR_VALUE)malloc(descValueDataSize); if (NULL == pDescValueBuffer) { printf("pDescValueBuffer out of memory\r\n"); } else { RtlZeroMemory(pDescValueBuffer, descValueDataSize); } //////////////////////////////////////////////////////////////////////////// // Retrieve the Descriptor Value //////////////////////////////////////////////////////////////////////////// hr = BluetoothGATTGetDescriptorValue( hLEDevice, currGattDescriptor, (ULONG)descValueDataSize, pDescValueBuffer, NULL, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetDescriptorValue - Actual Data %d", hr); } if (currGattDescriptor->AttributeHandle < 255) { BTH_LE_GATT_DESCRIPTOR_VALUE newValue; RtlZeroMemory(&newValue, sizeof(newValue)); newValue.DescriptorType = ClientCharacteristicConfiguration; newValue.ClientCharacteristicConfiguration.IsSubscribeToNotification = TRUE; hr = BluetoothGATTSetDescriptorValue( hLEDevice, currGattDescriptor, &newValue, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetDescriptorValue - Actual Data %d", hr); } else { printf("setting notification for serivice handle %d\n", currGattDescriptor->ServiceHandle); } } } } BLUETOOTH_GATT_EVENT_HANDLE EventHandle; if (currGattChar->IsNotifiable) { printf("Setting Notification for ServiceHandle %d\n", currGattChar->ServiceHandle); BTH_LE_GATT_EVENT_TYPE EventType = CharacteristicValueChangedEvent; BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION EventParameterIn; EventParameterIn.Characteristics[0] = *currGattChar; EventParameterIn.NumCharacteristics = 1; //hr = BluetoothGATTRegisterEvent( //hLEDevice, //EventType, //&EventParameterIn, //EventNotif, //NULL, //&EventHandle, //BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTRegisterEvent - Actual Data %d", hr); } } if (currGattChar->IsReadable) { hr = BluetoothGATTGetCharacteristicValue( hLEDevice, currGattChar, 0, NULL, &charValueDataSize, BLUETOOTH_GATT_FLAG_NONE); if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) { printf("BluetoothGATTGetCharacteristicValue - Buffer Size %d", hr); } pCharValueBuffer = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(charValueDataSize); if (NULL == pCharValueBuffer) { printf("pCharValueBuffer out of memory\r\n"); } else { RtlZeroMemory(pCharValueBuffer, charValueDataSize); } hr = BluetoothGATTGetCharacteristicValue( hLEDevice, currGattChar, (ULONG)charValueDataSize, pCharValueBuffer, NULL, BLUETOOTH_GATT_FLAG_NONE); if (S_OK != hr) { printf("BluetoothGATTGetCharacteristicValue - Actual Data %d", hr); } //print the characeteristic Value printf("\n Printing a read (not notifiable) characterstic (maybe) body sensor value"); for (int iii = 0; iii< pCharValueBuffer->DataSize; iii++) {// ideally check ->DataSize before printing printf("%d", pCharValueBuffer->Data[iii]); } printf("\n"); free(pCharValueBuffer); pCharValueBuffer = NULL; } } while (1) { Sleep(1000); //printf("look for notification\n"); UCHAR dataBuffer[sizeof(int)]; BTH_LE_GATT_CHARACTERISTIC_VALUE newValue; newValue.DataSize = 4; newValue.Data[0] = 1234; if (hr != S_OK) { printf("Failed to write characteristic\n"); } } CloseHandle(hLEDevice); if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS) { return 1; } return 0; }
Код успешно скомпилирован и работает в режиме отладки. Однако ближайшие услуги BLE не перечислены. Кроме того, когда я закрываю приложение из режима отладки, я получаю следующие ошибки в консоли отладки,
onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(164)\BluetoothApis.dll!5177642F: (caller: 51773B3A) ReturnHr(1) tid(2094) 80070006 The handle is invalid. onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(164)\BluetoothApis.dll!5177642F: (caller: 51773B3A) ReturnHr(2) tid(2094) 80070006 The handle is invalid. onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(308)\BluetoothApis.dll!51775956: (caller: 517739ED) ReturnHr(3) tid(2094) 80070006 The handle is invalid.
Что я уже пробовал:
Моя среда разработки-VS 2017 на Windows 10.
Пожалуйста, помогите мне разобраться в этом вопросе