How comunicate with UART Transparent service BLE in xamarin - xamarin.forms

I'm trying to do an app with xamarin which can communicate with a chip rn4870. This BLE chip uses UART Transparent services. I'm new with bluetooth, so the most thing I read for do a communication with a ble device is to scan the device, connect it, looking for the service you want, get the characteristics and write,read or notify.
But, The most example I read, with heart rate device o smarthwath, the service is defined , for example a service for a battery, so, I can get the service, then the characteristic and read it. But with UART Transparent service, I get the 49535343-FE7D-4AE5-8FA9-9FAFD205E455 service to datatransfer, and then I get TX 49535343-1E4D-4BD9-BA61-23C647249616 and RX 49535343-8841-43F4-A8D4-ECBE34729BB3 characteristic but I don't know how to communicate.
Also I'm using plugin BLE of xamarin, with these plugin I can not see any particular function or documentation where I can use client/server functionality.
https://github.com/xabre/xamarin-bluetooth-le
So, if anyone has a idea how or which step I have to follow to can communicate with it and if you know how I could do it with xamarin, I will appreciate.
Thanks in advance.

You can handle the UART transparent service the same way you would handle a battery service.
Scan for available devices, even better if you use a filter to only find devices offering the UART service
adapter.DeviceDiscovered += (s,a) => deviceList.Add(a.Device);
await adapter.StartScanningForDevicesAsync(new[] { Guid.Parse("49535343-FE7D-4AE5-8FA9-9FAFD205E455"));
Connect to the device
try
{
await _adapter.ConnectToDeviceAsync(device);
}
catch(DeviceConnectionException e)
{
// ... could not connect to device
}
Get the UART service and both of the characteristics
var TX = await connectedDevice.GetServiceAsync(Guid.Parse("49535343-1E4D-4BD9-BA61-23C647249616"));
var RX = await connectedDevice.GetServiceAsync(Guid.Parse("49535343-8841-43F4-A8D4-ECBE34729BB3"));
Enable notifications on the TX characteristic to receive the answers and start writing to the RX characteristic
TX.ValueUpdated += (o, args) =>
{
// Do something with the received value
var bytes = args.Characteristic.Value;
};
await TX.StartUpdatesAsync();
await RX.WriteAsync(bytes);
If you want to test the connection and the communication procedure you can use a generic BLE scanner app such as nRF Connect. Use it to search for your device and you can read, write and activate notifications with it.
There is also a sample app using your xamarin plugin that offers this functionality:
check the ble status
discover devices
connect/disconnect
discover the services
discover the characteristics
see characteristic details
read/write and register for notifications of a characteristic

Related

How to enable notification and indications on Arduino nano 33 IOT BLE descriptor?

I am making BLE echo system between Arduino and Android.
I have finished to make read and write function. But I want Android can automatically detect value when BluetoothGattCharacteristic value change. So I made set notification on Android.
When I tried to check the fucntion is working properly or not, It was not working properly. And I use nRFConnect App to check what is the problem. the problem is the status of descriptor on Arduino is Notification and indications disabled. And I googled how to enable notification and indication on Arduino. But on the Arduino's document, I cannot find the function which can make enable descriptor's notification and indication. this is the document link. So is it possible to enable notification and indication on Arduino BLE??
Code of Arduino nano 33 IOT.
#include <ArduinoBLE.h>
BLEService echoService("00000000-0000-1000-8000-00805f9b34fb");
BLEStringCharacteristic charac ("741c12b9-e13c-4992-8a5e-fce46dec0bff", BLERead | BLEWrite | BLENotify,40);
BLEDescriptor Descriptor("beca6057-955c-4f8a-e1e3-56a1633f04b1","Descriptor");
String var = "";
void setup(){
Serial.begin(9600);
while(!Serial);
if(!BLE.begin()){
Serial.println("starting BLE failed.");
while(1);
}
BLE.setLocalName("Arduino BLE Echo");
BLE.setAdvertisedService(echoService);
charac.addDescriptor(Descriptor);
echoService.addCharacteristic(charac);
BLE.addService(echoService);
BLE.advertise();
Serial.println("Bluetooth device active, waiting for connections...");
Serial.println(" ");
}
void loop(){
BLEDevice central = BLE.central();
if(central){
Serial.println("* Connected to central device!");
Serial.print("Connected to central : ");
Serial.println(central.address());
Serial.println(" ");
while(central.connected()){
if(charac.written()){
var = charac.value();
Serial.println(String(var));
delay(500);
charac.writeValue(var);
Serial.println("write stringCharacteristic");
}
}
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
picture of nRFConnection APP.
You need to enable the notifications from the Android side in order to receive the BLE notifications. This is because according to the BLE specification, BLE notifications are disabled by default. If you want BLE notifications to remain enabled after the first time you enable them, you can bond with the Arduino device. This way, the status of the notification will persist across power cycles and disconnection/reconnection, and as soon as you reconnect to the Arduino device, notifications will be enabled by default (but again, you still have to enable them the first time).
This can be seen in the paragraph below (Bluetooth Specification v5.3, Vol 3, Part G, Section 3.3.3.3 - Clinet Characteristic Configuration - Page 1489):-
"The Client Characteristic Configuration declaration is an optional
characteristic descriptor that defines how the characteristic may be
configured by a specific client. The Client Characteristic
Configuration descriptor value shall be persistent across connections
for bonded devices. The Client Characteristic Configuration descriptor
value shall be set to the default value at each connection with
non-bonded devices.The characteristic descriptor value is a bit
field. When a bit is set, that action shall be enabled, otherwise it
will not be used. The Client Characteristic Configuration descriptor
may occur in any position within the characteristic definition after
the Characteristic Value. Only one Client Characteristic Configuration
declaration shall exist in a characteristic definition.
The default value for the Client Characteristic Configuration descriptor value shall be 0x0000."
Note that the Client Characteristic Descriptor (CCCD) is the attribute in the characteristic that handles notification/indications. You can read more about this here:-
Bluetooth Low Energy: A Primer
Bluetooth GATT
Bluetooth Low Energy Characteristics Tutorial

How to handle the device watcher "cache" of old devices on start-up?

I have one BLE application.
When I start the device scanning, the DeviceWatcher.Added event will call immediately and shows the previously connected devices which is currently powered off. But in the DeviceWatcher.Removed event it will be cleared.
How can I prevent this situation. In my application I am trying to connect the device immediately when ever there is the device listed in the DeviceWatcher.Added event. I don't want to wait till the DeviceWatcher.EnumerationCompleted event.
Because of this implementation, the connection API BluetoothLEDevice bluetoothLEDevice = BluetoothLEDevice::FromIdAsync(GetId()).get(); is returning success. And in the service scan API GattDeviceServicesResult result = m_BluetoothLEDevice.GetGattServicesAsync(BluetoothCacheMode::Uncached).get(); I am getting GattCommunicationStatus::Unreachable status.
I need this status in the initial time of scanning. Or there is any other way I can check the device is unreachable or not?
The sample written here is in C#, you could find the C++ replacement in the learn.microsoft.com
You could get all the paired BLE devices like this.
var pairedBleDevices = await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelectorFromPairingState(true)); # Return all the paired Bluetooth LE devices
Now, if you want to remove the pairing of a specific device, you could loop through the pairedBleDevices and find your removal device by matching specific property, let's say device name or address.
foreach (var device in pairedBleDevices )
{
if (!device::Name.Contains("myDevice")) continue;
await device.Pairing.UnpairAsync();
break;
}
Now, as you have all the previously paired LE devices with properties, as Mike suggested, you could use BluetoothLEAdvertisementWatcher to discover BLE devices and filter the advertisement by matching the BluetoothAddress(from the paired device). If you find a new device, pair the device or execute the GATT operation and start communicating.
You are getting GattCommunicationStatus::Unreachable that's probably the device you are trying to communicate with is in sleep mode. So the best way is to capture the advertisement first using BluetoothLEAdvertisementWatcher and, after that, initiate the pairing or GATT operation.

Bluez BLE Connections Monitoring using DBUS-Python

I was able to advertise the BLE and setup GATT Services and Characteristics by following the "example_advertisement" and "example-gatt-server" in Bluez Examples. How can I know from DBUS when a BLE client is connected and when it is disconnected, using similar DBUS binding for Python? Which DBUS API do I look into?
There is another example that you can look at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/test-discovery
When BlueZ/DBus learns of a new remote device, then the InterfacesAdded signal gets sent.
When a remote device goes from disconnected, to connected. Then that is a property change on the device and the PropertiesChanged signal gets sent.
This is why there is the code in the above example they use add_signal_receiver to add callbacks for both signals.
bus.add_signal_receiver(interfaces_added,
dbus_interface = "org.freedesktop.DBus.ObjectManager",
signal_name = "InterfacesAdded")
bus.add_signal_receiver(properties_changed,
dbus_interface = "org.freedesktop.DBus.Properties",
signal_name = "PropertiesChanged",
arg0 = "org.bluez.Device1",
path_keyword = "path")
As a side note, the DBus bindings used in the Buez examples are not the only ones available:
https://www.freedesktop.org/wiki/Software/DBusBindings/

Is running HM10 on a soft-serial enable the Low Energy charecteristics ? If so, how can the UUIDs and GATT profiles be tweaked in this case ?

I've been tinkering with the HM-10 board for a few weeks now, trying to push data from phone to module and vice-versa. The ultimate goal was to enable the BLE mode and tweak with the characteristics and GATT profiles. I'm pretty new to this domain so can anyone help me out ?
And is there any way we can interface the HM-10 with the hardware rx-tx channel instead of soft-serial ?
Your question is still not very clear, but i think you mean sending AT-commands over BLE-radio.
To make this possible you have to change the MODE using serial connection.
In standard mode the device can only be configured over the serial connection (pins RXD and TXD) using AT commands.
AT+MODE0: It only accepts AT-commands over the serial connection (RXD/TXD)
until a central device connects to the module.
AT+MODE1: Same as MODE0, once a connection is established,
AT-commands can be sent over BLE and manipulate some PIO pins on
the device.
AT+MODE2: Same as MODE0, once a connection is established,
AT-commands can be sent over BLE.
To test it just send a string to hm-10 as "AT\r\n" and it will respond with OK.
Update:
You cannot change the services and characteristics with AT-commands.
There are a lot of other things you can change,like advertising, setup a beacon and change a lot of settings.
For a full list of AT commands and more see the official data sheet:
http://www.jnhuamao.cn/bluetooth41_en.zip

QSerialPortInfo : Finding the USB hardware location of a virtual serial Port

I have a USB hub chip, and a micro controller connected to it on one of its ports.
I am able to enumerate, and communicate with the micro controller with QSerialPortInfo / QSerialPort.
My problem is, that I have to tell if a general USB device is connected to the same USB hub as my micro controller or not.
This should be easy, I can tell the general USB device's hardware location, like "Port_#0001.Hub_#0010", so if the Hub_# number is the same as where the micro controller is connected, I can tell that it is the same hub they are connected to.
The problem is that QSerialPortInfo.systemLocation() return with "\.\COM31" string, and not someting like "Port_#0002.Hub_#0010".
How can I obtain what USB hardware path does the QSerialPortInfo / QSerialPort belong to?
Additional info:
Windows 7, Qt 5.3, C++11
QSerialPortInfo returns information:
QSerialPortInfo.portName() == "COM31"
QSerialPortInfo.description() == "LPC USB VCom Port"
QSerialPortInfo.serialNumber() == "" // (Empty string)
While windows device manager shows the real USB correctly: (sorry can't post images yet)
DeviceManager > Ports(COM & LPT) > LPC USB VCom Port (COM31)
Properties > General > Location: Port_#0002.Hub_#0010
How could I access this information from my Qt code?
Well, managed to get is working, but its not the desired solution:
I use the SetupDiGetClassDevs windows api call to get all devices for a specific GUID, then with the SetupDiGetDeviceRegistryProperty winApi I get properties until I find the specific port the MCU is located on, and initialize a QSerialPort with that port name. Then the properties SPDRP_LOCATION_PATHS and SPDRP_LOCATION_INFORMATION provide information that is usable to detect if a general USB device is on the same hub.
The problem is that this is a "Throw away the high level API that Qt provides and start to mess around with winApi" solution. I would rather avoid this. If there is a more Qt like, and less direct winApi dependent solutions for this it would be appreciated.

Resources