Skip to content
Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!

Peripheral

IPeripheral represents a BLE device discovered during scanning. It provides connection management and GATT operations.

Property Type Description
Uuid string Unique identifier for this peripheral
Name string? Local name (may be null)
Mtu int Usable payload per GATT operation - the negotiated ATT MTU minus the 3-byte ATT header. Starts at 20
Status ConnectionState Current connection state
IPeripheral peripheral; // from scan result
// Fire and forget - connects when in range
peripheral.Connect();
// Async - waits for connection to establish
await peripheral.ConnectAsync(cancelToken: cts.Token, timeout: TimeSpan.FromSeconds(10));

AutoConnect (on by default) keeps the peripheral connected for you - the connection is re-established when the peripheral comes back into range or is power-cycled, without you having to watch WhenDisconnected() and call Connect() again.

peripheral.Connect(new ConnectionConfig(AutoConnect: true));
// opt out - faster initial connection, but you own reconnecting
peripheral.Connect(new ConnectionConfig(AutoConnect: false));

Setting false speeds up the initial connection (the OS connects to the peripheral it can see right now instead of arming a background connect), at the cost of reconnecting yourself.

An explicit CancelConnection() is final - it tears the auto-reconnect down, so a deliberate disconnect never reconnects behind your back. Call Connect() again to arm it once more.

peripheral.CancelConnection();
// or async
await peripheral.DisconnectAsync();

Always call CancelConnection() when you’re done with a peripheral. Not doing so will leave the connection open and drain the device battery.

peripheral
.WhenStatusChanged()
.Subscribe(state =>
{
// ConnectionState: Connecting, Connected, Disconnecting, Disconnected
});
// Convenience extensions
peripheral.WhenConnected().Subscribe(p => { /* connected */ });
peripheral.WhenDisconnected().Subscribe(p => { /* disconnected */ });
peripheral
.WhenConnectionFailed()
.Subscribe(ex =>
{
// BleException with details about the failure
});

The ATT MTU (Maximum Transmission Unit) determines how much data fits in a single GATT operation. Every BLE link starts at the spec minimum of 23 bytes, of which 3 are the ATT header - so 20 bytes of payload.

// Check if ATT MTU requests are supported
if (peripheral.CanRequestMtu())
{
// 512 is the requested ATT MTU; the result is the usable payload
var payloadSize = await peripheral.TryRequestMtuAsync(512);
Console.WriteLine($"Usable payload: {payloadSize} bytes"); // 509 when 512 is granted
}
// Fragment to this value as-is
foreach (var chunk in data.Chunk(peripheral.Mtu))
await peripheral.WriteCharacteristicAsync(serviceUuid, charUuid, chunk);

Need the ATT MTU itself - to hand to a peer protocol that negotiates its own framing, for example? Add the header back:

var attMtu = peripheral.Mtu + BleConstants.AttHeaderSize;
// Check if pairing is available
if (peripheral.IsPairingRequestsAvailable())
{
var result = await peripheral
.TryPairingRequest()
.ToTask();
if (result == true)
Console.WriteLine("Paired successfully");
}
// Check current pairing status
var status = peripheral.TryGetPairingStatus();
// PairingState: NotPaired, Paired
var rssi = await peripheral.ReadRssiAsync();
Console.WriteLine($"RSSI: {rssi} dBm");