BLE Indicate UWP GATT Client

925 Views Asked by At

I was wondering, if there is a problem with the UWP Bluetooth API and Indicate. If I understand the documentation correctly UWP will handle the Acknowledgment of a received Indicate package. But for some reason, the sample code works for notifys but not for indicates. I am trying this with a Myo Wristband. I can receive notifications via notify characteristics but not via the indicates one. Unfortunately I have to use indicate.

I changed the sample code a little bit to this, but its not working:

GattCommunicationStatus status = await selectedCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
    GattClientCharacteristicConfigurationDescriptorValue.Indicate);

if(status == GattCommunicationStatus.Success)
{
    // Server has been informed of clients interest.
}

and the Handler stays the same:

characteristic.ValueChanged += Characteristic_ValueChanged;
// ... 
void Characteristic_ValueChanged(GattCharacteristic sender, 
                                    GattValueChangedEventArgs args)
{
    // An Indicate or Notify reported that the value has changed.
    var reader = DataReader.FromBuffer(args.CharacteristicValue)
    // Parse the data however required.
}

Any ideas what I am doing wrong? The device is connected and correctly programed, it sends the notifications.

Thanks in Advance for any help

Marcel

2

There are 2 best solutions below

1
On BEST ANSWER

I found the answer to my question. It was not a problem of UWP, but of the Myo. The code above works for Indicate, just change the notify to indicate and your good to go.

For everyone else in the future. I was making a mistake with the command bytes. I misunderstood the Bluetooth Header file and thought that the payload equals the command, but it not like that. So after each command byte you have to send the amount bytes, you give as "argument". This is the payload. Its said in the header, but I somehow missed it.

So for example, to set the myo to EMG_none, IMU_send_all, Classifier_Enabled you have to send this byte to the CommandCharacteristic:

01 03 00 03 01

where the first 01 is the set_mode, the first 03 the payload (3 "Arguments"), the 00 the EMG_none, the second 03 the IMU_send_all, the last 01 the Classifier_enabled.

Wished they had made an example command on their tutorial :-)

The full header can be found here: https://github.com/thalmiclabs/myo-bluetooth/blob/master/myohw.h

and a short explanation here: http://developerblog.myo.com/myo-bluetooth-spec-released/

Hope that will help someone.

2
On

Not all characteristic are Indicate.

I do not have a MYO, but did some research and found a list with the characteristics of the MYO:

ControlService 0x0001 Myo info service

MyoInfoCharacteristic 0x0101 Serial number for this Myo and various parameters which are specific to this firmware. Read-only attribute.

FirmwareVersionCharacteristic 0x0201 Current firmware version. Read-only characteristic.

CommandCharacteristic 0x0401 Issue commands to the Myo. Write-only characteristic.

ImuDataService 0x0002 IMU service

IMUDataCharacteristic 0x0402 Notify-only characteristic.

MotionEventCharacteristic 0x0502 Motion event data. Indicate-only characteristic.

ClassifierService 0x0003 Classifier event service.

ClassifierEventCharacteristic 0x0103 Classifier event data. Indicate-only characteristic.

EmgDataService 0x0005 Raw EMG data service.

EmgData0Characteristic 0x0105 Raw EMG data. Notify-only characteristic.

EmgData1Characteristic 0x0205 Raw EMG data. Notify-only characteristic.

EmgData2Characteristic 0x0305 Raw EMG data. Notify-only characteristic.

EmgData3Characteristic 0x0405 Raw EMG data. Notify-only characteristic.

BatteryService 0x180f Battery service

BatteryLevelCharacteristic 0x2a19 Current battery level information. Read/notify characteristic.

DeviceName 0x2a00 Device name data. Read/write characteristic.

Also it is better to use Ibuffer instead of the DataReader. I think the data send by the MYO is BigEndian. With Ibuffer is is easier to change encoding. Here is an axample how to use Ibuffer:

    private async void Characteristic_ValueChanged(GattCharacteristic sender,GattValueChangedEventArgs args)
      {         
         var newValue = FormatValue(args.CharacteristicValue);
         await Task.Run(() => Process_received(newValue));
  }

 private string FormatValue(IBuffer buffer)//using Windows.Storage.Streams;
      {
          CryptographicBuffer.CopyToByteArray(buffer, out byte[] data);//using Windows.Security.Cryptography;
         try
         {
           // return Encoding.BigEndianUnicode.GetBytes(data) gives char array
           // return Encoding.UTF32.GetString(data)
            return Encoding.ASCII.GetString(data);
         }
         catch (ArgumentException)
         {
            return "Unknown format";
         }
      }