This is a new question from my original question found: How to Bind manually to a BlueTooth Low Energy Device in a WinForm using C#?
Using: Windows 10, C# .Net 2015 Community, WinForms App.
The app currently handles the below features without problem:
1) receive the BLE advertisements for BLE that are both Bound and unbound to windows.
2) I can then,through a advertisment callback, connect to the advertising BLE and either Bind to it via code or Continue to the next step.
3) Retrieve all GATT services and corresponding Characteristics and Descriptors.
Let me explain the custom device: It is a TI SmartRF06 Eval Board with the Ti CC2650BLE chip. The service works a lot like serial but is over BLE. The Ti device expects a single byte code. Based on that code it will run some function on the TI device and then return a result. The result will be a Byte[] that we have special classes that can take that in and parse out the data.
If we use a BLE2COMM type board and connect via serial it works like a snap since I just open a COMM port and use simple read/write commands.
It is supposed to also work through a GATT service. And this is where I am stuck.
Some more info:
for simple attributes like "Device Name" or "Device Firmware version" they have simple Characteristics in which I simply do a Characteristic.ReadValueAsync(). Look at the GATT services below. Anything that is of type "READ" or "READ/WRITE" read/write easily and I get the value when there is one.
So I understand that part.
It appears that the custom BLE device I am connecting too, according to the developer, has a custom GATT which is GUID: 9804c436-45ed-50e2-b577-c43ccb17079d. And sure enough if I look for the GatService using GetGattService I do see it and it has two characteristics (Notify/Indicate).
I read online that I need to write to the characteristic and setup a callback for the returned data.
I have hooked up the callback like:
1:await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); //1
2:characteristic.ValueChanged += stData_ValueChanged; //2
3:DataWriter writer = new DataWriter(); //3
4:writer.WriteBytes(new byte[] { 0x01 }); //4
5:var buf = writer.DetachBuffer(); //5
6:WriteRslt = await characteristic.WriteValueAsync(buf,GattWriteOption.WriteWithResponse); //6
So, after the above fires I expect my "stData_ValueChanged" function to fire off. And it does not. Also, the lines 1 and 5 fail. In my code I wrap them in a try/catch.
Errors:
WriteClientChar Error:The attribute value length is invalid for the operation. (Exception from HRESULT: 0x8065000D)
Writing Bytes: Result(bad): Error:The attribute value length is invalid for the operation. (Exception from HRESULT: 0x8065000D)
I did try different lengths of Byte[] lengths.
Here is the actual code:
private async void BtAddRx2(BluetoothLEAdvertisementWatcher bw, BluetoothLEAdvertisementReceivedEventArgs args)
{
// BluetoothDevice btDevice;
if (bw.Status != BluetoothLEAdvertisementWatcherStatus.Started) return; //Can't run this is already stopped.
bw.Stop();
device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
if (device.DeviceInformation.Pairing.IsPaired == false)
{
var handlerPairingRequested = new TypedEventHandler<DeviceInformationCustomPairing, DevicePairingRequestedEventArgs>(handlerPairingReq);
device.DeviceInformation.Pairing.Custom.PairingRequested += handlerPairingRequested;
var prslt = await device.DeviceInformation.Pairing.Custom.PairAsync(DevicePairingKinds.ProvidePin, DevicePairingProtectionLevel.None);
device.DeviceInformation.Pairing.Custom.PairingRequested -= handlerPairingRequested; //Don't need it anymore once paired.
System.Threading.Thread.Sleep(5000); //try 3 second delay.
device.Dispose();
device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
}
//Now Paired. Lets get all Chars
var GatService = device.GetGattService(Guid.Parse("9804c436-45ed-50e2-b577-c43ccb17079d"));
var GattChars = GatService.GetAllCharacteristics();
log("GattChars Count: " + GattChars.Count);
c1 = GattChars[0];
var d1 = c1.GetAllDescriptors()[0];
c2 = GattChars[1];
var d2 = c2.GetAllDescriptors()[0];
byte[] datarslt1, datarslt2;
log("d1 total Descs[0] :" + c1.GetAllDescriptors().Count);
log("d2 total Descs[0] :" + c2.GetAllDescriptors().Count);
//online examples state I should be able to write to the "Notify" Characterisitic which is C2.
//I happen to know that C2 is the one I want so below I will be refering to it only.
if (c2.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
{
//we have isolated the Notify Char.
log("Notify - Uuid: " + c2.Uuid);
IAsyncOperation<GattReadClientCharacteristicConfigurationDescriptorResult> cs2Char;
GattCommunicationStatus cs2;
try
{
cs2Char = c2.ReadClientCharacteristicConfigurationDescriptorAsync();
log("Read Client Chars: " + cs2Char.GetResults().ClientCharacteristicConfigurationDescriptor.ToString());
cs2 = await c2.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
catch (Exception eee)
{ log("WriteClientChar Error:" + eee.Message); }
c2.ValueChanged += stData_ValueChanged; //will alert us when data changes.
//set the notify enable flag per examples
GattCommunicationStatus WriteRslt = 0;
DataWriter writer = new DataWriter();
writer.WriteBytes(new byte[] { 0x01 });
var buf = writer.DetachBuffer();
try
{
log("Writting Bytes: ");
WriteRslt = await d2.WriteValueAsync(buf);
log("Result(good): " + WriteRslt.ToString());
}
catch (Exception ee)
{ log("Result(bad): " + WriteRslt.ToString() + " Error:" + ee.Message); }
}
}
This is where I am stuck. Below are the services/gatts that I pulled off the device using a simple WinFormApp on windows 10 using c# .net 4.5.
> Total Gatt services found: 4 Local Name: NASACPAD-1sd HEX: 4E 41 53
> 41 43 50 41 44 2D 31 73 64
> Gatt Device Address: 00001800-0000-1000-8000-00805f9b34fb
> Total Characteristics: 3
> Char: 00002a00-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a00-0000-1000-8000-00805f9b34fb
> Data returned : 4E 41 53 41 43 50 41 44 2D 31 73 64
> ASCII Value : NASACPAD-1sd
> Char: 00002a01-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a01-0000-1000-8000-00805f9b34fb
> Data returned : 00 00
> ASCII Value :
> Char: 00002a04-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a04-0000-1000-8000-00805f9b34fb
> Data returned : 50 00 A0 00 00 00 E8 03
> ASCII Value : P
> Gatt Device Address: 00001801-0000-1000-8000-00805f9b34fb
> Total Characteristics: 0 found it
> Gatt Device Address: 9804c436-45ed-50e2-b577-c43ccb17079d
> Total Characteristics: 2
> Char: 00002a1c-0000-1000-8000-00805f9b34fb CharProps: Indicate
> UUID: 00002a1c-0000-1000-8000-00805f9b34fb
> Total Descriptors: 1
> 12 Plain
> Char: 00002a1e-0000-1000-8000-00805f9b34fb CharProps: Notify
> UUID: 00002a1e-0000-1000-8000-00805f9b34fb
> Total Descriptors: 1
> 15 Plain
> Gatt Device Address: 0000180a-0000-1000-8000-00805f9b34fb
> Total Characteristics: 9
> Char: 00002a23-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a23-0000-1000-8000-00805f9b34fb
> Data returned : 00 00 00 00 00 00 00 00
> ASCII Value :
> Char: 00002a24-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a24-0000-1000-8000-00805f9b34fb
> Data returned : 4D 6F 64 65 6C 20 4E 75 6D 62 65 72
> ASCII Value : Model Number
> Char: 00002a25-0000-1000-8000-00805f9b34fb CharProps: Read, Write
> UUID: 00002a25-0000-1000-8000-00805f9b34fb
> Write Bytes: 30 30 30 30 30 30 30 31
> Data returned : 30 30 30 30 30 30 30 31
> ASCII Value : 00000001
> Char: 00002a26-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a26-0000-1000-8000-00805f9b34fb
> Data returned : 46 69 72 6D 77 61 72 65 20 52 65 76 69 73 69 6F 6E
> ASCII Value : Firmware Revision
> Char: 00002a27-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a27-0000-1000-8000-00805f9b34fb
> Data returned : 48 61 72 64 77 61 72 65 20 52 65 76 69 73 69 6F 6E
> ASCII Value : Hardware Revision
> Char: 00002a28-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a28-0000-1000-8000-00805f9b34fb
> Data returned : 30 2E 30 2E 33
> ASCII Value : 0.0.3
> Char: 00002a29-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a29-0000-1000-8000-00805f9b34fb
> Data returned : 4D 69 72 69 6F 6E 20 54 65 63 68 6E 6F 6C 6F 67 69 65 73
> ASCII Value : Mirion Technologies
> Char: 00002a2a-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a2a-0000-1000-8000-00805f9b34fb
> Data returned : FE 00 65 78 70 65 72 69 6D 65 6E 74 61 6C
> ASCII Value : experimental
> Char: 00002a50-0000-1000-8000-00805f9b34fb CharProps: Read
> UUID: 00002a50-0000-1000-8000-00805f9b34fb
> Data returned : 01 0D 00 00 00 10 01
> ASCII Value :
If you see the Guid:9804c436-45ed-50e2-b577-c43ccb17079d that is the one that I am supposed to use.
Can anyone give me an idea what is next? Maybe I should not be using GATT at all? although I am not aware of any other way to connect to a BLE device. I feel like the information for BLE and windows10 is very scarce. Much of it just repeats and points back to the same samples. I could not find a sample where a custom device acts as a server and simply sends data based on what value is written into a characteristic.