Closed tufeixp closed 2 years ago
Maybe related: https://github.com/adabru/BleWinrtDll/issues/7, https://github.com/adabru/BleWinrtDll/issues/19, https://github.com/adabru/BleWinrtDll/issues/21, https://github.com/adabru/BleWinrtDll/issues/20
Hi @tufeixp, the error message could help you.
Hi @adabru , I have ran the Microsoft sample project and it does not have this problem, would you please help me to debug this issue 'cause I'm really not good at C++ coding :-|
I have ran the Microsoft sample project and it does not have this problem
This seems like a good start.
Do you receive any error message? Also make sure that you use the version after February with the ui fix (https://github.com/adabru/BleWinrtDll/pull/25).
Sure, I have the ui fix. The error message is as simple as "Subscribe Characteristic catch: The attribute cannot be written"
I did a short google, maybe this can help: https://stackoverflow.com/questions/50596561/writeclientcharacteristicconfigurationdescriptorasync-not-working-in-uwp#50604121
You can also compare the subscribing code (https://github.com/adabru/BleWinrtDll/blob/main/BleWinrtDll/BleWinrtDll.cpp#L482) to the winrt code of the Microsoft sample.
For faster debugging you may consider using the DebugBle program. You can also print to the console from the dll like in https://github.com/adabru/BleWinrtDll/blob/main/BleWinrtDll/BleWinrtDll.cpp#L108.
Thanks @adabru I looked into the code, and find it's my miss-understanding lead me to the question, that read-only params eg. the serial infor can Not be "notified" other than query. I understand the current code does not implement a query method, and I tried to code in Cpp and able to read the correct info I need, however, due to my lacking of coding experience, the code will freeze and fail to pass over the data to C#, here's my simple code:
fire_and_forget ReadDataAsync(BLEData data) { { lock_guard lock(characteristicQueueLock); } auto characteristic = co_await retrieveCharacteristic(data.deviceId, data.serviceUuid, data.characteristicUuid); GattReadResult result = co_await characteristic.ReadValueAsync(); if (result.Status() == GattCommunicationStatus::Success) { auto dataReader = DataReader::FromBuffer(result.Value()); auto output = dataReader.ReadString(dataReader.UnconsumedBufferLength());
Characteristic charStruct;
wcscpy_s(charStruct.uuid, sizeof(charStruct.uuid) / sizeof(wchar_t), to_hstring(characteristic.Uuid()).c_str());
wcscpy_s(charStruct.userDescription, sizeof(charStruct.userDescription) / sizeof(wchar_t), output.c_str());
{
lock_guard queueGuard(characteristicQueueLock);
characteristicQueue.push(charStruct);
characteristicQueueSignal.notify_one();
}
saveError(L"%s:%d read done: %s", __WFILE__, __LINE__, charStruct.userDescription);
}
}
void ReadData(BLEData data) { ReadDataAsync(data); }
Glad you found the problem! Do you want a blocking, a non-blocking, or an optionally blocking read function?
A none blocking read function is needed~
Ok. The code actually already looks quite nice.
The first lock_guard looks redundant?
I guess you can use dataQueue instead of characteristicQueue. You could also reuse the function PollData without modification. Furthermore you would have more space for your data. The size limit could be a reason for the crash.
And maybe a try catch would be helpful to prevent a freeze.
Here's the code finally works:
fire_and_forget ReadDataAsync(BLEData data) {
{
lock_guard lock(dataQueueLock);
}
auto characteristic = co_await retrieveCharacteristic(data.deviceId, data.serviceUuid, data.characteristicUuid);
GattReadResult result = co_await characteristic.ReadValueAsync();
if (result.Status() == GattCommunicationStatus::Success) {
auto dataReader = DataReader::FromBuffer(result.Value());
auto output = dataReader.ReadString(dataReader.UnconsumedBufferLength());
BLEData data;
wcscpy_s(data.characteristicUuid, sizeof(data.characteristicUuid) / sizeof(wchar_t), to_hstring(characteristic.Uuid()).c_str());
wcscpy_s(data.serviceUuid, sizeof(data.serviceUuid) / sizeof(wchar_t), to_hstring(characteristic.Service().Uuid()).c_str());
wcscpy_s(data.deviceId, sizeof(data.deviceId) / sizeof(wchar_t), characteristic.Service().Device().DeviceId().c_str());
data.size = output.size();
memcpy(data.buf, output.data(), data.size);
{
lock_guard queueGuard(dataQueueLock);
dataQueue.push(data);
dataQueueSignal.notify_one();
}
//saveError(L"%s:%d read done: %s", __WFILE__, __LINE__, output.c_str());
}
}
it's working when query fe55 / 0001 bytes from a google daydream controller, but, report failure in SubscribeCharacteristicAsync() / characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(), when I'm trying to get data from 180a / 2a25 (or 180f/2a29 which is the 1 byte battery data), which was supposed to be a string of some 34 bytes serial numbers. Would you help me to figure out why?