Velorexe / Unity-Android-Bluetooth-Low-Energy

A Unity Android plugin to support basic Bluetooth Low Energy interactions.
The Unlicense
101 stars 21 forks source link

How to Read Data From a Characteristic #20

Closed Boodums closed 1 year ago

Boodums commented 1 year ago

How do you access the data from the subscribed characteristic? I can see the data in Logcat but I haven't figured out how to access it within the program. I've tried overriding Command Received in the ReadFromCharacteristic class but that method was never called.

Velorexe commented 1 year ago

Hi @Boodums

I've written a branch for reading and writing this weekend, I'm still testing it out, but you can check it it works for you in the feature/read-and-write branch.

Boodums commented 1 year ago

Thank you! I'll check it out this evening.

Boodums commented 1 year ago

I apologize, my request was unclear. My Bluetooth knowledge is rusty. The Characteristic that I need to gather data on is a Notify Characteristic, not a Read Characteristic. It occurs every second. Your code on the main branch logs the characteristic data every second. The logs from Logcat are below. I need to subscribe to an event to collect the data.

2023/01/24 13:46:16.397 10030 10046 Info UnityAndroidBLE [3, -44, 0, 0, 0, 14, -84, -44, 0, 112, -69] 2023/01/24 13:46:17.435 10030 10046 Info UnityAndroidBLE [3, -44, 0, 0, 0, 14, -84, -44, 0, 112, -69] 2023/01/24 13:46:18.432 10030 10046 Info UnityAndroidBLE [3, -43, 0, 0, 0, 112, -83, -43, 0, -42, -63] 2023/01/24 13:46:19.410 10030 10046 Info UnityAndroidBLE [3, -42, 0, 0, 0, 127, -82, -42, 0, -68, -58] 2023/01/24 13:46:20.427 10030 10046 Info UnityAndroidBLE [3, -41, 0, 0, 0, 123, -81, -41, 0, 76, -53] 2023/01/24 13:46:21.425 10030 10046 Info UnityAndroidBLE [3, -41, 0, 0, 0, 123, -81, -41, 0, 76, -53] 2023/01/24 13:46:22.423 10030 10046 Info UnityAndroidBLE [3, -40, 0, 0, 0, 126, -80, -40, 0, -7, -49] 2023/01/24 13:46:23.420 10030 10046 Info UnityAndroidBLE [3, -39, 0, 0, 0, -112, -79, -39, 0, -19, -44] 2023/01/24 13:46:24.418 10030 10046 Info UnityAndroidBLE [3, -38, 0, 0, 0, -103, -78, -38, 0, -71, -39] 2023/01/24 13:46:25.415 10030 10046 Info UnityAndroidBLE [3, -37, 0, 0, 0, -73, -77, -37, 0, -29, -34] 2023/01/24 13:46:26.414 10030 10046 Info UnityAndroidBLE [3, -37, 0, 0, 0, -73, -77, -37, 0, -29, -34] 2023/01/24 13:46:27.411 10030 10046 Info UnityAndroidBLE [3, -37, 0, 0, 0, -73, -77, -37, 0, -29, -34]

Velorexe commented 1 year ago

Ah, if that's the case then you're looking for the SubscribeToCharacteristic command. This has a similar setup as the ReadFromCharacteristic command, but will stay running in the background after receiving a value. You'd want to set it up as follows:

// Replace "1101" and "2101" with your device's Service and Characteristic
_subscribeToCharacteristic = new SubscribeToCharacteristic(_deviceUuid, "1101", "2101", (byte[] data) => {
   //Use the byte[] data
   Debug.Log(data.Length);
});
BleManager.Instance.QueueCommand(_subscribeToCharacteristic);

Every command has different constructors, though undocumented, so I didn't touch on this one in my example code. Here's a link to the constructor that I'm using in the example above.

Boodums commented 1 year ago

This is exactly what I need. I feel foolish for not figuring this out on my own.

However when I run the code I get the following error.

FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

at System.Convert.FromBase64CharPtr (System.Char* inputPtr, System.Int32 inputLength) [0x0004c] in <05089c1b6989455fb1452c627044bac4>:0

at System.Convert.FromBase64String (System.String s) [0x00025] in <05089c1b6989455fb1452c627044bac4>:0

at Android.BLE.BleObject.GetByteMessage () [0x00000] in <6952539eeeb640668626a3e8f723d3c4>:0

at Android.BLE.Commands.SubscribeToCharacteristic.CommandReceived (Android.BLE.BleObject obj) [0x000c2] in <6952539eeeb640668626a3e8f723d3c4>:0

at Android.BLE.BleManager.OnBleMessageReceived (Android.BLE.BleObject obj) [0x00095] in <6952539eeeb640668626a3e8f723d3c4>:0

at Android.BLE.BleAdapter.OnBleMessage (System.String jsonMessage) [0x00047] in <6952539eeeb640668626a3e8f723d3c4>:0

I'm using a newer version of the Unity Editor (2021.3.16f1). I wonder if this is the issue.

Boodums commented 1 year ago

For reference the string that it's trying to convert from base64 is "CharacteristicValueChanged". It's not a multiple of 4.

Velorexe commented 1 year ago

Ah, I'm not sure what branch you're on, but that was indeed a mistake on my part and was also fixed in the feature/read-and-write branch.

I migrated the code from my thesis project wrong, so it's trying to convert the command to the byte[] that's passed to the callback. This instead should be the base64Message that's passed from the library to the Unity plugin.

If you're interested in the difference, this is the old implementation (main and development)

public byte[] GetByteMessage() => Convert.FromBase64String(command);

While it should have been (feature/read-and-write)

public string Base64Message { get => base64Message; }
[SerializeField]
private string base64Message = string.Empty;

public byte[] GetByteMessage() => Convert.FromBase64String(base64Message);
Boodums commented 1 year ago

I'll try it out.

BTW, in OnDeviceFound(string name, string device), the variables passed in are swapped. In other words, the name variable contains the device and vice versa.

Velorexe commented 1 year ago

Yeah I noticed that as well, should be fixed in the same branch that I mentioned above.

Boodums commented 1 year ago

It works well. Thanks again!

Velorexe commented 1 year ago

Glad that the branch worked for you! I'll merge it with development and main tomorrow.