Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read issue after polling characteristics #65

Open
Sobattan opened this issue May 30, 2024 · 3 comments
Open

Read issue after polling characteristics #65

Sobattan opened this issue May 30, 2024 · 3 comments

Comments

@Sobattan
Copy link

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
Copy link
Owner

adabru commented Jun 2, 2024

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: #45 (comment)

Good luck :)

@Sobattan
Copy link
Author

Sobattan commented Jun 4, 2024

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
Copy link
Owner

adabru commented Jun 8, 2024

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

Concerning the ReadDataAsync function:

  • The first lock_guard seems redundant, you should be able to remove it.
  • There is no error reporting for the case that it fails.
  • If the data is not a string, it might not work. I would do the string decoding in Unity.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants