# BLEClient Component

An easy-to-use Bluetooth Low Energy (BLE) GATT Client component.

## Syntax

```text
nsoftware.IPWorksBLE.BLEClient
```

## Remarks

The BLEClient component provides a simple but flexible BLE GATT client implementation, making it easy to work with the services, characteristics, and descriptors exposed by BLE GATT servers on remote devices.

### Prerequisites

 **Windows Notes:**

Please note that the *BLEClient* component is only supported by Windows 10 Creator's Update (10.0.15063.0) and later. Additionally .NET Version 4.5 or higher is required.

 **Android Notes:**

The *BLEClient* component requires Android API level of 21 or higher.

*Note that on Android, even when pairing is not explicitly enabled in the component, the operating system may automatically perform pairing as it deems appropriate.*

 **iOS/macOS Notes:**

The *BLEClient* component has the following operating system requirements:

- iOS 5.0+
- iPadOS 5.0+
- Mac Catalyst 13.0+
- macOS 10.10+

 *Note that for iOS and macOS, the operating system handles all pairing, and this is not controllable from the component.*

 **Linux Notes:**

On Linux, the BLE components rely on BlueZ and DBus. These packages must be installed in order to use the components. Many Linux distributions come with BlueZ and DBus pre-installed.

### Scanning and Connecting

 To begin, call the [StartScanning](#startscanning-method-bleclient-component) method, optionally passing in a list of service UUIDs that you're interested in so that irrelevant devices are ignored during scanning. While the component is scanning, the [Advertisement](#advertisement-event-bleclient-component) event will fire for each relevant advertisement received from a GATT server.

The [Advertisement](#advertisement-event-bleclient-component) event provides a wealth of information about the remote device, such as its Id and local name, whether or not you can connect to it, the list of service UUIDs it's advertising, and much more.

Once you've determined what device you wish to connect to, call the [Connect](#connect-method-bleclient-component) method and pass its server Id, obtained from the [Advertisement](#advertisement-event-bleclient-component) event. The component will stop scanning, then attempt to connect to the device. The [Connected](#connected-event-bleclient-component) event is fired when the connection attempt finishes, and will contain error information in case of a failure.

The [PairingMode](#PairingMode) configuration setting can be used to enable automatic pairing as part of the connection process. As part of the pairing process, the [PairingRequest](#pairingrequest-event-bleclient-component) event will fire, allowing the client to manage the pairing request.

```csharp
// StartScan, StopScan, and Advertisement event handlers.
bleclient1.OnStartScan += (s, e) => Console.WriteLine("Scanning has started");
bleclient1.OnStopScan += (s, e) => Console.WriteLine("Scanning has stopped");
bleclient1.OnAdvertisement += (s, e) => {
  // Your application should make every effort to handle the Advertisement event quickly.
  // BLEClient fires it as often as necessary, often multiple times per second.
  Console.WriteLine("Advertisement Received:\r\n\tServerId: " + e.ServerId + "\r\n\tName: " +
    e.Name + "\r\n\tServiceUuids: " + e.ServiceUuids + "\r\n\tManufacturerCompanyId:  " +
    e.ManufacturerCompanyId + "\r\n\tIsConnectable:  " + e.IsConnectable);
};

// Scan for all devices.
bleclient1.StartScanning("");

// Alternatively, you can scan for devices advertising specific service UUIDs. You can use a
// mixture of 16-, 32-, and 128-bit UUID strings, they'll be converted to 128-bit internally.
bleclient1.StartScanning("180A,0000180F,00001801-0000-1000-8000-00805F9B34FB");

// ...Once you find a device you wish to connect to...
bleclient1.Connect("SERVER_ID");
```

Refer to [StartScanning](#startscanning-method-bleclient-component) for more detailed code examples.

### Service, Characteristic, and Descriptor Discovery

 Once connected to a device, the next step is to discover the services that you're interested in. To do this, call the [DiscoverServices](#discoverservices-method-bleclient-component) method, optionally passing a list of service UUIDs to limit the discovery process. For each service discovered, an object will be added to the [Services](#services-property-bleclient-component) collection, and the [Discovered](#discovered-event-bleclient-component) event will fire.

After you've discovered the services you're interested in, you have to discover those services' characteristics. This is done with the [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component) method, passing the Id of the service you wish to discover characteristics for, and optionally passing a list of characteristic UUIDs to limit the discovery process. For each characteristic discovered, an object will be added to the [Characteristics](#characteristics-property-bleclient-component) collection, and the [Discovered](#discovered-event-bleclient-component) event will fire.

Finally, you can discover descriptors for the discovered characteristics. To do this, you use the [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) method, passing the Id of a characteristic, as well as the Id of the service which owns it. For each descriptor discovered, an object will be added to the [Descriptors](#descriptors-property-bleclient-component) collection, and the [Discovered](#discovered-event-bleclient-component) event will fire.

If you would prefer to do multiple discovery steps with a single call, you can use the [Discover](#discover-method-bleclient-component) method rather than the individual [DiscoverServices](#discoverservices-method-bleclient-component), [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component), and [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) methods. However, keep in mind that doing so will consume more power up front. Discovering services, characteristics, and descriptors as you need them is more energy-efficient.

```csharp
// Discovered event handler.
bleclient1.OnDiscovered += (s, e) => {
  string gattType = e.GattType == 0 ? "Service" :
    (e.GattType == 1 ? "Characteristic" : "Descriptor");
  Console.WriteLine(gattType + " discovered:" +
    // The 128-bit UUID string, "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX".
    "\r\n\tUUID: " + e.Uuid +
    // For standard GATT objects whose UUIDs are defined by the Bluetooth
    // SIG, the Description event parameter will contain their name.
    "\r\n\tDescription: " + e.Description);
};

string serviceIds = "180A,F000AA70-0451-4000-B000-000000000000,F000AA20-0451-4000-B000-000000000000";
// Discover specific root services.
bleclient1.DiscoverServices(serviceIds, "");

foreach (Service s in bleclient1.Services) {
  // Discover all characteristics for this service.
  bleclient1.DiscoverCharacteristics(s.Id, "");

  bleclient1.Service = s.Id;
  foreach (Characteristic c in bleclient1) {
    // Discover all descriptors for this characteristic.
    bleclient1.DiscoverDescriptors(s.Id, c.Id);
  }
}
```

Refer to [DiscoverServices](#discoverservices-method-bleclient-component), [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component), [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component), and [Discover](#discover-method-bleclient-component) for more detailed code examples.

### Working with Discovered Data

 Once you've discovered the services, characteristics, and descriptors that you need, you'll want to make use of them. BLEClient makes it easy to navigate the GATT data hierarchy. Start by iterating over the objects in the [Services](#services-property-bleclient-component) collection and inspecting the information discovered for each service.

Set the [Service](#service-property-bleclient-component) property to a specific service's Id to have the component populate the [Characteristics](#characteristics-property-bleclient-component) collection based on the characteristics discovered for that service. You can then iterate over the characteristic objects to inspect the details of each characteristic. Depending on what flags a characteristic has, you may also be able to directly manipulate some of its information.

Set the [Characteristic](#characteristic-property-bleclient-component) property to a specific characteristic's Id to have the component populate the [Descriptors](#descriptors-property-bleclient-component) collection based on the descriptors discovered for that characteristic. You can then iterate over the descriptor objects to inspect the details of each descriptor.

```csharp
// Loop through all discovered GATT objects and print out their UUIDs and descriptions.
foreach (Service s in bleclient1.Services) {
  Console.WriteLine("Service: " + s.Description + " (" + s.Uuid + ")");
  // Select this service and loop through its characteristics.
  bleclient1.Service = s.Id;

  foreach (Characteristic c in bleclient1.Characteristics) {
    Console.WriteLine("\tCharacteristic: " + c.Description + " (" + c.Uuid + ")");
    // Select this characteristic and loop through its descriptors.
    bleclient1.Characteristic = c.Id;

    foreach (Descriptor d in bleclient1.Descriptors) {
      Console.WriteLine("\t\tDescriptor: " + d.Description + " (" + d.Uuid + ")");
    }
  }
}
```

### Reading and Writing Values

 The BLEClient component exposes [Characteristic](#characteristic-type).[CachedValue](#Characteristic_f_CachedValue) and [Descriptor](#descriptor-type).[CachedValue](#Descriptor_f_CachedValue) fields, which retrieve values from the local system's value cache, preventing unnecessary power drain involved with communicating with the device.

```csharp
// Print the cached value for a characteristic (which you can assume
// we've already found and assigned to a variable called "c").
Console.WriteLine("Characteristic Value: " + BitConverter.ToUInt16(c.CachedValueB, 0));

// Print the cached value for a descriptor (again, assume it's stored in "d").
Console.WriteLine("Descriptor Value: " + BitConverter.ToString(d.CachedValueB));
```

To read a value directly from the remote device's GATT server, use the [ReadValue](#readvalue-method-bleclient-component) method. For characteristics, you'll need to pass the Ids of the characteristic and the service which owns it. For descriptors, you'll pass both of those, as well as the Id of the descriptor. If the read succeeds, the method will return the value read from the device, and the [Value](#value-event-bleclient-component) event will be fired. If the read fails, the [Error](#error-event-bleclient-component) event is fired and the component throws an exception.

```csharp
// Value event handler.
bleclient1.OnValue += (s, e) => {
  Console.WriteLine("Read value {" + BitConverter.ToString(e.ValueB) + "} for " +
    (string.IsNullOrEmpty(e.DescriptorId) ? "characteristic" : "descriptor") +
    " with UUID " + e.Uuid);
};

// Prints the live value for a characteristic.
bleclient1.ReadValue("001C00000000", "001C001D0000", "");

// Prints the live value for a descriptor.
bleclient1.ReadValue("001C00000000", "001C001D0000", "001C001D0021");
```

To write a characteristic or descriptor value, call the [WriteValue](#writevalue-method-bleclient-component) method, passing the appropriate Ids and the value to be written. If the write succeeds, the method will return and the [WriteResponse](#writeresponse-event-bleclient-component) event will fire. If the write fails, the [Error](#error-event-bleclient-component) event is fired and the component throws an exception.

```csharp
// WriteResponse event handler.
bleclient1.OnWriteResponse += (s, e) => {
  string gattType = string.IsNullOrEmpty(e.DescriptorId) ? "characteristic" : "descriptor";
  Console.WriteLine("Successfully wrote to " + gattType + " with UUID " + e.Uuid);
};

// Write to a characteristic.
bleclient1.WriteValue("004200000000", "004200460000", "", new byte[] { 0x1 });

// Write to a descriptor.
bleclient1.WriteValue("004200000000", "004200430000", "004200430045", new byte[] { 0x1 });
```

You can also use the [PostValue](#postvalue-method-bleclient-component) method to write values to characteristics that have the "Write Without Response" flag. Posting a value to a characteristic is more energy-efficient since the remote device's GATT server won't send back an acknowledgement, even if the write fails.

```csharp
// Write without response to a characteristic.
bleclient1.PostValue("00AA00000000", "00AA00BB0000", new byte[] { 0x1, 0x2, 0x3 });
```

Keep in mind that not all characteristics and descriptors support value writes, and some might not even support value reads. If you attempt to perform an operation that a characteristic or descriptor doesn't support, the component throws an exception.

For characteristics, you can inspect the [Characteristic](#characteristic-type).[Flags](#Characteristic_f_Flags) field to determine what operations the characteristic supports. For descriptors, you'll either need to know in advance what operations are supported, or be ready to handle exceptions which may occur.

Refer to [ReadValue](#readvalue-method-bleclient-component), [WriteValue](#writevalue-method-bleclient-component), and [PostValue](#postvalue-method-bleclient-component) for more detailed code examples.

### Subscribing to Characteristics

 One of the most important features of the BLE GATT data model is the ability for a GATT server to send characteristic value updates to interested GATT clients in real-time. A GATT client can subscribe to either notifications or indications to get value updates. The difference between the two is simple: notifications are not acknowledged by GATT clients, while indications are.

When you want to subscribe to a characteristic, start by checking the [Characteristic](#characteristic-type).[CanSubscribe](#Characteristic_f_CanSubscribe) field to determine if it supports subscriptions.

For characteristics which do support subscriptions, you can subscribe and unsubscribe by using either the [Characteristic](#characteristic-type).[Subscribed](#Characteristic_f_Subscribed) field or the [Subscribe](#subscribe-method-bleclient-component) and [Unsubscribe](#unsubscribe-method-bleclient-component) methods. The [Subscribed](#subscribed-event-bleclient-component) and [Unsubscribed](#unsubscribed-event-bleclient-component) events are fired whenever a characteristic's subscription state changes, and the [Value](#value-event-bleclient-component) event is fired whenever a value update is received.

Note that characteristics do not have to support *both* subscription types, or even one of them. For characteristics which do support both, the component will subscribe for notifications by default. If you'd prefer that it subscribe for indications instead, enable the [PreferIndications](#PreferIndications) configuration setting.

```csharp
// Subscribed, Unsubscribed, and Value event handlers.
bleclient1.OnSubscribed += (s, e) => {
  Console.WriteLine("Subscribed to characteristic:" + "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid + "\r\n\tDescription: " + e.Description);
};
bleclient1.OnUnsubscribed += (s, e) => {
  Console.WriteLine("Unsubscribed from characteristic:" + "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid + "\r\n\tDescription: " + e.Description);
};
bleclient1.OnValue += (s, e) => {
  Console.WriteLine("Value update received for characteristic: " + "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid + "\r\n\tDescription: " + e.Description + "\r\n\tValue: " +
    BitConverter.ToString(e.ValueB));
};

// Assume that we've already found a characteristic, its owning service,
// and a descriptor on it; and we've stored them in variables called "c",
// "s", and "d", respectively. You can subscribe to and unsubscribe from
// the characteristic using any, or all, of the three methods below.

// Subscribe and unsubscribe using methods.
bleclient1.Subscribe(s.Id, c.Id);
// ...
bleclient1.Unsubscribe(s.Id, c.Id);

// Subscribe and unsubscribe using the "Subscribed" field.
c.Subscribed = true;
// ...
c.Subscribed = false;

// Subscribe and unsubscribe by writing directly to the CCCD.
bleclient1.WriteValue(s.Id, c.Id, d.Id, new byte[] { 1, 0 });
// ...
bleclient1.WriteValue(s.Id, c.Id, d.Id, new byte[] { 0, 0 });
```

### Usage Notes

 It is very important that you do not block or perform any long-running operations within the component's event handlers. The platform APIs that the component uses rely on timely delivery of events in order to function properly.

Most platforms will in some way limit the use of Bluetooth APIs when your application is in the background. Be aware of the limitations your platform places on the usage of BLE APIs while in the background, and be ready to act accordingly.

Be sure to disconnect from a remote device by calling [Disconnect](#disconnect-method-bleclient-component) when you're finished using it. When you're completely finished using the BLEClient component, be sure that you've called [StopScanning](#stopscanning-method-bleclient-component) and [Disconnect](#disconnect-method-bleclient-component) before disposing of the instance. (Calling the component's *Dispose()* method will automatically take care of this for you.)

## Property List

*The following is the full list of the properties of the component with short descriptions. Click on the links for further details.*

|  |  |
| --- | --- |
| [ActiveScanning](#activescanning-property-bleclient-component) | Whether to use active scanning. |
| [Characteristic](#characteristic-property-bleclient-component) | The currently selected characteristic's Id. |
| [Characteristics](#characteristics-property-bleclient-component) | The characteristics which have been discovered for the currently selected service. |
| [Descriptors](#descriptors-property-bleclient-component) | The descriptors which have been discovered for the currently selected characteristic. |
| [Scanning](#scanning-property-bleclient-component) | Whether or not the component is currently scanning for servers. |
| [ServerId](#serverid-property-bleclient-component) | Platform-specific string identifying the currently connected server. |
| [ServerName](#servername-property-bleclient-component) | Local name of the currently connected server. |
| [Service](#service-property-bleclient-component) | The currently selected service's Id. |
| [Services](#services-property-bleclient-component) | The services which have been discovered on the currently connected server. |
| [Timeout](#timeout-property-bleclient-component) | A timeout for the component |

## Method List

*The following is the full list of the methods of the component with short descriptions. Click on the links for further details.*

|  |  |
| --- | --- |
| [CheckCharacteristicSubscribed](#checkcharacteristicsubscribed-method-bleclient-component) | Checks to see if the component is subscribed to a characteristic. |
| [Config](#config-method-bleclient-component) | Sets or retrieves a configuration setting. |
| [Connect](#connect-method-bleclient-component) | Connect to a BLE GATT server based on its identifier. |
| [Disconnect](#disconnect-method-bleclient-component) | Disconnects from the remote server. |
| [Discover](#discover-method-bleclient-component) | Convenience method to discover multiple levels of the GATT object hierarchy at once. |
| [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component) | Used to discover characteristics for a specific service. |
| [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) | Used to discover all descriptors for a specific characteristic. |
| [DiscoverServices](#discoverservices-method-bleclient-component) | Used to discover services for the currently connected server. |
| [DoEvents](#doevents-method-bleclient-component) | This method processes events from the internal message queue. |
| [PostValue](#postvalue-method-bleclient-component) | Write the value of a characteristic without expecting a response. |
| [QueryCharacteristicCachedVal](#querycharacteristiccachedval-method-bleclient-component) | Reads and returns a characteristic value from the value cache. |
| [QueryDescriptorCachedVal](#querydescriptorcachedval-method-bleclient-component) | Reads and returns a descriptor value from the value cache. |
| [ReadValue](#readvalue-method-bleclient-component) | Read the value of a characteristic or descriptor from the server. |
| [Select](#select-method-bleclient-component) | Used to set the currently selected service and characteristic by their Ids. |
| [StartScanning](#startscanning-method-bleclient-component) | Causes the component to begin scanning for BLE GATT servers. |
| [StopScanning](#stopscanning-method-bleclient-component) | Causes the component to stop scanning for BLE GATT servers. |
| [Subscribe](#subscribe-method-bleclient-component) | Subscribes to value updates for the specified characteristic. |
| [Unsubscribe](#unsubscribe-method-bleclient-component) | Unsubscribes from value updates for one or more characteristics. |
| [WriteValue](#writevalue-method-bleclient-component) | Write the value of a characteristic or descriptor. |

## Event List

*The following is the full list of the events fired by the component with short descriptions. Click on the links for further details.*

|  |  |
| --- | --- |
| [Advertisement](#advertisement-event-bleclient-component) | Fired when an advertisement packet is received during scanning. |
| [Connected](#connected-event-bleclient-component) | Fired immediately after a connection to a remote device completes (or fails). |
| [Disconnected](#disconnected-event-bleclient-component) | Fired when the component has been disconnected from the remote device. |
| [Discovered](#discovered-event-bleclient-component) | Fired when the component discovers a service, characteristic, or descriptor. |
| [Error](#error-event-bleclient-component) | Fired when information is available about errors during data delivery. |
| [Log](#log-event-bleclient-component) | Fires once for each log message. |
| [PairingRequest](#pairingrequest-event-bleclient-component) | Fired when pairing is requested. |
| [ServerUpdate](#serverupdate-event-bleclient-component) | Fired when the currently connected server updates its name or available services. |
| [StartScan](#startscan-event-bleclient-component) | Fired when the component starts scanning. |
| [StopScan](#stopscan-event-bleclient-component) | Fired when the component stops scanning. |
| [Subscribed](#subscribed-event-bleclient-component) | Fired when the component has successfully subscribed to a characteristic. |
| [Unsubscribed](#unsubscribed-event-bleclient-component) | Fired when the component has successfully unsubscribed from a characteristic. |
| [Value](#value-event-bleclient-component) | Fired when a characteristic or descriptor value is received from the server. |
| [WriteResponse](#writeresponse-event-bleclient-component) | Fired when the server acknowledges a successful value write request. |

## Config Settings

*The following is a list of config settings for the component with short descriptions. Click on the links for further details.*

|  |  |
| --- | --- |
| [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics) | Whether to automatically discover all characteristics when a service is discovered. |
| [AutoDiscoverDescriptors](#AutoDiscoverDescriptors) | Whether to automatically discover all descriptors when a characteristic is discovered. |
| [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices) | Whether to automatically discover all included services when a service is discovered. |
| [GattObjTreeInfo](#GattObjTreeInfo) | Returns a string representation of the currently discovered GATT object tree. |
| [IncludeRediscovered](#IncludeRediscovered) | Whether to fire the Discovered event for rediscovered services, characteristics, and descriptors. |
| [LogLevel](#LogLevel) | The level of detail that is logged. |
| [ManufacturerCompanyId\[i\]](#ManufacturerCompanyId[i]) | The manufacturer company Id at index 'i'. |
| [ManufacturerData\[i\]](#ManufacturerData[i]) | The manufacturer data at index 'i'. |
| [ManufacturerDataCount](#ManufacturerDataCount) | The number of manufacturer data sections an advertisement has. |
| [PairingMode](#PairingMode) | Determines how pairing is handled while connecting. |
| [PreferIndications](#PreferIndications) | Whether to subscribe to characteristics using indicate when possible. |
| [ScanStartedTimeout](#ScanStartedTimeout) | The maximum amount of time to wait for scanning to start. |
| [ServiceData](#ServiceData) | Gets the data associated with a service UUID from an advertisement. |
| [BuildInfo](#BuildInfo) | Information about the product's build. |
| [GUIAvailable](#GUIAvailable) | Whether or not a message loop is available for processing events. |
| [LicenseInfo](#LicenseInfo) | Information about the current license. |
| [MaskSensitiveData](#MaskSensitiveData) | Whether sensitive data is masked in log messages. |
| [UseInternalSecurityAPI](#UseInternalSecurityAPI) | Whether or not to use the system security libraries or an internal implementation. |

# ActiveScanning Property ([BLEClient](#bleclient-component) Component)

Whether to use active scanning.

## Syntax

```text
public bool ActiveScanning { get; set; }
```

## Default Value

False

## Remarks

When enabled, the component will instruct the system to use active scanning rather than passive scanning, at the cost of higher power consumption.

Active scanning causes the system's BLE API to request a scan response packet for each advertisement received, which in turn means that you will be able to get more information from devices without connecting to them.

The tradeoff is that enabling this feature increases power consumption for both the client and server, but if your use-case doesn't call for ever actually connecting to the devices (which itself can be a power-intensive operation), then that tradeoff might be mitigated.

Note that you cannot change the value of the ActiveScanning property if the component is already scanning.

**Active Scanning**

```csharp
// Enable active scanning.
bleclient1.ActiveScanning = true;
bleclient1.StartScanning("");
// ...
bleclient1.StopScanning();
```

This property is not available at design time.

# Characteristic Property ([BLEClient](#bleclient-component) Component)

The currently selected characteristic's Id.

## Syntax

```text
public string Characteristic { get; set; }
```

## Default Value

""

## Remarks

Setting the Characteristic property to the Id of a discovered characteristic allows you to inspect the descriptors which have been discovered for it using the [Descriptors](#descriptors-property-bleclient-component) collection.

Characteristic can either be set to the Id of a characteristic which has been discovered for the service currently selected by [Service](#service-property-bleclient-component), or to empty string.

This property is automatically set when you call the [Select](#select-method-bleclient-component) method; and it is reset to empty string when you set [Service](#service-property-bleclient-component).

This property is not available at design time.

# Characteristics Property ([BLEClient](#bleclient-component) Component)

The characteristics which have been discovered for the currently selected service.

## Syntax

```text
public CharacteristicList Characteristics { get; }
```

## Remarks

The characteristics which have been discovered for the service currently selected with [Service](#service-property-bleclient-component). This collection is populated when characteristics are discovered for a service, which may occur due to a call to the [Discover](#discover-method-bleclient-component) or [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component) methods, or at the time when a service is discovered (if you have the [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics) configuration setting enabled).

Characteristics do not all have to be discovered at one time, and additional characteristics discovered for a service will automatically be added to this collection upon discovery. This collection is cleared when the component disconnects from the server.

If [Service](#service-property-bleclient-component) is set to empty string, or if no characteristics have been discovered for the currently selected service, this collection will be empty.

This property is not available at design time.

 Please refer to the [Characteristic](#characteristic-type) type for a complete list of fields.

# Descriptors Property ([BLEClient](#bleclient-component) Component)

The descriptors which have been discovered for the currently selected characteristic.

## Syntax

```text
public DescriptorList Descriptors { get; }
```

## Remarks

The descriptors which have been discovered for the characteristic currently selected with [Characteristic](#characteristic-property-bleclient-component). This collection is populated when descriptors are discovered for a characteristic, which may occur due to a call to the [Discover](#discover-method-bleclient-component) or [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) methods, or at the time when a characteristic is discovered (if you have the [AutoDiscoverDescriptors](#AutoDiscoverDescriptors) configuration setting enabled).

Descriptors do not all have to be discovered at one time, and additional descriptors discovered for a characteristic will automatically be added to this collection upon discovery. This collection is cleared when the component disconnects from the server.

If [Characteristic](#characteristic-property-bleclient-component) is set to empty string, or if no descriptors have been discovered for the currently selected characteristic, this collection will be empty.

This property is read-only and not available at design time.

 Please refer to the [Descriptor](#descriptor-type) type for a complete list of fields.

# Scanning Property ([BLEClient](#bleclient-component) Component)

Whether or not the component is currently scanning for servers.

## Syntax

```text
public bool Scanning { get; }
```

## Default Value

False

## Remarks

This property indicates whether or not the component is currently scanning for servers. While the component is scanning, the [Advertisement](#advertisement-event-bleclient-component) event will be fired whenever an advertisement from a remote device is received.

Refer to the [StartScanning](#startscanning-method-bleclient-component) method for more information.

This property is read-only and not available at design time.

# ServerId Property ([BLEClient](#bleclient-component) Component)

Platform-specific string identifying the currently connected server.

## Syntax

```text
public string ServerId { get; }
```

## Default Value

""

## Remarks

When the component is connected to a server, this property contains the platform-specific server identification string.

Note that this value is not guaranteed to be the same at any point in time for a specific server device.

This property is read-only and not available at design time.

# ServerName Property ([BLEClient](#bleclient-component) Component)

Local name of the currently connected server.

## Syntax

```text
public string ServerName { get; }
```

## Default Value

""

## Remarks

When the component is connected to a server, this property contains the server's local name.

If the server's name changes while you're connected to it, the [ServerUpdate](#serverupdate-event-bleclient-component) event will fire with the *Name* parameter populated, and the new value will be reflected here.

This property is read-only and not available at design time.

# Service Property ([BLEClient](#bleclient-component) Component)

The currently selected service's Id.

## Syntax

```text
public string Service { get; set; }
```

## Default Value

""

## Remarks

Setting the Service property to the Id of a discovered service allows you to inspect the characteristics which have been discovered for it using the [Characteristics](#characteristics-property-bleclient-component) collection.

Service can either be set to the Id of a service which has been discovered for the currently connected server, or to empty string. Setting Service will automatically reset [Characteristic](#characteristic-property-bleclient-component) to empty string.

This property is automatically set when you call the [Select](#select-method-bleclient-component) method.

This property is not available at design time.

# Services Property ([BLEClient](#bleclient-component) Component)

The services which have been discovered on the currently connected server.

## Syntax

```text
public ServiceList Services { get; }
```

## Remarks

The services which have been discovered for the currently connected server. This collection is populated when services are discovered, which may occur due to a call to the [Discover](#discover-method-bleclient-component) or [DiscoverServices](#discoverservices-method-bleclient-component) methods, or at the time when a service with included services is discovered (if you have the [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices) configuration setting enabled).

Included services are represented in this collection just like root ones are.

Services do not all have to be discovered at one time, and additional services discovered will automatically be added to this collection upon discovery. This collection is cleared when the component disconnects from the server.

This property is read-only and not available at design time.

 Please refer to the [Service](#service-type) type for a complete list of fields.

# Timeout Property ([BLEClient](#bleclient-component) Component)

A timeout for the component

## Syntax

```text
public int Timeout { get; set; }
```

## Default Value

60

## Remarks

If the Timeout property is set to 0, all operations will run uninterrupted until successful completion or an error condition is encountered (except the [PostValue](#postvalue-method-bleclient-component) method, which always returns immediately).

If Timeout is set to a positive value, the component will wait for a maximum of Timeout seconds since the beginning of the operation. If Timeout expires, and the operation is not yet complete, the component throws an exception.

The default value for the Timeout property is 60 (seconds).

# CheckCharacteristicSubscribed Method ([BLEClient](#bleclient-component) Component)

Checks to see if the component is subscribed to a characteristic.

## Syntax

```text
public bool CheckCharacteristicSubscribed(int index);

Async Version
public async Task<bool> CheckCharacteristicSubscribed(int index);
public async Task<bool> CheckCharacteristicSubscribed(int index, CancellationToken cancellationToken);
```

## Remarks

This method is used to see if the component is subscribed to a characteristic. The method uses the given *index* parameter to find the characteristic at the *index* of the [Characteristics](#characteristics-property-bleclient-component) property. The method will then return a bool value based on whether the client is currently subscribed to that characteristic.

# Config Method ([BLEClient](#bleclient-component) Component)

Sets or retrieves a configuration setting.

## Syntax

```text
public string Config(string configurationString);

Async Version
public async Task<string> Config(string configurationString);
public async Task<string> Config(string configurationString, CancellationToken cancellationToken);
```

## Remarks

Config is a generic method available in every component. It is used to set and retrieve [configuration settings](#config-settings-bleclient-component) for the component.

These settings are similar in functionality to properties, but they are rarely used. In order to avoid "polluting" the property namespace of the component, access to these *internal properties* is provided through the Config method.

To set a configuration setting named *PROPERTY*, you must call *Config("PROPERTY=VALUE")*, where *VALUE* is the value of the setting expressed as a string. For boolean values, use the strings "True", "False", "0", "1", "Yes", or "No" (case does not matter).

To read (query) the value of a [configuration setting](#config-settings-bleclient-component), you must call *Config("PROPERTY")*. The value will be returned as a string.

# Connect Method ([BLEClient](#bleclient-component) Component)

Connect to a BLE GATT server based on its identifier.

## Syntax

```text
public void Connect(string serverId);

Async Version
public async Task Connect(string serverId);
public async Task Connect(string serverId, CancellationToken cancellationToken);
```

## Remarks

This method will attempt to connect to the BLE GATT server represented by the platform-specific identifier supplied in the *ServerId* parameter. The [Connected](#connected-event-bleclient-component) event will be fired when the connection attempt finishes, and will contain additional information if the attempt failed.

If the component is connected to a server already when Connect is called, and the given *ServerId* is different than the currently connected server's [ServerId](#serverid-property-bleclient-component), it will attempt to gracefully disconnect prior to initiating a new connection.

Calling Connect does nothing if *ServerId* is empty or matches the currently connected server's [ServerId](#serverid-property-bleclient-component).

If Connect is called while the component is [Scanning](#scanning-property-bleclient-component), the component will stop scanning prior to attempting to initiate a connection.

Note that there are a variety of reasons that a connection to a server may fail, not the least of which includes the server device being out of range of the client device. For the best results, it is recommended that you scan for devices before attempting a connection. Also note that the device identifier is a platform-specific value which is not guaranteed to be the same at any given point in time for any specific server device.

**Connecting and Disconnecting**

```csharp
// Connect to our TI SensorTag device.
bleclient1.Connect("546C0E795800");
// Use BLEClient...
// Disconnect from the device.
bleclient1.Disconnect();
```

# Disconnect Method ([BLEClient](#bleclient-component) Component)

Disconnects from the remote server.

## Syntax

```text
public void Disconnect();

Async Version
public async Task Disconnect();
public async Task Disconnect(CancellationToken cancellationToken);
```

## Remarks

This method disconnects from the remote server and clears all service, characteristic, and descriptor data from the component. The [Disconnected](#disconnected-event-bleclient-component) event will be fired when the component has disconnected from the remote device.

Refer to the [Connect](#connect-method-bleclient-component) method for more information.

# Discover Method ([BLEClient](#bleclient-component) Component)

Convenience method to discover multiple levels of the GATT object hierarchy at once.

## Syntax

```text
public void Discover(string serviceUuids, string characteristicUuids, bool discoverDescriptors, string includedByServiceId);

Async Version
public async Task Discover(string serviceUuids, string characteristicUuids, bool discoverDescriptors, string includedByServiceId);
public async Task Discover(string serviceUuids, string characteristicUuids, bool discoverDescriptors, string includedByServiceId, CancellationToken cancellationToken);
```

## Remarks

This method can be used in place of individual calls to the [DiscoverServices](#discoverservices-method-bleclient-component), [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component), and [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) methods in order to discover GATT objects from multiple levels of the GATT hierarchy at once.

To discover root services, their characteristics, and those characteristics' descriptors, you can:

- Pass a comma-separated list of service UUIDs for the services which you are interested in to the *ServiceUuids* parameter.
- Pass a comma-separated list of characteristic UUIDs for the characteristics which you are interested in (for any and all services which could be discovered) to the *CharacteristicUuids* parameter.
- Pass either true or false to the *DiscoverDescriptors* parameter, based on whether or not you wish to discover descriptors for discovered characteristics.
- Pass the empty string to the *IncludedByServiceId* parameter.

If you wish to discover included services, their characteristics, and those characteristics' descriptors, the above still applies, but you should pass the Id of an already discovered service to the *IncludedByServiceId* parameter.

You have the option of passing the empty string to either, or both, of the *ServiceUuids* and *CharacteristicUuids* parameters if you do not wish to limit your discovery to specific services and/or characteristics, but doing so is **strongly discouraged** due to the additional power consumption that will result.

During the discovery process, the [Discovered](#discovered-event-bleclient-component) event will fire once for each GATT object discovered. You may control whether it fires when a GATT object is rediscovered by setting the [IncludeRediscovered](#IncludeRediscovered) configuration setting.

Keep in mind that having any of the following configuration settings enabled when you call this method may cause additional, unwanted power consumption: [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics), [AutoDiscoverDescriptors](#AutoDiscoverDescriptors), or [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices).

**Multi-Level Discovery**

```csharp
string serviceUUIDs = "180A,F000AA70-0451-4000-B000-000000000000,F000AA20-0451-4000-B000-000000000000";
string characteristicUUIDs = ""; //All Characteristics
bool discoverDescriptors = true;
string includedByServiceId = ""; //No included services

// This will discover all characteristics and descriptors for specific services.
bleclient1.Discover(serviceUUIDs, characteristicUUIDs, discoverDescriptors, includedByServiceId);

// This will discover everything on the server, but won't discover
// the "includes"/"included by" service relationships.
bleclient1.Discover("", "", true, "");
```

# DiscoverCharacteristics Method ([BLEClient](#bleclient-component) Component)

Used to discover characteristics for a specific service.

## Syntax

```text
public void DiscoverCharacteristics(string serviceId, string characteristicUuids);

Async Version
public async Task DiscoverCharacteristics(string serviceId, string characteristicUuids);
public async Task DiscoverCharacteristics(string serviceId, string characteristicUuids, CancellationToken cancellationToken);
```

## Remarks

This method is used to discover characteristics that belong to the service represented by *ServiceId*. Discovered characteristics' data will be used to populate the [Characteristics](#characteristics-property-bleclient-component) collection property when the [Service](#service-property-bleclient-component) property is set to the applicable service Id.

It is recommended that you pass a comma-separated list of characteristic UUIDs for the *CharacteristicUuids* parameter in order to limit discovery to just the characteristics that you are interested in. You may also pass the empty string to discover all of the service's characteristics, but doing so will result in higher power consumption.

During the discovery process, the [Discovered](#discovered-event-bleclient-component) event will fire once for each characteristic discovered. You may control whether it fires when a characteristic is rediscovered by setting the [IncludeRediscovered](#IncludeRediscovered) configuration setting.

Keep in mind that having any of the following configuration settings enabled when you call this method may cause additional, unwanted power consumption: [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics), [AutoDiscoverDescriptors](#AutoDiscoverDescriptors), or [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices).

**Characteristic Discovery**

```csharp
// Discovered event handler.
bleclient1.OnDiscovered += (s, e) => {
  Console.WriteLine("Characteristic discovered:" +
    "\r\n\tOwning Service Id: " + e.ServiceId +
    "\r\n\tCharacteristic Id: " + e.CharacteristicId +
    // The discovered characteristic's 128-bit UUID string, in the format
    // "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    "\r\n\tUUID: " + e.Uuid +
    // For standard characteristics whose UUIDs are defined by the Bluetooth SIG,
    // the Description event parameter will contain the name of the characteristic.
    "\r\n\tDescription: " + e.Description);
};

// Discover all characteristics for the service whose Id is "000900000000".
// (On our CC2650STK TI SensorTag, this is the Device Information Service.)
bleclient1.DiscoverCharacteristics("000900000000", "");
```

**Filtered Characteristic Discovery**

```csharp
// Discover specific characteristics for the service whose Id is "000900000000".
// (On our CC2650STK TI SensorTag, this is the Device Information Service.)
// This will cause the System Id, Model Number String, and Manufacturer Name String
// characteristics to be discovered, respectively.
bleclient1.DiscoverCharacteristics("000900000000", "2A23,2A24,2A29");
```

# DiscoverDescriptors Method ([BLEClient](#bleclient-component) Component)

Used to discover all descriptors for a specific characteristic.

## Syntax

```text
public void DiscoverDescriptors(string serviceId, string characteristicId);

Async Version
public async Task DiscoverDescriptors(string serviceId, string characteristicId);
public async Task DiscoverDescriptors(string serviceId, string characteristicId, CancellationToken cancellationToken);
```

## Remarks

This method is used to discover all descriptors that belong to the characteristic represented by *CharacteristicId* (which is owned by the service represented by *ServiceId*). Discovered descriptors' data will be used to populate the [Descriptors](#descriptors-property-bleclient-component) collection property when the [Characteristic](#characteristic-property-bleclient-component) property is set to the applicable characteristic Id.

During the discovery process, the [Discovered](#discovered-event-bleclient-component) event will fire once for each descriptor discovered. You may control whether it fires when a descriptor is rediscovered by setting the [IncludeRediscovered](#IncludeRediscovered) configuration setting.

Keep in mind that having any of the following configuration settings enabled when you call this method may cause additional, unwanted power consumption: [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics), [AutoDiscoverDescriptors](#AutoDiscoverDescriptors), or [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices).

**Descriptor Discovery**

```csharp
// Discovered event handler.
bleclient1.OnDiscovered += (s, e) => {
  Console.WriteLine("Descriptor discovered:" +
    "\r\n\tOwning Service Id: " + e.ServiceId +
    "\r\n\tOwning Characteristic Id: " + e.CharacteristicId +
    "\r\n\tDescriptor Id: " + e.DescriptorId +
    // The discovered descriptor's 128-bit UUID string, in the format
    // "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    "\r\n\tUUID: " + e.Uuid +
    // For standard descriptors whose UUIDs are defined by the Bluetooth SIG,
    // the Description event parameter will contain the name of the descriptor.
    "\r\n\tDescription: " + e.Description);
};

// Discover all descriptors for characteristic Id "001C001D0000", owned by
// service Id "001C00000000". (On our CC2650STK TI SensorTag, this is the
// Battery Level characteristic, which is owned by the Battery Service.)
bleclient1.DiscoverDescriptors("001C00000000", "001C001D0000");
```

# DiscoverServices Method ([BLEClient](#bleclient-component) Component)

Used to discover services for the currently connected server.

## Syntax

```text
public void DiscoverServices(string serviceUuids, string includedByServiceId);

Async Version
public async Task DiscoverServices(string serviceUuids, string includedByServiceId);
public async Task DiscoverServices(string serviceUuids, string includedByServiceId, CancellationToken cancellationToken);
```

## Remarks

This method is used to discover root services on the currently connected server when empty string is passed for the *IncludedByServiceId* parameter. Passing the Id of an already-discovered service instead will cause the component to discover services included by that service.

All discovered services, root or otherwise, are added to the [Services](#services-property-bleclient-component) collection property.

It is recommended that you pass a comma-separated list of service UUIDs for the *ServiceUuids* parameter in order to limit discovery to just the services that you are interested in. You may also pass the empty string to discover all of the server's services (or all of a service's included services), but doing so will result in much higher power consumption.

During the discovery process, the [Discovered](#discovered-event-bleclient-component) event will fire once for each service discovered. You may control whether it fires when a service is rediscovered by setting the [IncludeRediscovered](#IncludeRediscovered) configuration setting.

Keep in mind that having any of the following configuration settings enabled when you call this method may cause additional, unwanted power consumption: [AutoDiscoverCharacteristics](#AutoDiscoverCharacteristics), [AutoDiscoverDescriptors](#AutoDiscoverDescriptors), or [AutoDiscoverIncludedServices](#AutoDiscoverIncludedServices).

**Service Discovery**

```csharp
// Discovered event handler.
bleclient1.OnDiscovered += (s, e) => {
  Console.WriteLine("Service discovered:" +
    "\r\n\tService Id: " + e.ServiceId +
    // The discovered service's 128-bit UUID string, in the format
    // "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    "\r\n\tUUID: " + e.Uuid +
    // For standard services whose UUIDs are defined by the Bluetooth SIG,
    // the Description event parameter will contain the name of the service.
    "\r\n\tDescription: " + e.Description);
};

// Discover all root services.
bleclient1.DiscoverServices("", "");

// Discover all services included by a discovered service whose Id is "000100000000".
bleclient1.DiscoverServices("", "000100000000");
```

**Filtered Service Discovery**

```csharp
// Discover specific root services. These three UUIDs will cause the Device Information,
// Luxometer, and Humidity services to be discovered on our CC2650STK TI SensorTag.
// (Since the latter two are non-standard, you have to use their full UUIDs.)
bleclient1.DiscoverServices("180A,F000AA70-0451-4000-B000-000000000000,F000AA20-0451-4000-B000-000000000000", "");

// Discover specific services included by a discovered service whose Id is "000100000000".
// (The TI SensorTag doesn't have any included services, this is just an example.)
bleclient1.DiscoverServices("FFFFFFFF-9000-4000-B000-000000000000", "000100000000")
```

# DoEvents Method ([BLEClient](#bleclient-component) Component)

This method processes events from the internal message queue.

## Syntax

```text
public void DoEvents();

Async Version
public async Task DoEvents();
public async Task DoEvents(CancellationToken cancellationToken);
```

## Remarks

When DoEvents is called, the component processes any available events. If no events are available, it waits for a preset period of time, and then returns.

Note that while calling this method is not normally necessary when working in form-based applications, it is required when using the component on Linux to ensure proper event processing.

# PostValue Method ([BLEClient](#bleclient-component) Component)

Write the value of a characteristic without expecting a response.

## Syntax

```text
public void PostValue(string serviceId, string characteristicId, byte[] value);

Async Version
public async Task PostValue(string serviceId, string characteristicId, byte[] value);
public async Task PostValue(string serviceId, string characteristicId, byte[] value, CancellationToken cancellationToken);
```

## Remarks

This method is used to write the value of a characteristic, but unlike [WriteValue](#writevalue-method-bleclient-component) it instructs the server not to send a response, even if the write request fails. This method will return immediately after the request is sent, regardless of the current [Timeout](#timeout-property-bleclient-component) value.

If your use-case doesn't require confirmation of characteristic value writes, this method is preferred; it allows both devices (but especially the server) to save power by keeping the BLE radio hardware turned off.

If you do require confirmation of characteristic value writes, or need to write a descriptor's value, use the [WriteValue](#writevalue-method-bleclient-component) method.

**Posting Values**

```csharp
// The CC2650STK TI SensorTag doesn't have any characteristics which support
// write without response, so this is just an example.
bleclient1.PostValue("00AA00000000", "00AA00BB0000", new byte[] { 0x1, 0x2, 0x3 });
```

# QueryCharacteristicCachedVal Method ([BLEClient](#bleclient-component) Component)

Reads and returns a characteristic value from the value cache.

## Syntax

```text
public byte[] QueryCharacteristicCachedVal(int index);

Async Version
public async Task<byte[]> QueryCharacteristicCachedVal(int index);
public async Task<byte[]> QueryCharacteristicCachedVal(int index, CancellationToken cancellationToken);
```

## Remarks

This method will return the cached value for the characteristic. The method uses the given *index* parameter to find the characteristic at the *index* of the [Characteristics](#characteristics-property-bleclient-component) property. The method then uses that characteristic to retrieve information from the value cache.

# QueryDescriptorCachedVal Method ([BLEClient](#bleclient-component) Component)

Reads and returns a descriptor value from the value cache.

## Syntax

```text
public byte[] QueryDescriptorCachedVal(int index);

Async Version
public async Task<byte[]> QueryDescriptorCachedVal(int index);
public async Task<byte[]> QueryDescriptorCachedVal(int index, CancellationToken cancellationToken);
```

## Remarks

This method will return the cached value for the descriptor. The method uses the given *index* parameter to find the descriptor at the *index* of the [Descriptors](#descriptors-property-bleclient-component) property. The method then uses that descriptor to retrieve information from the value cache.

# ReadValue Method ([BLEClient](#bleclient-component) Component)

Read the value of a characteristic or descriptor from the server.

## Syntax

```text
public byte[] ReadValue(string serviceId, string characteristicId, string descriptorId);

Async Version
public async Task<byte[]> ReadValue(string serviceId, string characteristicId, string descriptorId);
public async Task<byte[]> ReadValue(string serviceId, string characteristicId, string descriptorId, CancellationToken cancellationToken);
```

## Remarks

This method is used to read the value of a characteristic or a descriptor directly from the server, bypassing the platform's cache in the process.

To read the value of a characteristic, pass the Ids of it and its owning service for the *CharacteristicId* and *ServiceId* parameters, and pass empty string for the *DescriptorId* parameter. To read the value of a descriptor, do the same thing, but pass the descriptor's Id for the *DescriptorId* parameter too.

If the read request is successful, the read value will be returned and the [Value](#value-event-bleclient-component) event will be fired. In addition, the platform will cache the value; you can retrieve the cached for a characteristic using [CachedValue](#@@BLEClient_Characteristic@@_f_CachedValue) or for a descriptor using [CachedValue](#@@BLEClient_Descriptor@@_f_CachedValue).

If the read request fails, the [Error](#error-event-bleclient-component) event will be fired and the component throws an exception.

If the value of a characteristic changes often, prefer subscribing to the characteristic over polling in order to prevent unnecessary power consumption. Refer to the [Subscribe](#subscribe-method-bleclient-component) method for more information.

**Reading Live Values**

```csharp
// Value event handler.
bleclient1.OnValue += (s, e) => {
  if (string.IsNullOrEmpty(e.DescriptorId)) {
    Console.WriteLine("Read value {" + BitConverter.ToString(e.ValueB) +
      "} for characteristic with UUID " + e.Uuid);
  } else {
    Console.WriteLine("Read value {" + BitConverter.ToString(e.ValueB) +
    "} for descriptor with UUID " + e.Uuid);
  }
};

// Print the live value for the Battery Level characteristic. These Ids
// are correct for our CC2650STK TI SensorTag, but yours might differ.
byte[] rawBatteryVal = bleclient1.ReadValue("001C00000000", "001C001D0000", "");
Console.WriteLine("Battery Level Value: " + (int)rawBatteryVal[0]);

// Print the live value for the Characteristic Presentation Format descriptor on
// the Battery Level characteristic. Again, your Ids might differ.
byte[] rawBatteryPF = bleclient1.ReadValue("001C00000000", "001C001D0000", "001C001D0021");
Console.WriteLine("Battery Level Presentation Format bytes: " + BitConverter.ToString(rawBatteryPF));
```

**Reading Cached Values**

```csharp
// Print the cached value for the Luxometer Data characteristic (which you can
// assume we've already found and assigned to a variable called "luxChara").
byte[] rawLuxVal = luxChara.CachedValueB;
ushort luxVal = BitConverter.ToUInt16(rawLuxVal, 0);
Console.WriteLine("Luxometer Value: " + luxVal);

// Print the cached value for the Client Characteristic Configuration descriptor on
// the Luxometer Data characteristic (again, assume it's stored in "luxCCCD").
byte[] rawLuxCCCD = luxCCCD.CachedValueB;
Console.WriteLine("Luxometer CCCD bytes: " + BitConverter.ToString(rawLuxCCCD));
```

# Select Method ([BLEClient](#bleclient-component) Component)

Used to set the currently selected service and characteristic by their Ids.

## Syntax

```text
public void Select(string serviceId, string characteristicId);

Async Version
public async Task Select(string serviceId, string characteristicId);
public async Task Select(string serviceId, string characteristicId, CancellationToken cancellationToken);
```

## Remarks

This is a convenience method used to select a specific service and/or characteristic.

To select just a service, only pass the desired service Id for *ServiceId*; pass empty string for *CharacteristicId*. To select a characteristic, pass both of the Ids.

As long as both of the Ids are valid, the [Service](#service-property-bleclient-component) and [Characteristic](#characteristic-property-bleclient-component) properties will be set accordingly ([Characteristic](#characteristic-property-bleclient-component) is cleared if a characteristic Id isn't given).

An error will be thrown if any of the Ids aren't valid, or if an invalid combination of Ids is passed.

# StartScanning Method ([BLEClient](#bleclient-component) Component)

Causes the component to begin scanning for BLE GATT servers.

## Syntax

```text
public void StartScanning(string serviceUuids);

Async Version
public async Task StartScanning(string serviceUuids);
public async Task StartScanning(string serviceUuids, CancellationToken cancellationToken);
```

## Remarks

This method causes the component to start scanning for BLE GATT servers, optionally filtered to include only servers which are advertising one or more services of interest.

To scan for all servers, pass empty string as the *ServiceUuids* parameter.

To scan for only servers advertising specific services, pass a comma-separated list of service UUIDs as the *ServiceUuids* parameter. (Only servers advertising **all** of the given services will be detected. Be aware that, due to the limited space in an advertisement packet, it's common for servers to support more services than they advertise.)

The [StartScan](#startscan-event-bleclient-component) event will be fired when the scanning has begun, after which the [Advertisement](#advertisement-event-bleclient-component) event is fired whenever an advertisement from a server is received; the [Error](#error-event-bleclient-component) event is fired if an error occurs.

If you wish to use active scanning, enable the [ActiveScanning](#activescanning-property-bleclient-component) property before you call StartScanning (refer to its documentation for more information).

You may start scanning while already connected to a server, but the component will stop scanning automatically if you attempt to initiate a new server connection (regardless of whether or not that connection attempt ends up succeeding).

Please be aware that scanning is a power-intensive activity, and you should call the [StopScanning](#stopscanning-method-bleclient-component) method as soon as is appropriate in order to prevent unnecessary power consumption.

Calling StartScanning when the component is already scanning does nothing.

**Basic Scanning and Advertisement Handling Example**

```csharp
// StartScan event handler.
bleclient1.OnStartScan += (s, e) => Console.WriteLine("Scanning has started");
// StopScan event handler.
bleclient1.OnStopScan += (s, e) => Console.WriteLine("Scanning has stopped");
// Advertisement event handler.
bleclient1.OnAdvertisement += (s, e) => {
  // Your application should make every effort to handle the Advertisement event quickly.
  // BLEClient fires it as often as necessary, often multiple times per second.
  Console.WriteLine("Advertisement Received:" +
    "\r\n\tServerId: " + e.ServerId +
    "\r\n\tName: " + e.Name +
    "\r\n\tRSSI: " + e.RSSI +
    "\r\n\tTxPower: " + e.TxPower +
    "\r\n\tServiceUuids: " + e.ServiceUuids +
    "\r\n\tServicesWithData: " + e.ServicesWithData +
    "\r\n\tSolicitedServiceUuids: " + e.SolicitedServiceUuids +
    "\r\n\tManufacturerCompanyId:  " + e.ManufacturerCompanyId +
    // We use BitConverter.ToString() to print data as hex bytes; this also prevents
    // an issue where the string could be cut off early if the data has a 0 byte in it.
    "\r\n\tManufacturerCompanyData:  " + BitConverter.ToString(e.ManufacturerDataB) +
    "\r\n\tIsConnectable:  " + e.IsConnectable +
    "\r\n\tIsScanResponse:  " + e.IsScanResponse);
};

// Scan for all devices.
bleclient1.StartScanning("");
// Wait a while...
bleclient1.StopScanning();
```

**Filtered Scanning Example**

```csharp
// Scan for devices which are advertising at least these UUIDs. You can use a mixture
// of 16-, 32-, and 128-bit UUID strings, they'll be converted to 128-bit internally.
bleclient1.StartScanning("180A,0000180F,00001801-0000-1000-8000-00805F9B34FB");
// ...
bleclient1.StopScanning();
```

# StopScanning Method ([BLEClient](#bleclient-component) Component)

Causes the component to stop scanning for BLE GATT servers.

## Syntax

```text
public void StopScanning();

Async Version
public async Task StopScanning();
public async Task StopScanning(CancellationToken cancellationToken);
```

## Remarks

This method will request that the component stop scanning for BLE GATT servers if it is currently doing so, otherwise it will do nothing. The [StopScan](#stopscan-event-bleclient-component) event will fire when the scanning has stopped.

Note that scanning may be stopped automatically by the platform under certain conditions; the [StopScan](#stopscan-event-bleclient-component) event will contain the error code and description if applicable.

You can check the [Scanning](#scanning-property-bleclient-component) property to determine whether or not the component is currently scanning.

# Subscribe Method ([BLEClient](#bleclient-component) Component)

Subscribes to value updates for the specified characteristic.

## Syntax

```text
public void Subscribe(string serviceId, string characteristicId);

Async Version
public async Task Subscribe(string serviceId, string characteristicId);
public async Task Subscribe(string serviceId, string characteristicId, CancellationToken cancellationToken);
```

## Remarks

This method will subscribe the component to value updates for the characteristic whose Id is passed to *CharacteristicId* (which is owned by the service specified by *ServiceId*), as long as the characteristic supports it.

You can check a characteristic's [CanSubscribe](#@@BLEClient_Characteristic@@_f_CanSubscribe) field to determine whether or not it supports subscriptions.

The [Subscribed](#subscribed-event-bleclient-component) event will fire whenever you subscribe to a characteristic. While subscribed to a characteristic, the [Value](#value-event-bleclient-component) event will be fired each time the server sends an updated value for it (and its cached value will be updated as well).

The characteristic's [Subscribed](#@@BLEClient_Characteristic@@_f_Subscribed) field can be used to determine whether or not the component is currently subscribed to a characteristic. You can also set it to *true* or *false*, which will automatically call Subscribe or [Unsubscribe](#unsubscribe-method-bleclient-component).

An error will be thrown if either of the given Ids are invalid, if the characteristic does not support subscribing for updates, or if there is an issue while trying to subscribe. Trying to subscribe to an already-subscribed characteristic does nothing.

**Subscriptions**

```csharp
// Subscribed event handler.
bleclient1.OnSubscribed += (s, e) => {
  Console.WriteLine("Subscribed to characteristic:" +
    "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid +
    "\r\n\tDescription: " + e.Description);
};
// Unsubscribed event handler.
bleclient1.OnUnsubscribed += (s, e) => {
  Console.WriteLine("Unsubscribed from characteristic:" +
    "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid +
    "\r\n\tDescription: " + e.Description);
};
// Value event handler.
bleclient1.OnValue += (s, e) => {
  Console.WriteLine("Value update received for characteristic: " +
    "\r\n\tID: " + e.CharacteristicId +
    "\r\n\tUUID: " + e.Uuid +
    "\r\n\tDescription: " + e.Description +
    "\r\n\tValue: " + BitConverter.ToString(e.ValueB));
};

// Assume that we've already found the Luxometer Data characteristic,
// its owning service, and the Client Characteristic Configuration
// descriptor on it; and we've stored them in variables called "luxSvc",
// "luxData", and "luxCCCD".

// Subscribe and unsubscribe using methods.
bleclient1.Subscribe(luxSvc.Id, luxData.Id);
// ...
bleclient1.Unsubscribe(luxSvc.Id, luxData.Id);

// Subscribe and unsubscribe using the "Subscribed" field.
luxData.Subscribed = true;
// ...
luxData.Subscribed = false;

// Subscribe and unsubscribe by writing directly to the CCCD.
bleclient1.WriteValue(luxSvc.Id, luxData.Id, luxCCCD.Id, new byte[] { 1, 0 });
// ...
bleclient1.WriteValue(luxSvc.Id, luxData.Id, luxCCCD.Id, new byte[] { 0, 0 });
```

# Unsubscribe Method ([BLEClient](#bleclient-component) Component)

Unsubscribes from value updates for one or more characteristics.

## Syntax

```text
public void Unsubscribe(string serviceId, string characteristicId);

Async Version
public async Task Unsubscribe(string serviceId, string characteristicId);
public async Task Unsubscribe(string serviceId, string characteristicId, CancellationToken cancellationToken);
```

## Remarks

This method will unsubscribe from value updates for the characteristic represented by *CharacteristicId* (which is owned by the service specified by *ServiceId*). The [Unsubscribed](#unsubscribed-event-bleclient-component) event will fire each time you unsubscribe from a characteristic.

Passing empty string for *CharacteristicId* will cause the component to unsubscribe from any characteristic it is subscribed to in the specified service. Passing empty string for both parameters does the same, but for all services. (Unsubscribing *en masse* may take time since every subscribe/unsubscribe operation requires a write request and response behind the scenes.)

An error will be thrown if either of the given Ids are invalid (when both are passed), if only *CharacteristicId* is passed, if the characteristic does not support subscribing for updates, or if there is an issue while trying to unsubscribe.

Refer to the [Subscribe](#subscribe-method-bleclient-component) method for more information.

# WriteValue Method ([BLEClient](#bleclient-component) Component)

Write the value of a characteristic or descriptor.

## Syntax

```text
public void WriteValue(string serviceId, string characteristicId, string descriptorId, byte[] value);

Async Version
public async Task WriteValue(string serviceId, string characteristicId, string descriptorId, byte[] value);
public async Task WriteValue(string serviceId, string characteristicId, string descriptorId, byte[] value, CancellationToken cancellationToken);
```

## Remarks

This method is used to write the value of a characteristic or descriptor. The method will return and the [WriteResponse](#writeresponse-event-bleclient-component) event will fire if the write is a success. If the write fails, the [Error](#error-event-bleclient-component) event will fire and the component throws an exception.

To write the value of a characteristic, pass the Ids of it and its owning service for the *CharacteristicId* and *ServiceId* parameters, and pass empty string for the *DescriptorId* parameter. To write the value of a descriptor, do the same thing, but pass the descriptor's Id for the *DescriptorId* parameter too.

If your use-case doesn't require confirmation of characteristic value writes, prefer the [PostValue](#postvalue-method-bleclient-component) method in order to reduce power consumption.

**Writing Values**

```csharp
// WriteResponse event handler.
bleclient1.OnWriteResponse += (s, e) => {
  if (string.IsNullOrEmpty(e.DescriptorId)) {
    Console.WriteLine("Successfully wrote to characteristic with UUID " + e.Uuid);
  } else {
    Console.WriteLine("Successfully wrote to descriptor with UUID " + e.Uuid);
  }
};

// Write to the Luxometer Config characteristic. These Ids are correct
// for our CC2650STK TI SensorTag, but yours might differ.
bleclient1.WriteValue("004200000000", "004200460000", "", new byte[] { 0x1 });

// Write to the Client Characteristic Configuration descriptor on the
// Luxometer Data characteristic. Again, your Ids might differ.
bleclient1.WriteValue("004200000000", "004200430000", "004200430045", new byte[] { 0x1 });
```

# Advertisement Event ([BLEClient](#bleclient-component) Component)

Fired when an advertisement packet is received during scanning.

## Syntax

```text
public event OnAdvertisementHandler OnAdvertisement;

public delegate void OnAdvertisementHandler(object sender, BLEClientAdvertisementEventArgs e);

public class BLEClientAdvertisementEventArgs : EventArgs {
  public string ServerId { get; }
  public string Name { get; }
  public int RSSI { get; }
  public int TxPower { get; }
  public string ServiceUuids { get; }
  public string ServicesWithData { get; }
  public string SolicitedServiceUuids { get; }
  public int ManufacturerCompanyId { get; }
  public string ManufacturerData { get; }  public byte[] ManufacturerDataB { get; }
  public bool IsConnectable { get; }
  public bool IsScanResponse { get; }
}
```

## Remarks

The Advertisement event is fired each time an advertisement is received while the component is [Scanning](#scanning-property-bleclient-component) for servers to connect to. Based on the information in the advertisement, you can decide whether or not you wish to connect to the associated device (if it is connectable).

Not all of the parameters are relevant for all platforms. Additionally, since advertisement packets are somewhat flexible in their contents, it is not guaranteed that every parameter relevant to your platform will be populated for every advertisement. Please refer to the following table for descriptions of the parameters:

| Parameter | Description |
| --- | --- |
| ServerId | Platform-specific server Id string |
| Name | Server's local name, either shortened or complete |
| RSSI | Server RSSI in dBm (.NET), or dB (macOS/iOS) |
| TxPower | Server transmit power in dBm (Or integer's MinValue if not in advertisement) |
| ServiceUuids | Comma-separated list of 128-bit service UUID strings |
| ServicesWithData | Comma-separated list of 128-bit service UUID strings for services which the advertisement contained data for |
| SolicitedServiceUuids | Comma-separated list of 128-bit solicited service UUID strings |
| ManufacturerCompanyId | Company Id from the first manufacturer data section in the advertisement (Or -1 if there are none) |
| ManufacturerData | Data from the first manufacturer data section in the advertisement (Or empty if there are none) |
| IsConnectable | Whether the device which sent this advertisement is accepting connections |
| IsScanResponse | Whether this is a scan response packet |

Setting the [ServiceData](#ServiceData) configuration setting to any of the service UUIDs in the *ServicesWithData* parameter will return the associated data.

You can use the [ManufacturerDataCount](#ManufacturerDataCount) configuration setting to determine whether the advertisement contains multiple manufacturer data sections; if it does, the [ManufacturerData](#ManufacturerData) and [ManufacturerCompanyId](#ManufacturerCompanyId) configuration settings can be used to iterate over them.

Note that all of the configuration settings mentioned above are only valid while you are within the Advertisement event handler.

Please refer to the following table to determine which parameters are relevant for your platform:

| Parameter | .NET | macOS/iOS |
| --- | --- | --- |
| ServerId | X | X |
| Name | X | X |
| RSSI | X | X |
| TxPower | X | X |
| ServiceUuids | X | X |
| ServicesWithData | X | X |
| SolicitedServiceUuids | X | X |
| ManufacturerCompanyId | X | X |
| ManufacturerData | X | X |
| IsConnectable | X | X |
| IsScanResponse | X |  |

Note: *IsConnectable* will always be *false* when *IsScanResponse* is *true*.

Refer to the [StartScanning](#startscanning-method-bleclient-component) method for more information.

# Connected Event ([BLEClient](#bleclient-component) Component)

Fired immediately after a connection to a remote device completes (or fails).

## Syntax

```text
public event OnConnectedHandler OnConnected;

public delegate void OnConnectedHandler(object sender, BLEClientConnectedEventArgs e);

public class BLEClientConnectedEventArgs : EventArgs {
  public int StatusCode { get; }
  public string Description { get; }
}
```

## Remarks

If the connection is made successfully, *StatusCode* is 0 and *Description* is "OK".

If the connection fails, *StatusCode* has the error code returned by the Bluetooth stack. *Description* contains a description of this code.

Refer to the [Connect](#connect-method-bleclient-component) method for more information.

# Disconnected Event ([BLEClient](#bleclient-component) Component)

Fired when the component has been disconnected from the remote device.

## Syntax

```text
public event OnDisconnectedHandler OnDisconnected;

public delegate void OnDisconnectedHandler(object sender, BLEClientDisconnectedEventArgs e);

public class BLEClientDisconnectedEventArgs : EventArgs {
  public int StatusCode { get; }
  public string Description { get; }
}
```

## Remarks

If the connection is broken normally, *StatusCode* is 0 and *Description* is "OK".

If the connection is broken for any other reason, *StatusCode* has the error code returned by the Bluetooth stack. *Description* contains a description of this code.

Refer to the [Disconnect](#disconnect-method-bleclient-component) section for more information.

# Discovered Event ([BLEClient](#bleclient-component) Component)

Fired when the component discovers a service, characteristic, or descriptor.

## Syntax

```text
public event OnDiscoveredHandler OnDiscovered;

public delegate void OnDiscoveredHandler(object sender, BLEClientDiscoveredEventArgs e);

public class BLEClientDiscoveredEventArgs : EventArgs {
  public int GattType { get; }
  public string ServiceId { get; }
  public string CharacteristicId { get; }
  public string DescriptorId { get; }
  public string Uuid { get; }
  public string Description { get; }
}
```

## Remarks

This event is fired during any discovery process to indicate that the component has discovered a service, characteristic, or descriptor. Discovery processes take place whenever [Discover](#discover-method-bleclient-component), [DiscoverServices](#discoverservices-method-bleclient-component), [DiscoverCharacteristics](#discovercharacteristics-method-bleclient-component), or [DiscoverDescriptors](#discoverdescriptors-method-bleclient-component) is called.

*GattType* indicates what type of GATT object was discovered:

- 0 - Service
- 1 - Characteristic
- 2 - Descriptor

*Uuid* and *Description* are the UUID and Bluetooth SIG user-friendly name (if one is defined) of the discovered service, characteristic, or descriptor.

When a service is discovered:

- *ServiceId* is the Id of the newly discovered service.
- *CharacteristicId* is empty.
- *DescriptorId* is empty.

When a characteristic is discovered:

- *ServiceId* is the Id of the previously discovered service which owns the newly discovered characteristic.
- *CharacteristicId* is the Id of the newly discovered characteristic.
- *DescriptorId* is empty.

When a descriptor is discovered:

- *ServiceId* is the Id of the previously discovered service which owns the previously discovered characteristic.
- *CharacteristicId* is the Id of the previously discovered characteristic which owns the newly discovered descriptor.
- *DescriptorId* is the Id of the newly discovered descriptor.

# Error Event ([BLEClient](#bleclient-component) Component)

Fired when information is available about errors during data delivery.

## Syntax

```text
public event OnErrorHandler OnError;

public delegate void OnErrorHandler(object sender, BLEClientErrorEventArgs e);

public class BLEClientErrorEventArgs : EventArgs {
  public int ErrorCode { get; }
  public string Description { get; }
}
```

## Remarks

The Error event is fired in case of exceptional conditions during message processing. Normally the component throws an exception.

The *ErrorCode* parameter contains an error code, and the *Description* parameter contains a textual description of the error. For a list of valid error codes and their descriptions, please refer to the [Error Codes](#trappable-errors-bleclient-component) section.

# Log Event ([BLEClient](#bleclient-component) Component)

Fires once for each log message.

## Syntax

```text
public event OnLogHandler OnLog;

public delegate void OnLogHandler(object sender, BLEClientLogEventArgs e);

public class BLEClientLogEventArgs : EventArgs {
  public int LogLevel { get; }
  public string Message { get; }
  public string LogType { get; }
}
```

## Remarks

This events fires once for each log message generated by the component. The verbosity is controlled by the [LogLevel](#LogLevel) setting.

*LogLevel* indicates the level of the *Message*. Possible values are:

|  |  |
| --- | --- |
| 0 (None) | No events are logged. |
| 1 (Info - default) | Informational events are logged. |
| 2 (Verbose) | Detailed data is logged. |
| 3 (Debug) | Debug data is logged. |

The default log level, Info, provides information when most BLE operations begin and end, and should be sufficient to get a good idea of what the component is doing at a high level.

The Verbose log level adds a few extra operation timing messages, and adds more detail to some messages logged at the Info level.

The Debug log level causes the component to output as much information as possible about what it is doing at all times. All BLE communications, even those which are typically abstracted away by the API, are logged in full detail. Typically the additional information added by this log level is not helpful to the end user, and would only be necessary to capture if you wish to report an issue to the support team.

*LogType* identifies the type of log entry. Possible values are:

- Scanning: Messages relating to scanning and advertisements.
- Connection: Messages relating to connecting, disconnecting, and connection failures.
- Discovery: Messages relating to any service, characteristic, or descriptor discovery process.
- Read: Messages relating to reading values from the remote device.
- Write: Messages relating to writing values to the remote device.
- Subscriptions: Messages relating to subscribing to and unsubscribing from characteristics.
- Info, Verbose, and Debug: Miscellaneous messages fired at the applicable log level concerning internal component operations.

# PairingRequest Event ([BLEClient](#bleclient-component) Component)

Fired when pairing is requested.

## Syntax

```text
public event OnPairingRequestHandler OnPairingRequest;

public delegate void OnPairingRequestHandler(object sender, BLEClientPairingRequestEventArgs e);

public class BLEClientPairingRequestEventArgs : EventArgs {
  public string ServerId { get; }
  public int PairingKind { get; }
  public string Pin { get; set; }
  public bool Accept { get; set; }
}
```

## Remarks

This event will fire during the pairing process, allowing the client to decide whether or not to continue with the pairing process. Pairing can be enabled by setting the [PairingMode](#PairingMode) configuration setting to *1* (Automatic), and this event must be handled in order for pairing to be enabled.

*ServerId* indicates the server for which pairing is being performed. *PairingKind* indicates the kind of pairing being requested. Possible values are:

|  |  |
| --- | --- |
| 1 | ConfirmOnly |
| 4 | ProvidePin |
| 8 | ConfirmPinMatch |

**ConfirmOnly**

The application must confirm they wish to perform the pairing action. An optional confirmation dialog may be presented to the user. Set *Accept* to true to confirm the pairing request.

**ProvidePin**

The application must request a PIN from the user. The PIN will typically be displayed on the target device. For this kind of pairing, along with setting *Accept* to true, the *Pin* parameter will need to be set to the provided PIN.

**ConfirmPinMatch**

The application must display the given PIN to the user and ask the user to confirm that the PIN matches the one shown on the target device. Set *Accept* to true to indicate the PIN values match.

# ServerUpdate Event ([BLEClient](#bleclient-component) Component)

Fired when the currently connected server updates its name or available services.

## Syntax

```text
public event OnServerUpdateHandler OnServerUpdate;

public delegate void OnServerUpdateHandler(object sender, BLEClientServerUpdateEventArgs e);

public class BLEClientServerUpdateEventArgs : EventArgs {
  public string Name { get; }
  public string ChangedServices { get; }
}
```

## Remarks

This event is fired under one of two conditions, both of which involve some sort of server-side change *other than* the value of a subscribed characteristic having changed (subscribed characteristic value updates are delivered through the [Value](#value-event-bleclient-component) event).

If the server's name has changed, this event is fired with the new name in the *Name* parameter, and the [ServerName](#servername-property-bleclient-component) property is updated as well.

If the server's services have changed, this event is fired with a non-empty value in the *ChangedServices* parameter.

# StartScan Event ([BLEClient](#bleclient-component) Component)

Fired when the component starts scanning.

## Syntax

```text
public event OnStartScanHandler OnStartScan;

public delegate void OnStartScanHandler(object sender, BLEClientStartScanEventArgs e);

public class BLEClientStartScanEventArgs : EventArgs {
  public string ServiceUuids { get; }
}
```

## Remarks

This event is fired when the component starts scanning. *ServiceUuids* is a comma-separated list of 128-bit service UUIDs that the scan is being filtered by. Refer to the [StartScanning](#startscanning-method-bleclient-component) method for more information.

# StopScan Event ([BLEClient](#bleclient-component) Component)

Fired when the component stops scanning.

## Syntax

```text
public event OnStopScanHandler OnStopScan;

public delegate void OnStopScanHandler(object sender, BLEClientStopScanEventArgs e);

public class BLEClientStopScanEventArgs : EventArgs {
  public int ErrorCode { get; }
  public string ErrorDescription { get; }
}
```

## Remarks

This event is fired when the component stops scanning. If the scanning stopped due to an error, the *ErrorCode* and *ErrorDescription* parameters will be set accordingly; otherwise they will be *0* and empty string. Refer to the [StopScanning](#stopscanning-method-bleclient-component) method for more information.

# Subscribed Event ([BLEClient](#bleclient-component) Component)

Fired when the component has successfully subscribed to a characteristic.

## Syntax

```text
public event OnSubscribedHandler OnSubscribed;

public delegate void OnSubscribedHandler(object sender, BLEClientSubscribedEventArgs e);

public class BLEClientSubscribedEventArgs : EventArgs {
  public string ServiceId { get; }
  public string CharacteristicId { get; }
  public string Uuid { get; }
  public string Description { get; }
}
```

## Remarks

This event is fired when the component has successfully subscribed to a characteristic.

*Uuid* and *Description* are the UUID and Bluetooth SIG user-friendly name (if one is defined) of the characteristic.

Refer to the [Subscribe](#subscribe-method-bleclient-component) method for more information.

# Unsubscribed Event ([BLEClient](#bleclient-component) Component)

Fired when the component has successfully unsubscribed from a characteristic.

## Syntax

```text
public event OnUnsubscribedHandler OnUnsubscribed;

public delegate void OnUnsubscribedHandler(object sender, BLEClientUnsubscribedEventArgs e);

public class BLEClientUnsubscribedEventArgs : EventArgs {
  public string ServiceId { get; }
  public string CharacteristicId { get; }
  public string Uuid { get; }
  public string Description { get; }
}
```

## Remarks

This event is fired when the component has successfully unsubscribed from a characteristic.

*Uuid* and *Description* are the UUID and Bluetooth SIG user-friendly name (if one is defined) of the characteristic

Refer to the [Unsubscribe](#unsubscribe-method-bleclient-component) method for more information.

# Value Event ([BLEClient](#bleclient-component) Component)

Fired when a characteristic or descriptor value is received from the server.

## Syntax

```text
public event OnValueHandler OnValue;

public delegate void OnValueHandler(object sender, BLEClientValueEventArgs e);

public class BLEClientValueEventArgs : EventArgs {
  public string ServiceId { get; }
  public string CharacteristicId { get; }
  public string DescriptorId { get; }
  public string Uuid { get; }
  public string Description { get; }
  public string Value { get; }  public byte[] ValueB { get; }
}
```

## Remarks

This event is fired to signify that a value has been received for a characteristic or descriptor. The *DescriptorId* parameter will be empty string if the value is for a characteristic.

*Uuid* and *Description* are the UUID and Bluetooth SIG user-friendly name (if one is defined) of the characteristic or descriptor.

There are three scenarios which can cause this event to fire:

- The server has responded to a read request for a characteristic.
- The server has responded to a read request for a descriptor.
- The server has sent an updated value for a subscribed characteristic.

Whenever a value is received for a characteristic or descriptor, the value that the platform has cached for it is updated as well. You can read the cached value for a characteristic using [CachedValue](#@@BLEClient_Characteristic@@_f_CachedValue), or for a descriptor using [CachedValue](#@@BLEClient_Descriptor@@_f_CachedValue).

Refer to the [ReadValue](#readvalue-method-bleclient-component) and/or [Subscribe](#subscribe-method-bleclient-component) methods for more information.

# WriteResponse Event ([BLEClient](#bleclient-component) Component)

Fired when the server acknowledges a successful value write request.

## Syntax

```text
public event OnWriteResponseHandler OnWriteResponse;

public delegate void OnWriteResponseHandler(object sender, BLEClientWriteResponseEventArgs e);

public class BLEClientWriteResponseEventArgs : EventArgs {
  public string ServiceId { get; }
  public string CharacteristicId { get; }
  public string DescriptorId { get; }
  public string Uuid { get; }
  public string Description { get; }
}
```

## Remarks

This event is fired when the server acknowledges a successful value write request for a characteristic or descriptor.

*ServiceId* holds the Id of the service.

*CharacteristicId* holds the Id of the characteristic.

*DescriptorId* holds the Id of the descriptor. This is only populated when a descriptor value is written.

*Uuid* and *Description* are the UUID and Bluetooth SIG user-friendly name (if one is defined) of the characteristic or descriptor.

Note that this event is *not* fired if the write request was sent using [PostValue](#postvalue-method-bleclient-component), regardless of the outcome.

Refer to the [WriteValue](#writevalue-method-bleclient-component) method for more information.

# Characteristic Type

A GATT characteristic.

## Remarks

This type represents a GATT characteristic.

The following fields are available:

- [CanSubscribe](#Characteristic_f_CanSubscribe)

- [Description](#Characteristic_f_Description)

- [Flags](#Characteristic_f_Flags)

- [Id](#Characteristic_f_Id)

- [UserDescription](#Characteristic_f_UserDescription)

- [Uuid](#Characteristic_f_Uuid)

- [ValueExponent](#Characteristic_f_ValueExponent)

- [ValueFormat](#Characteristic_f_ValueFormat)

- [ValueFormatCount](#Characteristic_f_ValueFormatCount)

- [ValueFormatIndex](#Characteristic_f_ValueFormatIndex)

- [ValueUnit](#Characteristic_f_ValueUnit)

## Fields

 **CanSubscribe** *bool (read-only)*
Default: False

Whether or not you can subscribe to receive value updates for this characteristic.

 **Description** *string (read-only)*
Default: ""

This characteristic's Bluetooth SIG user-friendly name, if one is defined.

 **Flags** *int (read-only)*
Default: 0

A bitmask of this characteristic's flags.

This field is a bitmask which represents all of the flags (or, in BLE terms, "properties") which this characteristic has set. The following table shows what bitmask is used to represent each flag:

| Bitmask | Flag |
| --- | --- |
| 0x00000001 | Broadcast |
| 0x00000002 | Read |
| 0x00000004 | Write Without Response |
| 0x00000008 | Write |
| 0x00000010 | Notify |
| 0x00000020 | Indicate |
| 0x00000040 | Authenticated Signed Writes |
| 0x00000080 | Reliable Writes (extended property) |
| 0x00000100 | Writable Auxiliaries (extended property) |

Note that, on some platforms, the component might have to automatically discover specific descriptors for the value this returns to be accurate. The component take care of handling this automatic discovery in the most energy-efficient manner possible.

 **Id** *string (read-only)*
Default: ""

An identification string which uniquely identifies this instance of this characteristic.

This identification string is guaranteed to be unchanged while the component remains connected to the device.

 **UserDescription** *string*
Default: ""

The value of the user description descriptor for this characteristic.

If the "Writable Auxiliaries" property is set for this characteristic, you can change this value, which updates it on the server too.

Note that, on some platforms, the component might have to automatically discover specific descriptors for the value this returns to be accurate. The component take care of handling this automatic discovery in the most energy-efficient manner possible.

 **Uuid** *string (read-only)*
Default: ""

This characteristic's 128-bit UUID string.

 **ValueExponent** *int (read-only)*
Default: -1

The exponent of this characteristic's value, for applicable value formats.

For an applicable [ValueFormat](#Characteristic_f_ValueFormat), this signed integer should be used as an exponent in the following formula in order to determine the actual value of the characteristic: **[Value] * 10^[Exponent]**.

 **ValueFormat** *ValueFormats (read-only)*
Default: 0

The data type of this characteristic's value.

The valid options are as follows:

| Value Type | Description |
| --- | --- |
| vfUndefined (0) | Undefined |
| vfBoolean (1) | Unsigned 1-bit; 0 = false, 1 = true |
| vf2Bit (2) | Unsigned 2-bit integer |
| vfNibble (3) | Unsigned 4-bit integer |
| vfUInt8 (4) | Unsigned 8-bit integer; exponent applies |
| vfUInt12 (5) | Unsigned 12-bit integer; exponent applies |
| vfUInt16 (6) | Unsigned 16-bit integer; exponent applies |
| vfUInt24 (7) | Unsigned 24-bit integer; exponent applies |
| vfUInt32 (8) | Unsigned 32-bit integer; exponent applies |
| vfUInt48 (9) | Unsigned 48-bit integer; exponent applies |
| vfUInt64 (10) | Unsigned 64-bit integer; exponent applies |
| vfUInt128 (11) | Unsigned 128-bit integer; exponent applies |
| vfSInt8 (12) | Signed 8-bit integer; exponent applies |
| vfSInt12 (13) | Signed 12-bit integer; exponent applies |
| vfSInt16 (14) | Signed 16-bit integer; exponent applies |
| vfSInt24 (15) | Signed 24-bit integer; exponent applies |
| vfSInt32 (16) | Signed 32-bit integer; exponent applies |
| vfSInt48 (17) | Signed 48-bit integer; exponent applies |
| vfSInt64 (18) | Signed 64-bit integer; exponent applies |
| vfSInt128 (19) | Signed 128-bit integer; exponent applies |
| vfFloat32 (20) | IEEE-754 32-bit floating point |
| vfFloat64 (21) | IEEE-754 64-bit floating point |
| vfSFloat (22) | IEEE-11073 16-bit SFLOAT |
| vfFloat (23) | IEEE-11073 32-bit FLOAT |
| vfDUInt16 (24) | IEEE-20601 format (Two UInt16 values concatenated) |
| vfUtf8Str (25) | UTF-8 string |
| vfUtf16Str (26) | UTF-16 string |
| vfStruct (27) | Opaque structure |

 **ValueFormatCount** *int (read-only)*
Default: 0

The number of value formats this characteristic has.

Characteristics whose values are an aggregate of multiple other values will often have multiple value formats as a result. In such cases, this field's value will be greater than 1, and the [ValueFormatIndex](#Characteristic_f_ValueFormatIndex) field can be used to choose which value format the [ValueFormat](#Characteristic_f_ValueFormat), [ValueExponent](#Characteristic_f_ValueExponent), and [ValueUnit](#Characteristic_f_ValueUnit) fields are populated with.

Note that, on some platforms, the component might have to automatically discover specific descriptors for the value this returns to be accurate. The component take care of handling this automatic discovery in the most energy-efficient manner possible.

 **ValueFormatIndex** *int*
Default: -1

Selects the currently populated value format details for this characteristic.

See [ValueFormatCount](#Characteristic_f_ValueFormatCount) for more details.

 **ValueUnit** *string (read-only)*
Default: ""

The 128-bit UUID string that represents the unit of measurement for this characteristic's value.

## Constructors

```text
public Characteristic();
```

# Descriptor Type

A GATT descriptor.

## Remarks

This type represents a GATT descriptor.

The following fields are available:

- [Description](#Descriptor_f_Description)

- [Id](#Descriptor_f_Id)

- [Uuid](#Descriptor_f_Uuid)

## Fields

 **Description** *string (read-only)*
Default: ""

This descriptor's Bluetooth SIG user-friendly name, if one is defined.

 **Id** *string (read-only)*
Default: ""

An identification string which uniquely identifies this instance of this descriptor.

This identification string is guaranteed to be unchanged while the component remains connected to the device.

 **Uuid** *string (read-only)*
Default: ""

This descriptor's 128-bit UUID string.

## Constructors

```text
public Descriptor();
```

# Service Type

A GATT service.

## Remarks

This type represents a GATT service.

The following fields are available:

- [Description](#Service_f_Description)

- [Id](#Service_f_Id)

- [IncludedSvcIds](#Service_f_IncludedSvcIds)

- [ParentSvcIds](#Service_f_ParentSvcIds)

- [Uuid](#Service_f_Uuid)

## Fields

 **Description** *string (read-only)*
Default: ""

This service's Bluetooth SIG user-friendly name, if one is defined.

 **Id** *string (read-only)*
Default: ""

An identification string which uniquely identifies this instance of this service.

This identification string is guaranteed to be unchanged while the component remains connected to the device.

 **IncludedSvcIds** *string (read-only)*
Default: ""

If any included services have been discovered for this service, this is a comma-separated list of their Ids.

If additional included services are discovered later, their Ids will be appended.

 **ParentSvcIds** *string (read-only)*
Default: ""

If this services is included by any other services, this is a comma-separated list of those services' Ids.

If it is discovered later that additional services include this service, their Ids will be appended.

 **Uuid** *string (read-only)*
Default: ""

This service's 128-bit UUID string.

## Constructors

```text
public Service();
```

# Config Settings ([BLEClient](#bleclient-component) Component)

 The component accepts one or more of the following *configuration settings*. Configuration settings are similar in functionality to properties, but they are rarely used. In order to avoid "polluting" the property namespace of the component, access to these *internal properties* is provided through the [Config](#config-method-bleclient-component) method.

### BLEClient Config Settings

**AutoDiscoverCharacteristics**: Whether to automatically discover all characteristics when a service is discovered.When enabled, the component will automatically attempt to discover all characteristics for every service (or included service) that it discovers.

This is disabled by default; keep in mind that enabling it will likely cause increased power consumption.

**AutoDiscoverDescriptors**: Whether to automatically discover all descriptors when a characteristic is discovered.When enabled, the component will automatically attempt to discover all descriptors for every characteristic that it discovers.

This is disabled by default; keep in mind that enabling it will likely cause increased power consumption.

**AutoDiscoverIncludedServices**: Whether to automatically discover all included services when a service is discovered.When enabled, the component will automatically attempt to discover all included services for every service (or included service) that it discovers.

An exception will be thrown if a cycle of included services is detected (this should not occur on a properly configured server).

This is disabled by default; keep in mind that enabling it will likely cause increased power consumption.

**GattObjTreeInfo**: Returns a string representation of the currently discovered GATT object tree.When queried, the component will return a string with information about the current discovered GATT object tree. This is only useful for debugging purposes.

**IncludeRediscovered**: Whether to fire the Discovered event for rediscovered services, characteristics, and descriptors.When disabled, the component will not fire the [Discovered](#discovered-event-bleclient-component) event during a discovery process for any services, characteristics, or descriptors which have already been discovered.

This is enabled by default (the component will fire [Discovered](#discovered-event-bleclient-component) for every discovery, regardless of whether or not it was a rediscovery).

**LogLevel**: The level of detail that is logged.This setting controls the level of detail that is logged through the [Log](#log-event-bleclient-component) event. Possible values are:

|  |  |
| --- | --- |
| 0 (None) | No events are logged. |
| 1 (Info - default) | Informational events are logged. |
| 2 (Verbose) | Detailed data is logged. |
| 3 (Debug) | Debug data is logged. |

The default log level, Info, provides information when most BLE operations begin and end, and should be sufficient to get a good idea of what the component is doing at a high level.

The Verbose log level adds a few extra operation timing messages, and adds more detail to some messages logged at the Info level.

The Debug log level causes the component to output as much information as possible about what it is doing at all times. All BLE communications, even those which are typically abstracted away by the API, are logged in full detail. Typically the additional information added by this log level is not helpful to the end user, and would only be necessary to capture if you wish to report an issue to the support team.

**ManufacturerCompanyId[i]**: The manufacturer company Id at index 'i'.The setting can be queried while within the [Advertisement](#advertisement-event-bleclient-component) event handler to get the company Id from the manufacturer data section at index 'i'.

Valid indices are from 0 to [ManufacturerDataCount](#ManufacturerDataCount) - 1. This setting is only valid when used within the [Advertisement](#advertisement-event-bleclient-component) event handler.

**ManufacturerData[i]**: The manufacturer data at index 'i'.The setting can be queried while within the [Advertisement](#advertisement-event-bleclient-component) event handler to get the data from the manufacturer data section at index 'i'. The data is returned as a byte string.

Valid indices are from 0 to [ManufacturerDataCount](#ManufacturerDataCount) - 1. This setting is only valid when used within the [Advertisement](#advertisement-event-bleclient-component) event handler.

**ManufacturerDataCount**: The number of manufacturer data sections an advertisement has.This setting can be queried while within the [Advertisement](#advertisement-event-bleclient-component) event handler to determine how many manufacturer data sections the advertisement contains.

This setting is only valid when used within the [Advertisement](#advertisement-event-bleclient-component) event handler.

**PairingMode**: Determines how pairing is handled while connecting.The *PairingMode* configuration setting instructs the component on how to handle pairing while connecting with a device. Possible values are:

|  |  |
| --- | --- |
| 0 | Off (default) |
| 1 | Automatic |

By default, pairing is turned off and no pairing will be performed by the component during the connection process. When set to *1* (automatic), the component will attempt to pair if pairing is supported by the device.

During the pairing process, the component will fire the [PairingRequest](#pairingrequest-event-bleclient-component) event, where the pairing request can be accepted or rejected. This event must be handled in order for pairing to succeed. If automatic pairing is enabled, a pairing failure will result in a failed connection to the device.

Note that pairing may be handled by the operating system automatically, either while connecting or while accessing certain characteristics, even when *PairingMode* is set to *0* (off).

**PreferIndications**: Whether to subscribe to characteristics using indicate when possible.There are two types of characteristic subscriptions: notifications, which are not acknowledged; and indications, which are acknowledged. This setting is disabled by default, so the component will prefer notifications when subscribing to a characteristic which supports both types of subscriptions. If this setting is enabled, the component will instead prefer indications when subscribing to such characteristics.

Note that preferring indications over notifications can result in increased power consumption since indications require an additional transmit/receive operation.

**ScanStartedTimeout**: The maximum amount of time to wait for scanning to start.This setting determines how long the [StartScanning](#startscanning-method-bleclient-component) method will wait to let the scanning process start. If the scan status does not update in that time, the [Log](#log-event-bleclient-component) event will fire with a message that scanning failed to start. The default value is 2 seconds.

**ServiceData**: Gets the data associated with a service UUID from an advertisement.While within the [Advertisement](#advertisement-event-bleclient-component) event handler, you can set this to one of the UUIDs from the [Advertisement](#advertisement-event-bleclient-component) event's *ServicesWithData* parameter to get the data associated with it. The data is returned as a byte string.

This setting is only valid when used within the [Advertisement](#advertisement-event-bleclient-component) event handler.

### Base Config Settings

**BuildInfo**: Information about the product's build.When queried, this setting will return a string containing information about the product's build.

**GUIAvailable**: Whether or not a message loop is available for processing events.In a GUI-based application, long-running blocking operations may cause the application to stop responding to input until the operation returns. The component will attempt to discover whether or not the application has a message loop and, if one is discovered, it will process events in that message loop during any such blocking operation.

In some non-GUI applications, an invalid message loop may be discovered that will result in errant behavior. In these cases, setting [GUIAvailable](#GUIAvailable) to *false* will ensure that the component does not attempt to process external events.

**LicenseInfo**: Information about the current license.When queried, this setting will return a string containing information about the license this instance of a component is using. It will return the following information:

- Product: The product the license is for.
- Product Key: The key the license was generated from.
- License Source: Where the license was found (e.g., RuntimeLicense, License File).
- License Type: The type of license installed (e.g., Royalty Free, Single Server).
- Last Valid Build: The last valid build number for which the license will work.

**MaskSensitiveData**: Whether sensitive data is masked in log messages.In certain circumstances it may be beneficial to mask sensitive data, like passwords, in log messages. Set this to *true* to mask sensitive data. The default is *true*.

**UseInternalSecurityAPI**: Whether or not to use the system security libraries or an internal implementation. When set to *false*, the component will use the system security libraries by default to perform cryptographic functions where applicable. In this case, calls to unmanaged code will be made. In certain environments, this is not desirable. To use a completely managed security implementation, set this setting to *true*.

Setting this configuration setting to *true* tells the component to use the internal implementation instead of using the system security libraries.

 On Windows, this setting is set to *false* by default. On Linux/macOS, this setting is set to *true* by default.

NOTE: This setting is static. The value set is applicable to all components used in the application.

When this value is set, the product's system dynamic link library (DLL) is no longer required as a reference, as all unmanaged code is stored in that file.

# Trappable Errors ([BLEClient](#bleclient-component) Component)

### BLEClient Errors

|  |  |
| --- | --- |
| 600 | Invalid UUID. |
| 601 | Invalid Id. |
| 602 | Action not allowed. See error message for more details. |
| 603 | Scanning error. See error message for more details. |
| 604 | Connection error. See error message for more details. |
| 605 | Must be connected to a device to perform the requested action. |
| 606 | Error during communication. See error message for more details. |
| 607 | Device unreachable during communication attempt. |
| 608 | Error during discovery. See error message for more details. |
| 609 | Component detected a cycle of included services. |
| 610 | General read error. See error message for more details. |
| 611 | General write error. See error message for more details. |
| 612 | Application-specific protocol error. This error code indicates that a protocol error code in the range 0x80-0x9F was returned during a BLE communication. Such error codes are reserved for applications to use as they see fit. Refer to the documentation of your remote device for more information. |
| 613 | Bluetooth low energy not supported. |
| 701 | Invalid Handle: The attribute handle given was not valid on this server. |
| 702 | Read Not Permitted: The attribute cannot be read due to its permissions. |
| 703 | Write Not Permitted: The attribute cannot be written due to its permissions. |
| 704 | Invalid PDU: The attribute PDU was invalid. |
| 705 | Insufficient Authentication: The attribute requires authentication before it can be read or written. |
| 706 | Request Not Supported: Attribute server does not support the request received from the client. |
| 707 | Invalid Offset: Offset specified was past the end of the attribute's value. |
| 708 | Insufficient Authorization: The attribute requires authorization before it can be read or written. |
| 709 | Prepare Queue Full: Too many prepare writes have been queued. |
| 710 | Attribute Not Found: No attribute found within the given attribute handle range. |
| 711 | Attribute Not Long: The attribute cannot be read or written using the Read Blob Request. |
| 712 | Insufficient Encryption Key Size: The Encryption Key Size used for encrypting this link is insufficient. |
| 713 | Invalid Attribute Value Length: The attribute value length is invalid for the operation. |
| 714 | Unlikely Error: The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested. |
| 715 | Insufficient Encryption: The attribute requires encryption before it can be read or written. |
| 716 | Unsupported Group Type: The attribute type is not a supported grouping attribute as defined by a higher layer specification. |
| 717 | Insufficient Resources: Insufficient Resources to complete the request. |
| 952 | Write Request Rejected: A requested write operation could not be fulfilled for reasons other than its permissions. |
| 953 | Client Characteristic Configuration Descriptor (CCCD) Improperly Configured: The CCCD is not configured according to the requirements of the profile or service. |
| 954 | Procedure Already in Progress: A profile or service request cannot be serviced because a previously triggered operation is still in progress. |
| 955 | Out of Range: An attribute value is out of range (as defined by a profile or service specification). |
