Creating a Descriptor in Bluetooth Framework VCL - delphi

I'm using Bluetooth Framework VCL for a Bluetooth LE project.
I have created a Characteristic like this:
var
Service: TwclGattLocalService;
Params: TwclGattLocalCharacteristicParameters;
Characteristic: TwclGattLocalCharacteristic;
begin
Uuid.ShortUuid := $FFF1;
Params.Props := [cpReadable, cpNotifiable];
Res := Service.AddCharacteristic(Uuid, Params, Characteristic);
Service.AddDescriptor() ?????
I want to create a Descriptor for the Characteristic I created. But there is no method for that. I see read and write descriptor methods in Gatt client classes. But not in server/service or Characteristic classes.
var
wclGattClient: TwclGattClient;
Characteristic: TwclGattCharacteristic;
FDescriptors: TwclGattDescriptors;
begin
wclGattClient.ReadDescriptors(Characteristic, OpFlag, FDescriptors);
wclGattClient.WriteDescriptorValue(Descriptor, val);
I cannot use the Delphi default BluetoothLE components because Gatt server functions are not implemented for Windows.

Current version does not support descriptors for GATT server. Actually in most cases it is not required because Client Configuration Descriptor always created automatically for indicatable and notifiable characteristics. In case if you need other descriptor type contact us at support#btframework.com and we discuss this issue.

Related

What devices does CBCentralManager.retrieveConnectedPeripherals() return?

I want to check which Bluetooth Devices my iPhone is connected to. In order to do that, I use CBCentralManager.retrieveConnectedPeripherals() like this:
let connectedPerphs = centralManager.retrieveConnectedPeripherals(withServices: []);
My problem is that even if my iPhone is connected to a BluetoothDongle (it explicitly says "connected" in the settings), the list that is returned by retriveConnectedPeripherals() is always empty. Am I using the method in a wrong way or can it not be used to detect a bluetooth connection such as the connection to to my dongle? If the latter is the case, how can I detect that connection?
Let me clear, centralManager.retrieveConnectedPeripherals always return empty or nil value, If you are not passing any value into serviceUUIDs
retrieveConnectedPeripherals(withServices:)
Returns a list of the peripherals (containing any of the specified
services) currently connected to the system.
serviceUUIDs:
A list of service UUIDs (represented by CBUUID objects).
Update:
Unfortunately this the long way to do it. You can create Array of CBUUID statically then you can pass it to the method. Please refer below code.
let aryUUID = ["1800","18811"]
var aryCBUUIDS = [CBUUID]()
for uuid in aryUUID{
let uuid = CBUUID(string: "1800")
aryCBUUIDS.append(uuid)
}
let connectedPerphs = centralManager.retrieveConnectedPeripherals(withServices: aryCBUUIDS)
List of available services
First, this works only with BLE devices, thus if your dongle is using a common BT you will not get it from here, but probably using EAAccessoryManager var connectedAccessories: [EAAccessory] method, but as far as I know your app must comply to MFI.
That is why is asking which service your devices are exposing as a filter.

How to Track the progress of the Upload by NetHttpClient in delphi 10?

Now I will send the file to my server through the Nethttpclient component in delphi 10, but I don't know how to track the progress when uploading. If I download the file, I can get the progress through the event ReceiveData.
There are not any other useful functions or events to do it, please kindly help me to solve this problem.(only nethttpclient,because I don't use Indy)
TNetHTTPClient simply does not expose any kind of status info during uploads, other than OnRequestComplete and OnRequestError. If you need status on the progress of uploaded data, you should switch to another HTTP library that provides the kind of progress reporting you want.
That being said, the only way I can see to get upload status with TNetHTTPClient is to post the file data using a TStream. Derive a custom class from TFileStream and override its Read() method to read the file data and report status as needed.
Actually (i use Delphi v. 10.4.1) the TNetHttpClient implements a property/method named OnSendData similar to OnReciveData to manage the post stream during uploads:
property OnSendData: TSendDataEvent read FOnSendData write SetOnSendData;
base on TSendDataEvent declared in "System.Net.HttpClient.THTTPClient.Post" as procedure of object:
TSendDataEvent = procedure(const Sender: TObject; AContentLength: Int64; AWriteCount: Int64; var AAbort: Boolean) of object;
hope it is usefull

GetDescriptor() null value / 128-bit UUID descriptor?

I'm writing my code using Xamarin. I'm developing my IOS app which allows me to read the BLE devices, Services, characteristic value and activation of the notification.
My BLE beacon have one custom Services that contain two custom characteristics and both have the notification implemented using CCCD.
My ble devices work correctly I test it with BLE scanner app and it working well without any problem.
I can read value and I can active the notification for both characteristic. See picture here.
The app that I wrote using xamarin work correctly (reading services, characteristic value....) the only problem that didn't work is the activation of the notification. Here's a portion of the code :
public UUID Charac_UUID0 = UUID.FromString("0000beef-1212-efde-1523-785fef13d123");
public UUID Charac_UUID = UUID.FromString("0000b1e0-1212-efde-1523-785fef13d123") ;
public UUID Descr_UUID = UUID.FromString("00002902-1212-efde-1523-785fef13d123");
protected BluetoothGattCharacteristic _charac;
....
....
this._charac = App.Current.State.SelectedService.GetCharacteristic(Charac_UUID0);
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].SetCharacteristicNotification(_charac, true);
BluetoothGattDescriptor descriptor = _charac.GetDescriptor(Descr_UUID0);
descriptor.SetValue(BluetoothGattDescriptor.EnableNotificationValue.ToArray());
BluetoothLEManager.Current.ConnectedDevices[App.Current.State.SelectedDevice].WriteDescriptor(descriptor);
The code always give me an error at descriptor.SetValue and it indicate me that the descriptor is NULL meaning that _charac.GetDescriptor didn't return any value.
I suspect the Descriptor UUID value (Descr_UUID) is not correct. I don't know excatly how can I determine the Descr_UUID but I saw many example in the internet of people replacing the custom UUID of the caracteristic by 2902 which give me in my case a 128 descriptor UUID equal to 00002902-1212-efde-1523-785fef13d123.
But there is a problem here. The descriptor UUID for both characteristic will be the same because the base UUID is the same for both characteristic?
Any solution?
3 years later im sure you figured it out but, 2902 is the 16 bit value for a Client Characteristic Configuration Descriptor, and I believe it should also be inflated using the "BASE UUID" not just whatever your characteristic descriptor uses. See this: answer
This will convert your 16 (or 32) bit uuids to full 128 bit uuids using the BASE UUID:
public static UUID ConvertUuid(uint uuid)
{
const long msbMask = 0x0000000000001000;
const ulong lsb = 0x800000805f9b34fb;
var msb = msbMask | ((ulong)(uuid & uint.MaxValue) << 32);
return new UUID((long)msb, unchecked((long)lsb));
}

What is the format of the optionsFile for the IotFDevice class in Quarks?

The IotfDevice Class in Quarks has a constructor with an optionsFile. What is the format of this file and what are the necessary values?
The options file has five values: org, type, id, auth-method, auth-token. This is an example of mine with the values obfuscated.
[device]
org = 4pj4r4
type = rustQuark
id = rustIIa
auth-method = token
auth-token = 8jLWEY(P4SVJl5oi!V
When you register a device the set of values are issued, details and examples can be found here.
A little context.
Internet of Things Foundation (IoTf) is an infrastructure for application's to communicate with devices. IoTf requires that you register the application and all
devices that send data to the application.
Why would you use IoTf? Getting the communication setup between devices is
a pain: firewalls, retry, failover, QoS, debugging, monitoring. This is facility especially nice if you're doing a proof of concept.
For a better description of IoTf look here.

How do you create a descriptor for a mutable characteristic?

The documentation for CBMutableDescriptor:initWithType:value: says to pass a "128-bit UUID that identifies the characteristic" for the type parameter. It then goes on to say you should only use one of CBUUIDCharacteristicUserDescriptionString or CBUUIDCharacteristicFormatString for the type parameter. Finally, there is no method to add a descriptor to a mutable characteristic.
It appears that the parameter is doing two mutually exclusive things. On the one hand, it is being used to tell the O/S which characteristic the descriptor applies to, and on the other, it is being used to set the type of descriptor. The second makes more sense, but then how do you add the descriptor to the characteristic?
Whether you pass the UUID for the characteristic or CBUUIDCharacteristicUserDescriptionString, iOS crashes with
Assertion failure in -[CBMutableDescriptor initWithType:value:], /SourceCache/CoreBluetooth_Sim/CoreBluetooth-59.3/CBDescriptor.m:25
What's the correct way to create the CBMutableDescriptor and add it to a CBMutableCharacteristic?
You're correct about the docs. But just to be clear for everyone, here is a citation found in CBDescriptor.h:
...Only the Characteristic User Description and Characteristic
Presentation Format descriptors are currently supported. The
Characteristic Extended Properties and Client Characteristic
Configuration descriptors will be created automatically upon
publication of the parent service, depending on the properties of the
characteristic itself.
So in other words, unless you are setting those descriptors, the system will block you (thus why you got the assertion failure).
So say you want to use the Characteristic User Description descriptor, you would do:
CBUUID *yourCharUUID = [CBUUID UUIDWithString:#"c07c5050-15a0-11e3-8ffd-0800200c9a66"];//whatever UUID your using
CBMutableCharacteristic *yourCharacteristic = [[CBMutableCharacteristic alloc]initWithType:yourCharUUID properties:CBCharacteristicPropertyWriteWithoutResponse value:nil permissions:perms];
CBUUID *userDescriptionUUID = [CBUUID UUIDWithString:CBUUIDCharacteristicUserDescriptionString];//or set it to the actual UUID->2901
CBMutableDescriptor *yourDescriptor = [[CBMutableDescriptor alloc]initWithType:userDescriptionUUID value:#"myDescriptorValue"];
yourCharacteristic.descriptors = #[yourDescriptor];
Let me know if you have any questions.

Resources