If you're working with Silicon Labs EFR32 Bluetooth or Bluetooth Mesh hardware and need to control it from a C# / .NET application, you've probably noticed there's no official C# SDK. Silicon Labs provides pyBGAPI for Python, but .NET developers have been left to figure things out on their own.
We built CsharpBgapi to fill that gap. This tutorial walks through setting up serial communication with an EFR32 NCP device from a .NET console application.
What is BGAPI?
BGAPI is Silicon Labs' binary protocol for communicating with their Bluetooth and Bluetooth Mesh Network Co-Processor (NCP) devices over a serial connection (UART). In NCP mode, the EFR32 chip handles the Bluetooth stack, and your host application sends commands and receives events via BGAPI.
The protocol is defined by XAPI files (XML API definitions) that ship with the Gecko SDK. These files describe every command, response, and event along with their parameters.
Prerequisites
- .NET 9.0 or later (download)
- Silicon Labs EFR32 NCP hardware (e.g., BRD4186C, BRD4187C, or any EFR32 board flashed with Bluetooth NCP firmware)
- A USB connection to your NCP device (it will appear as a COM port on Windows or
/dev/ttyACM*on Linux)
Step 1: Create a New Project
dotnet new console -n BgapiDemo
cd BgapiDemo
dotnet add package CsharpBgapi
That's it. The NuGet package includes built-in XAPI definitions for Bluetooth and Bluetooth Mesh, so you don't need the Gecko SDK installed.
Step 2: Say Hello to Your Device
The simplest BGAPI interaction is the system hello command -- it verifies that communication is working.
using CsharpBgapi;
// Create and configure the device
var device = new BgapiDevice();
device.LoadDefaultXapis(); // Load built-in Bluetooth + Mesh protocol definitions
// Open serial connection (adjust port for your system)
device.Open("COM3"); // Windows
// device.Open("/dev/ttyACM0"); // Linux
try
{
// Send the 'hello' command -- this is a simple ping
var response = await device.SendCommandAsync("bt", "system", "hello");
Console.WriteLine($"Device responded! Status: {response.Status}");
}
finally
{
device.Close();
}
Run it:
dotnet run
If your device is connected and running NCP firmware, you'll see:
Device responded! Status: Ok
Step 3: Get System Information
Let's retrieve the firmware version and Bluetooth address:
using CsharpBgapi;
var device = new BgapiDevice();
device.LoadDefaultXapis();
device.Open("COM3");
try
{
// Get firmware version
var version = await device.SendCommandAsync("bt", "system", "get_version");
Console.WriteLine($"Firmware: {version["major"]}.{version["minor"]}.{version["patch"]}");
Console.WriteLine($"Bluetooth version: {version["build"]}");
// Get Bluetooth address
var addrResponse = await device.SendCommandAsync("bt", "system", "get_identity_address");
Console.WriteLine($"BT Address: {addrResponse["address"]}");
}
finally
{
device.Close();
}
Step 4: Wait for Events
BGAPI is event-driven. After sending a command, you often need to wait for one or more events. CsharpBgapi provides EventSelector for this:
using CsharpBgapi;
var device = new BgapiDevice();
device.LoadDefaultXapis();
device.Open("COM3");
try
{
// Start scanning for BLE advertisements
await device.SendCommandAsync("bt", "scanner", "start",
new Dictionary<string, object>
{
["scanning_phy"] = 1, // 1M PHY
["discover_mode"] = 2 // Discover all devices
});
// Wait for scan report events
var selector = new EventSelector("bt", "scanner", "legacy_advertisement_report");
var events = device.WaitEvents(selector, TimeSpan.FromSeconds(5), finalEventCount: 10);
Console.WriteLine($"Found {events.Count} advertisements:");
foreach (var evt in events)
{
Console.WriteLine($" Address: {evt["address"]}, RSSI: {evt["rssi"]}");
}
// Stop scanning
await device.SendCommandAsync("bt", "scanner", "stop");
}
finally
{
device.Close();
}
Step 5: Retry Pattern for Reliable Communication
In Bluetooth Mesh, commands can fail due to network congestion. CsharpBgapi has a built-in retry mechanism:
var events = await device.RetryUntilAsync(
command: () => device.SendCommandAsync("bt", "mesh", "vendor_model_send", parameters),
eventSelector: new EventSelector("bt", "mesh", "vendor_model_receive"),
retryParams: new RetryParams
{
RetryMax = 3,
RetryInterval = TimeSpan.FromSeconds(2)
},
finalEventCount: 1
);
This sends the command, waits for a matching event, and retries up to 3 times if it doesn't arrive.
Step 6: Using Dependency Injection
For production applications, CsharpBgapi integrates with .NET's dependency injection:
using CsharpBgapi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateApplicationBuilder(args);
// Register CsharpBgapi with custom options
builder.Services.AddCsharpBgapi(options =>
{
options.ResponseTimeoutSeconds = 5.0;
options.RetryMax = 10;
});
var host = builder.Build();
var device = host.Services.GetRequiredService<BgapiDevice>();
Or bind from appsettings.json:
{
"CsharpBgapi": {
"DefaultBaudRate": 115200,
"ResponseTimeoutSeconds": 5.0,
"RetryMax": 10
}
}
builder.Services.Configure<CsharpBgapiOptions>(
builder.Configuration.GetSection("CsharpBgapi"));
builder.Services.AddCsharpBgapi();
Using Custom XAPI Files
The built-in XAPI files cover Bluetooth and Bluetooth Mesh from Gecko SDK v10.1.1. If you need a different version (to match your NCP firmware), load XAPI files manually:
var device = new BgapiDevice();
device.LoadXapi("/path/to/gecko_sdk/protocol/bluetooth/api/sl_bt.xapi");
device.LoadXapi("/path/to/gecko_sdk/protocol/bluetooth/api/sl_btmesh.xapi");
How CsharpBgapi Compares to Alternatives
| Library | Protocol | Hardware | .NET Version | Status |
|---|---|---|---|---|
| CsharpBgapi | Modern BGAPI v3+ (XAPI) | EFR32 series | .NET 9.0+ | Active |
| jrowberg/bglib | Legacy Bluegiga | BLED112/BLE112 | .NET Framework | Unmaintained (2021) |
| BgApiDriver | Legacy Bluegiga | BLED112/BLE112 | .NET 6-9 | Low activity |
| BGLib.NET | Legacy Bluegiga | BLED112/BLE112 | .NET 5.0 | Dead (2021) |
| pyBGAPI (Python) | Modern BGAPI v3+ | EFR32 series | Python 3 | Official, active |
CsharpBgapi is the only C# library targeting the modern Silicon Labs BGAPI protocol. If you're using current EFR32 hardware, this is your option for .NET.
Get Started
dotnet add package CsharpBgapi
- GitHub: Lynxal/csharp-bgapi
- NuGet: CsharpBgapi
- License: MIT
Contributions and feedback welcome! Open an issue on GitHub if you run into any problems.
CsharpBgapi is developed by Lynxal and is not affiliated with Silicon Labs. XAPI definition files bundled with the package originate from the Silicon Labs Gecko SDK.
Top comments (0)