GATT Service
Overview
Section titled “Overview”GATT services define the data your BLE peripheral exposes. Each service contains characteristics that centrals can read from, write to, or subscribe to for notifications.
Creating a Service (Inline)
Section titled “Creating a Service (Inline)”Use the builder pattern to create services dynamically.
IBleHostingManager hostingManager; // injected
var service = await hostingManager.AddService( "Your-Service-UUID", true, // primary service sb => { sb.AddCharacteristic("char-uuid-1", cb => { cb.SetRead(request => { var data = System.Text.Encoding.UTF8.GetBytes("Hello"); return Task.FromResult(GattResult.Success(data)); });
cb.SetWrite(request => { var receivedData = request.Data; Console.WriteLine($"Received: {System.Text.Encoding.UTF8.GetString(receivedData)}"); return Task.CompletedTask; });
cb.SetNotification((subscription) => { Console.WriteLine(subscription.IsSubscribing ? "Central subscribed" : "Central unsubscribed"); return Task.CompletedTask; }); }); });Characteristic Operations
Section titled “Characteristic Operations”Return a GattResult with your data or an error status.
cb.SetRead(request =>{ // request.Peripheral - the connecting central // request.Offset - data offset var data = GetYourData(); return Task.FromResult(GattResult.Success(data));}, encrypted: false);Handle incoming writes from centrals.
cb.SetWrite(request =>{ // request.Data - the written bytes // request.Peripheral - the connecting central // request.IsReplyNeeded - whether a response is expected // request.Respond(GattState) - send response if needed
if (request.IsReplyNeeded) request.Respond(GattState.Success);
return Task.CompletedTask;}, WriteOptions.Write);WriteOptions flags: Write, WriteWithoutResponse, AuthenticatedSignedWrites, EncryptionRequired
Notifications
Section titled “Notifications”Send data to subscribed centrals.
// After setting up notification on a characteristic:var characteristic = service.Characteristics.First();
// Notify all subscribed centralsawait characteristic.Notify(data);
// Notify specific centralsawait characteristic.Notify(data, central1, central2);
// Check who is subscribedvar subscribers = characteristic.SubscribedCentrals;NotificationOptions flags: Notify, Indicate, EncryptionRequired
Managing Services
Section titled “Managing Services”// Remove a specific servicehostingManager.RemoveService("Your-Service-UUID");
// Clear all serviceshostingManager.ClearServices();
// List active servicesvar services = hostingManager.Services;Managed Characteristics
Section titled “Managed Characteristics”For more complex scenarios, use the managed characteristic pattern with dependency injection.
1. Create the Characteristic Class
Section titled “1. Create the Characteristic Class”[BleGattCharacteristic( "Your-Service-UUID", "Your-Characteristic-UUID", Notifications = NotificationOptions.Notify, Write = WriteOptions.Write)]public class MyCharacteristic : BleGattCharacteristic{ readonly ILogger<MyCharacteristic> logger;
public MyCharacteristic(ILogger<MyCharacteristic> logger) { this.logger = logger; }
public override Task OnStart() { this.logger.LogInformation("Characteristic started"); return Task.CompletedTask; }
public override void OnStop() { this.logger.LogInformation("Characteristic stopped"); }
public override Task<GattResult> OnRead(ReadRequest request) { var data = System.Text.Encoding.UTF8.GetBytes("Hello from managed"); return Task.FromResult(GattResult.Success(data)); }
public override Task OnWrite(WriteRequest request) { this.logger.LogInformation("Received: {Data}", request.Data.Length); return Task.CompletedTask; }
public override Task OnSubscriptionChanged(IPeripheral peripheral, bool subscribed) { this.logger.LogInformation("Subscription: {Subscribed}", subscribed); return Task.CompletedTask; }}2. Register
Section titled “2. Register”services.AddBleHostedCharacteristic<MyCharacteristic>();3. Attach/Detach
Section titled “3. Attach/Detach”IBleHostingManager hostingManager; // injected
// Attach all registered managed characteristics as GATT servicesawait hostingManager.AttachRegisteredServices();
// Detach when donehostingManager.DetachRegisteredServices();
// Check if attachedvar isAttached = hostingManager.IsRegisteredServicesAttached;