with one click
shiny-bluetoothle
// Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals
// Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals
| name | shiny-bluetoothle |
| description | Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals |
| triggers | ["bluetooth","ble","bluetoothle","bluetooth le","bluetooth low energy","peripheral","gatt","characteristic","scan ble","ble scan","ble connect","IBleManager","IPeripheral","managed scan","ble notification","ble write","ble read","ble descriptor","advertisement"] |
Use this skill when the user needs to:
Do NOT use this skill for BLE hosting/peripheral mode (advertising, GATT server). That is a separate library (Shiny.BluetoothLE.Hosting).
Shiny.BluetoothLEShiny.BluetoothLEShiny.BluetoothLE.ManagedRegister in your MauiProgram.cs or host builder:
// Basic registration
services.AddBluetoothLE();
// With a delegate for background events (adapter state changes, peripheral connections)
services.AddBluetoothLE<MyBleDelegate>();
// iOS/macOS only - with Apple-specific configuration
services.AddBluetoothLE<MyBleDelegate>(new AppleBleConfiguration(
ShowPowerAlert: true,
RestoreIdentifier: "my-ble-app"
));
The delegate class:
public class MyBleDelegate : BleDelegate
{
public override Task OnAdapterStateChanged(AccessState state)
{
// Handle adapter state changes (foreground or background)
return Task.CompletedTask;
}
public override Task OnPeripheralStateChanged(IPeripheral peripheral)
{
// Handle peripheral connection state changes (foreground or background)
return Task.CompletedTask;
}
}
When generating BLE client code, follow these conventions:
Always request access before scanning: Call IBleManager.RequestAccess() or RequestAccessAsync() and verify AccessState.Available before starting a scan.
Use reactive (IObservable) APIs as the primary pattern: The library is built on System.Reactive. Use the Async extension methods only when you need Task-based patterns.
Dispose scan subscriptions: Only one scan can be active at a time. Always dispose the scan subscription or call StopScan() when done.
Use string-based UUIDs for services and characteristics: The API uses string UUIDs throughout (e.g., "180D" or "0000180d-0000-1000-8000-00805f9b34fb").
Prefer ConnectAsync for simple connection flows: It handles waiting for the connected state and has a default 30-second timeout.
Always call CancelConnection() or DisconnectAsync() when done: Connections are not automatically cleaned up.
Use IManagedScan for UI-bound scanning: It provides an INotifyReadOnlyCollection that works with MVVM bindings and handles peripheral deduplication, buffering, and stale removal.
Feature detection via interface checks: Optional capabilities (MTU request, pairing, reliable transactions) use feature interfaces. Always use the Try* or Can* extension methods rather than casting directly.
Handle BleException and BleOperationException: GATT operations can throw these. BleOperationException includes a GattStatusCode.
Connection auto-reconnect: ConnectionConfig.AutoConnect = true (default) enables automatic reconnection. Set to false for faster initial connections.
IPeripheral: Both Shiny.BluetoothLE and Shiny.BluetoothLE.Hosting define an IPeripheral interface. If both packages are referenced, do NOT add Shiny.BluetoothLE.Hosting as a global using. Use file-level using or FQN (Shiny.BluetoothLE.IPeripheral) to disambiguate.DeviceInfo: Shiny.BluetoothLE has a DeviceInfo class that conflicts with Microsoft.Maui.Devices.DeviceInfo in MAUI apps. Use FQN when needed.ScanConfig with ServiceUuids to filter scans, especially on iOS where background scanning requires a service UUID filter.AndroidScanConfig for scan mode and batching options.AndroidConnectionConfig for connection priority settings.CharacteristicProperties before attempting read/write/notify operations using the convenience extensions (CanRead(), CanWrite(), CanNotify(), etc.).WriteCharacteristicBlob() for writing large data streams that exceed MTU size.NotifyCharacteristic() for real-time data streaming from a peripheral -- it handles subscription lifecycle and auto-reconnection.WhenConnected() and WhenDisconnected() convenience extensions for cleaner connection state handling.Generate code using Shiny.Speech for cross-platform speech-to-text, text-to-speech, audio capture, and audio playback with pluggable cloud providers
Generate code using Shiny Aspire integrations — Orleans ADO.NET hosting and Gluetun VPN container routing
Generate code for Shiny.AiConversation - a centralized AI service library for .NET MAUI apps with chat client abstraction, wake word detection, speech-to-text/text-to-speech, acknowledgement modes (None/AudioBlip/LessWordy/Full), persistent message store, optional AI chat history lookup tool, and configurable sound effects
Generate code using Shiny.BluetoothLE.Hosting, a BLE peripheral hosting library for .NET with GATT server, advertising, and managed characteristic patterns
Core infrastructure, hosting, DI, key-value stores, lifecycle hooks, and platform abstractions for Shiny on .NET MAUI, iOS, and Android
Guide for implementing Firebase Cloud Messaging push notifications in .NET MAUI apps using Shiny.Push.FirebaseMessaging on iOS and Android.