adabru / BleWinrtDll

BLE for Unity 3d in Windows without UWP.
Do What The F*ck You Want To Public License
168 stars 52 forks source link

Read issue after polling characteristics #65

Open Sobattan opened 2 months ago

Sobattan commented 2 months ago

Hi @adabru,

Thank you a lot for this repo. I have a little problem, I am not a developer at first but for my project I have to increase my knowledge sorry if there is any approximation. I am trying to connect an arduino through the BLE to a Unity game. When I use the demo just to test if it's working, I can connect to my device, I found the service and the characteristic but I can't read the value. Nothing happens. I tried with the Microsoft's Bluetooth Low Energy sample. Which works until I reach the same step. When I read, I get a status saying : "Read Result : Unknown format". So I understand that there is no problem with the reading in itself but more with the variable inside the characteristic.

I am already able to read the Characteristic with another arduino so I think that the Characteristics is updating well.

On the arduino side, I tried by simply put in the main loop : int level = 10; MyChar.writeValue(level);

I know that the writeValue() method automatically convert level into unsigned char.

Do you think it is a problem ? Do you have any idea on how to handle this format with BleWinrtDll ?

Thank you a lot !!

adabru commented 2 months ago

Hi @Sobattan :),

ReadCharacteristic is not implemented in this dll, just SubscribeCharacteristic. You can add it yourself or use the subscription.

I think you are getting the error message from this line: https://github.com/microsoft/Windows-universal-samples/blob/0db108e/Samples/BluetoothLE/cs/Scenario2_Client.xaml.cs#L295 . It is inside the ReadCharacteristic function. You can use that function from the cpp part https://github.com/microsoft/Windows-universal-samples/blob/0db108e/Samples/BluetoothLE/cppwinrt/Scenario2_Client.cpp#L370 and port it over to BleWinrt .

Or you can take tufeixp's code by following this discussion: https://github.com/adabru/BleWinrtDll/issues/45#issuecomment-1479295183

Good luck :)

Sobattan commented 2 months ago

Hi @adabru ,

Thank you for your answer ! Really helpful, it is very difficult for me as i'm not a developer. So, for now, I'm trying to compile a dll with the tufeixp's code (already 2 days on it šŸ„² ) I put his function :

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());
    }
}

I compiled it into a dll following your README.md and put the resulting dll into the Unity project (same place as the previous dll). I added the following lines in the BleApi.cs :

[DllImport("BleWinrtDll.dll", EntryPoint = "ReadDataAsync")]
public static extern bool ReadDataAsync(in BLEData data);

And finally simply modified the Subscribe function as follow :

public void Subscribe()
    {
        // no error code available in non-blocking mode
        // BleApi.SubscribeCharacteristic(selectedDeviceId, selectedServiceId, selectedCharacteristicId, false);
        // isSubscribed = true;
        BleApi.BLEData data = new BleApi.BLEData();
        BleApi.ReadDataAsync(in data);
        subcribeText.text = data.ToString();
    }

From your point of view, does it look the right way to do it ? Like this, I have an error : EntryPointNotFoundException: ReadDataAsync assembly: type: member:(null)

Thank you so much for your help !

adabru commented 2 months ago

I think you're missing the entry in the BleWinrtDll.h file for ReadDataAsync.

Concerning the ReadDataAsync function:

I can't see how subscribeText is defined and passed to Unity. It might be easiest to use the dataQueue.

You can add an accompanying ReadData function to ReadDataAsync. Like SubscribeCharacteristic uses SubscribeCharacteristicAsync and like SendData is using SendDataAsync.

If you want you can fork this repo, make your changes and create a pull request. I can then comment on your code directly and when it's working and kinda matching the rest of the code we can merge it.