I would like to keep on reading characteristic/set value changed event handlers for characteristics from my BLE 4.0 device, by using the ValueChanged callback in Universal Windows Platform C# in Visual Studio 2017.
I followed some tutorial from these sites: Damian Blog's Windows Universal with BLE, Bluetooth Gatt's Git Hub, Bluetooth Generic Attribute Profile - Heart Rate Service and Dr. Jukka's mobile Blog on BLE. All of them are using ValueChanged and I have tried to follow what they did.
Unfortunately, instead of ValueChanged being triggered, I receive the following error when using the ValueChanged callback.
System.ArgumentException: 'Value does not fall within the expected range.'
This line of code is producing the error:
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
Here is more details of my source code:
NOTE: I am using COM 7 for my dongler and my program could discover the BLE's device name, and could discover the Uuid of the services and characteristics.
public List<string> serviceList = new List<string>();
public List<string> characteristicList = new List<string>();
public BluetoothLEDevice myDevice { get; set; }
public MainPage()
{
this.InitializeComponent();
}
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
// Find the com port
string selector = SerialDevice.GetDeviceSelector("COM7");
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);
if (devices.Count > 0)
{
var dialog = new MessageDialog("Com Device found");
await dialog.ShowAsync();
DeviceInformation deviceInfo = devices[0];
SerialDevice serialDevice = await SerialDevice.FromIdAsync(deviceInfo.Id);
serialDevice.BaudRate = 9600;
serialDevice.DataBits = 8;
serialDevice.StopBits = SerialStopBitCount.One;
serialDevice.Parity = SerialParity.None;
}
else
{
MessageDialog popup = new MessageDialog("Sorry, no device found.");
await popup.ShowAsync();
}
// After com port is found, search for device
foreach (DeviceInformation di in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelector()))
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromIdAsync(di.Id);
// Display BLE device name
var dialogBleDeviceName = new MessageDialog("BLE Device Name " + bleDevice.Name);
await dialogBleDeviceName.ShowAsync();
myDevice = bleDevice;
}
// Check device connection
myDevice.ConnectionStatusChanged += OnConnectionStatusChanged;
foreach (var service in myDevice.GattServices)
{
serviceList.Add(service.Uuid.ToString());
// Verify if service is discovered by displaying a popup
MessageDialog serviceUuidPopUp = new MessageDialog("Adding Service Uuid to list " + service.Uuid.ToString() );
await serviceUuidPopUp.ShowAsync();
foreach (var characteristic in service.GetAllCharacteristics())
{
var characteristicUuid = characteristic.Uuid.ToString().ToLowerInvariant();
characteristicList.Add(characteristicUuid);
// Verify if characteristic is discovered by displaying a popup
MessageDialog charUuidPopUp = new MessageDialog("Adding characteristic Uuid to list " + characteristicUuid);
await charUuidPopUp.ShowAsync();
// set value changed event handlers for characteristics
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
}
}
}
private void OnConnectionStatusChanged(BluetoothLEDevice sender, object args)
{
if (sender.ConnectionStatus == BluetoothConnectionStatus.Connected)
{
System.Diagnostics.Debug.WriteLine("Connected");
}
else
{
System.Diagnostics.Debug.WriteLine("Disconnected");
}
}
private void Oncharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
byte[] data = new byte[args.CharacteristicValue.Length];
DataReader.FromBuffer(
args.CharacteristicValue).ReadBytes(data);
string text = Encoding.UTF8.GetString(data, 0, data.Length);
}
UPDATE 1 I tried to check Characteristic Properties before set value changed event handlers for my characteristics by following the answer given by rudi belt on SO.
if (characteristic.CharacteristicProperties == (GattCharacteristicProperties.Read | GattCharacteristicProperties.Notify))
{
characteristic.ValueChanged += Oncharacteristic_ValueChanged;
}
Unfortunately, this IF statement is not executed.
UPDATE 2 I have tried to remove ALL the codes inside Oncharacteristic_ValueChanged method. But it still gives me the same error
System.ArgumentException: 'Value does not fall within the expected range.'
I have been spending a lot of time trying to solve this problem. I will be very happy if anyone can help me on this. Thank you!