问题
I have a device with a custom service which sends sensor data in a very high rate using the BLE notification feature.
I'm using the the following API on a Windows 10 machine: https://msdn.microsoft.com/en-us/library/windows/hardware/jj159880(v=vs.85).aspx
I'm searching the device by the custom service ID using SetupDi API, and then "connect" to it using CreateFile.
When I pair the device with Windows for the first time it immediately shows "Connected" in the Bluetooth Settings window, and then when I run my app it works perfectly fine (I receive data at high rate). If I close my app it changes the status in the Settings window to "Paired" instead of connected (Which I assume is fine). When I open my app again it connects and changes the status in the Settings to "Connected" again but now I receive the data at a much lower rate for some reason. (the data itself is correct). If I disconnect it via the Bluetooth Settings windows by clicking "Remove Device" and then pair it again like I did before it works again at an high rate for the first time.
I know it's not a problem with the device itself because it works fine with Android and other BLE supported platforms.
Any idea what might causing this issue?
Here is the code I'm using:
GUID serviceGuid = StringToGUID(GEM_SERVICE_GUID);
HDEVINFO info = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA data;
data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
int i = 0;
while (SetupDiEnumDeviceInterfaces(info, NULL, &guid, i, &data))
{
i++;
}
if (GetLastError() != ERROR_NO_MORE_ITEMS)
{
// TODO throw
}
DWORD requiredSize;
if (!SetupDiGetDeviceInterfaceDetail(info, &data, NULL, 0, &requiredSize, NULL))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
// TODO throw
}
}
PSP_DEVICE_INTERFACE_DETAIL_DATA details = (PSP_DEVICE_INTERFACE_DETAIL_DATA)std::malloc(requiredSize);
details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(info, &data, details, requiredSize, NULL, NULL))
{
// TODO throw
}
m_service = CreateFile(details->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_service == INVALID_HANDLE_VALUE)
{
// TODO throw
return;
}
BTH_LE_GATT_CHARACTERISTIC combinedDataChar = FindCharacteristicByUUID(m_service, COMBINED_DATA_CHAR_HANDLE);
BTH_LE_GATT_DESCRIPTOR desc = FindDescriptorByType(m_service, &combinedDataChar, ClientCharacteristicConfiguration);
BTH_LE_GATT_DESCRIPTOR_VALUE val;
RtlZeroMemory(&val, sizeof(val));
val.DescriptorType = ClientCharacteristicConfiguration;
val.ClientCharacteristicConfiguration.IsSubscribeToNotification = TRUE;
HRESULT res = BluetoothGATTSetDescriptorValue(m_service, &desc, &val, BLUETOOTH_GATT_FLAG_NONE);
if (res != S_OK)
{
// TODO throw
}
BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION chars;
chars.NumCharacteristics = 1;
chars.Characteristics[0] = combinedDataChar;
res = BluetoothGATTRegisterEvent(m_service, CharacteristicValueChangedEvent, &chars, OnValueChanged, NULL, &m_registrationHandle, BLUETOOTH_GATT_FLAG_NONE);
if (res != S_OK)
{
// TODO throw
}
EDIT:
The code for the OnValueChanged
callback:
void OnValueChanged(BTH_LE_GATT_EVENT_TYPE eventType, PVOID eventOutParameter, PVOID context)
{
BLUETOOTH_GATT_VALUE_CHANGED_EVENT* e = (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)eventOutParameter;
std::cout << e->CharacteristicValue->DataSize << std::endl;
}
回答1:
I believe you receive data through OnValueChanged
callback? It's not provided in your code, and the problem could be somewhere inside it. If you hesitate to provide its code, I suggest that you perform the following experiments during the 'bad' session:
- Remove all of the code from it except for incrementing some counter to know the data rate.
- Measure CPU load. If it's nearing a full core load, you're CPU-bound.
- Use a profiler of your choice to check where your code spends time.
Now that the code for OnValueChanged
is available:
Output to console at high rate could be the bottleneck. I suggest that you only count events and output count once a few seconds, like that:
static DWORD lastTicks = GetTickCount(); static DWORD count = 0; count++; DWORD ticksElapsed = GetTickCount() - lastTicks; if (ticksElapsed > 5000) { std::cout << "Rate: " << (double(count) / ticksElapsed) << " / sec" << std::endl; lastTicks = GetTickCount(); count = 0; }
Do more tests (for example, 5 pairings, 5 connects after each pairing) and provide the event rates. It could happen that the drop in rate is actually related to something else, not re-pairing.
来源:https://stackoverflow.com/questions/32368370/bluetooth-low-energy-low-rate-on-windows