BLE Indicate UWP GATT Client - notifications

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

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";
}
}

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.

Related

gRPC and C#: receive message bigger than maximum allowed

I am doing some test to request some data to a remote database from a client. For that, I have a client gRPC that call a method in the gRPC, this gRPC server use EF to get the data and send the result to the client.
Well, in my case, I get about 3MB of data, that is higher than the default maximum size allowed for the channel.
I know that I can resolve the problem when I create the channel in the client, in this way, for example, to 60 mb:
var channel = GrpcChannel.ForAddress("http://localhost:5223",
new GrpcChannelOptions
{
MaxReceiveMessageSize = 62914560,
MaxSendMessageSize = 62914560,
});
But although I can increase this when I create the channel, I can't ensure that some query returns more data than the maximum allowed.
So I would like to know how I can handle this.
In this case, the method is unaray, it is not a stream.
Thanks.

ReactNative: decoding the characteristic value received from BLE is not working

I am building a ReactNative application that will receive the data from another machine/ device via BLE. I am using this package, https://www.npmjs.com/package/react-native-ble-plx to implement the BLE logic. Now, I am having a problem decoding the characteristic value that I received from the monitor function.
This is my code
char.monitor((err, cha) => {
if (err) {
console.log("Monitoring error");
console.log(err);
return
}
console.log("char data received")
console.log(base64.decode(cha.value))
console.log(cha.value)
})
When the data is received, as you can see I am base64-decoding it to get its original value. But it seems that the data is not decoded into the right format.
For example,
This is the original value
/hkABQAAMgAA//9kIwAAAACqAAEAAAAAigMAAA==
But it is decoded into the following value.
þ↓♣2ÿÿd#ª☺Š♥
As you can see it is not readable at all. The decoded value even contains the weird characters. I am using this ReactNative base64 package, https://www.npmjs.com/package/react-native-base64. What is missing in my code and how can I fix it?
This is the service UUID, 00001826-0000-1000-8000-00805F9B34FB and this is the characteristic UUID, 00002AD1-0000-1000-8000-00805F9B34FB.
Also, this documentation might be useful because I am trying to receive data from WaterRower machine, https://github.com/WaterRower-UK/WaterRowerData-iOS/blob/master/Sources/WaterRowerData-BLE/FTMS_v1.0.pdf.

Can I allow multiple http clients to consume a Flowable stream of data with resteasy-rxjava2 / quarkus?

Currently I am able to see the streaming values exposed by the code below, but only one http client will receive the continuous stream of values, the others will not be able to.
The code, a modified version of the quarkus quickstart for kafka reactive streaming is:
#Path("/migrations")
public class StreamingResource {
private volatile Map<String, String> counterBySystemDate = new ConcurrentHashMap<>();
#Inject
#Channel("migrations")
Flowable<String> counters;
#GET
#Path("/stream")
#Produces(MediaType.SERVER_SENT_EVENTS) // denotes that server side events (SSE) will be produced
#SseElementType("text/plain") // denotes that the contained data, within this SSE, is just regular text/plain data
public Publisher<String> stream() {
Flowable<String> mainStream = counters.doOnNext(dateSystemToCount -> {
String key = dateSystemToCount.substring(0, dateSystemToCount.lastIndexOf("_"));
counterBySystemDate.put(key, dateSystemToCount);
});
return fromIterable(counterBySystemDate.values().stream().sorted().collect(Collectors.toList()))
.concatWith(mainStream)
.onBackpressureLatest();
}
}
Is it possible to make any modification that would allow multiple clients to consume the same data, in a broadcast fashion?
I guess this implies letting go of backpressure, because that would imply a state per consumer?
I saw that Observable is not accepted as a return type in the resteasy-rxjava2 for the Server Side Events media-tpe.
Please let me know any ideas,
Thank you
Please find the full code in Why in multiple connections to PricesResource Publisher, only one gets the stream?

Best way to build a "task queue" with RxJava

Currently I'm working on a lot of network-related features. At the moment, I'm dealing with a network channel that allows me to send 1 single piece of information at a time, and I have to wait for it to be acknowledged before I can send the next piece of information. I'm representing the server with 1..n connected clients.
Some of these messages, I have to send in chunks, which is fairly easy to do with RxJava. Currently my "writing" method looks sort of like this:
fun write(bytes: ByteArray, ignoreMtu: Boolean) =
server.deviceList()
.first(emptyList())
.flatMapObservable { devices ->
Single.fromCallable {
if (ignoreMtu) {
bytes.size
} else {
devices.minBy { device -> device.mtu }?.mtu ?: DEFAULT_MTU
}
}
.flatMapObservable { minMtu ->
Observable.fromIterable(bytes.asIterable())
.buffer(minMtu)
}
.map { it.toByteArray() }
.doOnNext { server.currentData = bytes }
.map { devices }
// part i've left out: waiting for each device acknowledging the message, timeouts, etc.
}
What's missing in here is the part where I only allow one piece of information to be sent at the same time. Also, what I require is that if I'm adding a message into my queue, I have to be able to observe the status of only this message (completed, error).
I've thought about what's the most elegant way to achieve this. Solutions I've came up with include for example a PublishSubject<ByteArray> in which I push the messages (queue-like), add a subscriber and observe it - but this would throw for example onError if the previous message failed.
Another way that crossed my mind was to give each message a number upon creating / queueing it, and have a global "message-counter" Observable which I'd hook into the chain's beginning with a filter for the currently sent message == MY_MESSAGE_ID. But this feels kind of fragile. I could increment the counter whenever the subscription terminates, but I'm sure there must be a better way to achieve my goal.
Thanks for your help.
For future reference: The most straight-forward approach I've found is to add a scheduler that's working on a single thread, thus working each task sequential.

How to fetch fieldname and structure for additional properties in operation, managedObject etc

I am trying to figure out which fragments are related to operation:
managedObject
event
measurement
alarm
So , Is there a way to get all these fragments ?
Also there are additional Properties for which field name is defined as * and the value can be an Object or anything else(*). I have gone through the device management library and sensor library in cumulocity documentation but found it does not contain all the possible fragments and there is no clarity as in which object the fragment goes i.e does it go in operation or managedObject, or both?
Since every user, device and application can contribute such fragments, there is no "global list" of them that you could refer to. Normally, a client (application, device) knows what data it sends or what data it requests, so it's also in most cases not required.
Regarding the relationship between operations and managed objects, there are some typical design pattern. Let's say you want to configure something in a device, like a polling interval:
"mydevice_Configuration": { "pollingRate": 60 }
What your application would do is to send that fragment as an operation to a device:
POST /devicecontrol/operations HTTP/1.1
...
{
"deviceId": "12345",
"mydevice_Configuration": { "pollingRate": 60 }
}
The device would accept the operation (http://cumulocity.com/guides/rest/device-integration/#step-6-finish-operations-and-subscribe) and change its configuration. When it does that successfully, it will update its managed object to contain the new configuration:
PUT /inventory/managedObjects/12345 HTTP/1.1
{
"mydevice_Configuration": { "pollingRate": 60 }
}
This way, your inventory reflects as closely as possible the true state of devices.
Hope that helps ...