CsharpBgapi 1.0.0-ci.55
See the version list below for details.
dotnet add package CsharpBgapi --version 1.0.0-ci.55
NuGet\Install-Package CsharpBgapi -Version 1.0.0-ci.55
<PackageReference Include="CsharpBgapi" Version="1.0.0-ci.55" />
<PackageVersion Include="CsharpBgapi" Version="1.0.0-ci.55" />
<PackageReference Include="CsharpBgapi" />
paket add CsharpBgapi --version 1.0.0-ci.55
#r "nuget: CsharpBgapi, 1.0.0-ci.55"
#:package CsharpBgapi@1.0.0-ci.55
#addin nuget:?package=CsharpBgapi&version=1.0.0-ci.55&prerelease
#tool nuget:?package=CsharpBgapi&version=1.0.0-ci.55&prerelease
CsharpBgapi -- Silicon Labs BGAPI Library for C# / .NET
CsharpBgapi is a C# / .NET library for the Silicon Labs BGAPI protocol, enabling serial communication with EFR32 NCP (Network Co-Processor) devices for Bluetooth and Bluetooth Mesh applications.
This is the only actively maintained .NET implementation of the modern Silicon Labs BGAPI protocol (EFR32 series, XAPI-driven -- not the legacy Bluegiga/BLED112 protocol). It provides command/response framing, event selectors with parameter matching, retry logic, and XAPI-driven protocol definitions.
Ported from the official Python pyBGAPI library by Silicon Labs, CsharpBgapi brings the same capabilities to the .NET ecosystem.
Why CsharpBgapi?
- Modern BGAPI v3+ -- targets the current EFR32 NCP platform, not the discontinued Bluegiga/BLED112 hardware
- XAPI-driven -- protocol definitions are loaded from Silicon Labs' own XML API files, so the library stays current with new firmware versions
- .NET 10.0+ -- built for modern .NET with dependency injection, async/await, and
IOptions<T>configuration - Production-ready -- retry logic, event selectors, thread-safe serial I/O, and configurable timeouts
- Drop-in NuGet package --
dotnet add package CsharpBgapiwith built-in Bluetooth and Bluetooth Mesh XAPI definitions included
Architecture
BgapiDevice (main entry point)
+-- BgapiConnector -- Serial port I/O with framing and device ID validation
+-- BgapiProtocol -- BGAPI message encoding/decoding from XAPI definitions
+-- BgapiEventQueue -- Selector-based event waiting with retry support
- BgapiDevice orchestrates the connector, protocol, and event queue. It runs a background reader thread that dispatches responses and events.
- BgapiConnector (internal) handles raw serial communication with thread-safe send/receive locks.
- BgapiProtocol encodes commands and decodes messages using XAPI XML definitions.
- BgapiEventQueue provides
WaitEvents(selector-based event matching) andRetryUntilAsync(command retry with event confirmation). A wait takes only the events its selector selects; everything else stays queued, in arrival order, for other waiters. Unclaimed events are retained up toMaxQueuedEvents, after which the oldest is dropped and counted onDroppedEventCount.
Prerequisites
- .NET 10.0 or later
- Silicon Labs NCP hardware (e.g., EFR32 series with Bluetooth/Bluetooth Mesh firmware)
- Silicon Labs Gecko SDK (optional -- only needed if you want custom XAPI files instead of the built-in defaults)
Installation
dotnet add package CsharpBgapi
XAPI Setup
XAPI definition files describe the BGAPI protocol surface (commands, events, parameters). This library includes built-in XAPI definitions for Bluetooth and Bluetooth Mesh (v10.1.1), so most users can get started immediately.
Using Built-in Defaults
device.LoadDefaultXapis(); // Loads Bluetooth + Bluetooth Mesh definitions
Using Custom XAPI Files
If you need XAPI definitions from a different Gecko SDK version, you can load them manually:
- Install Silicon Labs Gecko SDK (via Simplicity Studio or standalone)
- Locate the XAPI files:
- Bluetooth:
<gecko_sdk>/protocol/bluetooth/api/sl_bt.xapi - Bluetooth Mesh:
<gecko_sdk>/protocol/bluetooth/api/sl_btmesh.xapi
- Bluetooth:
- Load them at runtime:
device.LoadXapi("/path/to/sl_bt.xapi");
device.LoadXapi("/path/to/sl_btmesh.xapi");
Note: Use XAPI files that match your NCP firmware version for correct protocol definitions.
Quick Start
using CsharpBgapi;
var device = new BgapiDevice();
device.LoadDefaultXapis();
device.Open("/dev/ttyACM0"); // or "COM3" on Windows
var response = await device.SendCommandAsync("bt", "system", "hello");
Console.WriteLine($"Status: {response.Status}");
device.Close();
Configuration
All tunable parameters are exposed via CsharpBgapiOptions:
| Property | Default | Description |
|---|---|---|
DefaultBaudRate |
115200 | Default baud rate for serial port communication |
SerialReadTimeoutMs |
1000 | Serial port read timeout (ms) |
SerialWriteTimeoutMs |
1000 | Serial port write timeout (ms) |
PartialFrameTimeoutMs |
500 | How long a partially received frame waits for the rest of its payload before the receive path abandons it and resyncs (ms) |
ReadExactMaxRetries |
5 | Deprecated, no longer read — superseded by PartialFrameTimeoutMs |
ResponseTimeoutSeconds |
2.0 | Default timeout for command responses |
ReaderLoopReadTimeoutMs |
100 | Read timeout for background reader loop (ms) |
StopReaderTimeoutSeconds |
2.0 | Timeout for stopping the reader thread |
WaitEventsDefaultMaxTimeSeconds |
10.0 | Default max time for WaitEvents |
MaxQueuedEvents |
1024 | How many events the queue retains for WaitEvents consumers that have not taken them yet; beyond it the oldest unclaimed event is dropped |
RetryMax |
5 | Max outer retries in RetryUntilAsync |
RetryIntervalSeconds |
1.0 | Interval between outer retries |
RetryCmdMax |
6 | Max command-level retries for transient errors |
RetryCmdIntervalSeconds |
1.0 | Interval between command retries |
Dependency Injection
Basic (loads built-in XAPI definitions automatically)
services.AddCsharpBgapi();
Without Built-in XAPI Defaults
services.AddCsharpBgapi(loadDefaultXapis: false);
With Configuration Binding
services.Configure<CsharpBgapiOptions>(configuration.GetSection("CsharpBgapi"));
services.AddCsharpBgapi();
With Inline Configuration
services.AddCsharpBgapi(options =>
{
options.ResponseTimeoutSeconds = 5.0;
options.RetryMax = 10;
});
appsettings.json
{
"CsharpBgapi": {
"DefaultBaudRate": 115200,
"SerialReadTimeoutMs": 1000,
"SerialWriteTimeoutMs": 1000,
"PartialFrameTimeoutMs": 500,
"ResponseTimeoutSeconds": 2.0,
"ReaderLoopReadTimeoutMs": 100,
"StopReaderTimeoutSeconds": 2.0,
"WaitEventsDefaultMaxTimeSeconds": 10.0,
"RetryMax": 5,
"RetryIntervalSeconds": 1.0,
"RetryCmdMax": 6,
"RetryCmdIntervalSeconds": 1.0
}
}
Usage Examples
These continue from Quick Start and additionally need
using CsharpBgapi.Events;.
Wait for Events
var selector = new NameParamSelector("btmesh_evt_vendor_model_receive");
var events = device.WaitEvents(selector, TimeSpan.FromSeconds(5), finalEventCount: 3);
Retry Pattern
var events = await device.RetryUntilAsync(
command: () => device.SendCommandAsync("btmesh", "vendor_model", "send", parameters),
eventSelector: new NameParamSelector("btmesh_evt_vendor_model_receive"),
retryParams: new RetryParams { RetryMax = 3, RetryInterval = TimeSpan.FromSeconds(2) },
finalEventCount: 1);
Subscribe to Events
device.Subscribe("btmesh_evt_vendor_model_receive", message =>
{
Console.WriteLine($"Received vendor event: {message.EventName}");
});
A handler runs on the device's only reader thread, so nothing is read off the port until it returns. A long hold can even overflow the serial receive buffer and lose frames. Keep handlers short, and treat calling a blocking method from one as unsupported:
- A synchronous
SendCommand(orAddEventFilter/RemoveEventFilter/ResetEventFilter) from a handler returnsSlStatus.Timeout, because its response cannot be read until the handler returns. The command has usually been sent by then, and the NCP may have acted on it. - A
no_returncommand such asbt.system.rebootreturnsOK, but only after any command already in flight has timed out. - Blocking on a
SendCommandAsynctask, startingRetryUntilAsync(its event wait can run on the reader thread), waiting for events, and callingClose/Disposehold the reader the same way.
Hand that work to another thread, and observe its outcome there. Work handed off this way no longer runs in event order:
device.Subscribe("bt_evt_system_boot", message =>
{
// The command runs on the thread pool, where the reader can deliver its response.
// A discarded task loses its status and exceptions, so check them inside it.
_ = Task.Run(async () =>
{
try
{
var response = await device.SendCommandAsync("bt", "system", "get_version");
if (response.Status != SlStatus.OK)
Console.WriteLine($"get_version failed: {response.Status}");
}
catch (Exception ex)
{
Console.WriteLine($"get_version threw: {ex.Message}");
}
});
});
To signal a waiter, use a TaskCompletionSource that does not resume its awaiter on the reader thread. This one also needs using CsharpBgapi.Protocol; for BgapiMessage:
var booted = new TaskCompletionSource<BgapiMessage>(TaskCreationOptions.RunContinuationsAsynchronously);
device.Subscribe("bt_evt_system_boot", message => booted.TrySetResult(message));
API Reference
| Class | Responsibility |
|---|---|
BgapiDevice |
Main entry point -- open/close, send commands, wait events, subscribe |
BgapiProtocol |
BGAPI message encoding/decoding |
BgapiEventQueue |
Event queue with selector-based waiting and retry logic |
XapiDefinitions |
XAPI XML definition loading and lookup |
EventSelector |
Event matching criteria for WaitEvents |
CsharpBgapiOptions |
Configuration POCO for all tunable parameters |
CsharpBgapiServiceExtensions |
DI registration extension methods |
SlStatus |
Silicon Labs status/error code enum (249 codes) |
CommandBuilder |
Fluent command builder for constructing BGAPI commands |
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License -- see LICENSE for details.
Note: The bundled XAPI definition files (sl_bt.xapi, sl_btmesh.xapi) originate from the Silicon Labs Gecko SDK. See the Gecko SDK license for terms governing these files.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.13)
- Microsoft.Extensions.Options (>= 10.0.13)
- System.IO.Ports (>= 10.0.13)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 1.1.0 | 0 | 10/26/2026 | |
| 1.1.0-ci.60 | 0 | 10/26/2026 | |
| 1.1.0-ci.58 | 0 | 10/26/2026 | |
| 1.0.0-ci.55 | 0 | 10/26/2026 | |
| 1.0.0-ci.53 | 47 | 10/23/2026 | |
| 1.0.0-ci.49 | 45 | 10/23/2026 | |
| 1.0.0-ci.45 | 41 | 10/23/2026 | |
| 0.3.0 | 52 | 10/23/2026 | |
| 0.3.0-ci.40 | 45 | 10/22/2026 | |
| 0.2.1-ci.38 | 63 | 10/22/2026 | |
| 0.2.0-ci.36 | 105 | 9/2/2026 | |
| 0.2.0-ci.34 | 95 | 9/2/2026 | |
| 0.1.0-ci.27 | 94 | 9/1/2026 | |
| 0.1.0-ci.23 | 182 | 7/16/2026 | |
| 0.1.0-ci.21 | 108 | 6/12/2026 | |
| 0.1.0-ci.19 | 144 | 6/12/2026 |