ble-windows-server 0.2.1

A simple BLE GATT server library for Windows using WinRT APIs
Documentation

ble-windows-server

A simple, ergonomic BLE GATT server library for Windows using WinRT APIs.

Crates.io Documentation License: MIT

Features

  • Create BLE GATT services with read/notify characteristics
  • Automatic Bluetooth adapter discovery and selection
  • Multiple data type support (strings, numbers, JSON, raw bytes)
  • Async/await support with Tokio
  • Zero-copy where possible
  • Windows 10/11 support via WinRT

Requirements

  • Windows 10 (1803+) or Windows 11
  • Bluetooth adapter with BLE peripheral role support
  • Rust 1.70+

Installation

Add to your Cargo.toml:

[dependencies]

ble-windows-server = "0.1"

tokio = { version = "1", features = ["full"] }

For JSON serialization support:

[dependencies]

ble-windows-server = { version = "0.1", features = ["json"] }

Quick Start

use ble_windows_server::{WindowsBLEGattServer, Uuid};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a server with a custom service UUID
    let service_uuid = Uuid::parse_str("12345678-1234-5678-1234-567812345678")?;
    let mut server = WindowsBLEGattServer::new("MyDevice".into(), service_uuid);

    // Start advertising
    server.start().await?;

    // Send notifications
    server.notify_str("Hello BLE!").await?;

    Ok(())
}

API Overview

Creating a Server

// Basic creation (characteristic UUID auto-generated)
let server = WindowsBLEGattServer::new("DeviceName".into(), service_uuid);

// With explicit characteristic UUID
let server = WindowsBLEGattServer::with_characteristic(
    "DeviceName".into(),
    service_uuid,
    characteristic_uuid,
);

Adapter Selection

use ble_windows_server::list_adapters;

// List available adapters
let adapters = list_adapters().await?;
for adapter in &adapters {
    println!("{}", adapter);  // [0] Intel Bluetooth - MAC: AA:BB:CC:DD:EE:FF
}

// Use a specific adapter
server.use_adapter(&adapters[0]);

// Or use the default
server.use_default_adapter();

Sending Notifications

// Raw bytes
server.notify(&[0x01, 0x02, 0x03]).await?;

// Strings
server.notify_str("Hello World").await?;

// Formatted strings
server.notify_fmt(format_args!("Temp: {:.1}C", 23.5)).await?;

// Numbers (little-endian)
server.notify_u8(255).await?;
server.notify_i16(-1000).await?;
server.notify_u32(123456).await?;
server.notify_f32(3.14159).await?;
server.notify_f64(2.718281828).await?;

// Boolean
server.notify_bool(true).await?;  // Sends 0x01

// JSON (requires "json" feature)
#[derive(serde::Serialize)]
struct SensorData {
    temperature: f32,
    humidity: u8,
}

server.notify_json(&SensorData {
    temperature: 23.5,
    humidity: 65,
}).await?;
// Sends: {"temperature":23.5,"humidity":65}

Server Lifecycle

// Start the server
server.start().await?;

// Check if running
if server.is_running() {
    // Send data...
}

// Stop explicitly (also called on drop)
server.stop()?;

Accessors

let name = server.device_name();           // "MyDevice"
let svc_uuid = server.service_uuid();      // Service UUID
let char_uuid = server.characteristic_uuid(); // Characteristic UUID
let running = server.is_running();         // true/false

Complete Example

use std::time::Duration;
use tokio::time::sleep;
use ble_windows_server::{list_adapters, WindowsBLEGattServer, Uuid};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Discover adapters
    let adapters = list_adapters().await?;
    println!("Found {} adapter(s)", adapters.len());

    // Create and configure server
    let uuid = Uuid::parse_str("12345678-1234-5678-1234-567812345678")?;
    let mut server = WindowsBLEGattServer::new("SensorHub".into(), uuid);

    // Start advertising
    server.start().await?;
    println!("BLE server started!");
    println!("Service UUID: {}", server.service_uuid());

    // Broadcast loop
    let mut counter = 0u32;
    loop {
        counter += 1;
        server.notify_fmt(format_args!("Count: {}", counter)).await?;
        sleep(Duration::from_secs(1)).await;
    }
}

Testing with nRF Connect

  1. Install nRF Connect on your phone
  2. Run your BLE server application
  3. Open nRF Connect and scan for devices
  4. Connect to your device
  5. Navigate to the service UUID
  6. Enable notifications on the characteristic
  7. Watch the data stream in!

Troubleshooting

"No Bluetooth adapters found"

  • Ensure Bluetooth is enabled in Windows Settings
  • Check that your adapter supports BLE peripheral role
  • Try running as Administrator

Adapter doesn't support peripheral role

Not all Bluetooth adapters support acting as a BLE peripheral. Check adapter capabilities:

let adapters = list_adapters().await?;
for adapter in &adapters {
    println!("Peripheral supported: {}", adapter.peripheral_supported);
}

Device not visible in scans

  • Windows may use the computer's Bluetooth name instead of the provided device name
  • Ensure SetIsDiscoverable(true) is set (default in this library)
  • Try restarting Bluetooth in Windows Settings

License

MIT License - see LICENSE for details.

Contributing

Contributions welcome! Please open an issue or PR on GitHub.