Blue-Falcon

Kotlin Multiplatform BLE library for iOS, Android, macos, windows and javascript

View the Project on GitHub Reedyuk/blue-falcon

Windows 10 Bluetooth LE Support

This document provides detailed information about the Windows 10 Bluetooth LE implementation for Blue Falcon.

Overview

The Windows implementation provides full Bluetooth Low Energy support for Windows 10 desktop applications through JNI (Java Native Interface) and Windows Runtime (WinRT) APIs. This implementation does NOT rely on any third-party libraries and uses only the built-in Windows Bluetooth APIs.

Architecture

The Windows implementation consists of three layers:

1. Kotlin/JVM Layer (windowsMain/kotlin)

2. JNI Bridge Layer (windowsMain/cpp/jni_bridge.cpp)

3. Native Windows Layer (windowsMain/cpp/BluetoothLEManager.cpp/h)

Requirements

Development Requirements

Runtime Requirements

Building the Native Library

Step 1: Set up your environment

  1. Install Visual Studio 2019 or later with C++ development tools
  2. Install Windows 10 SDK from: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/
  3. Ensure JAVA_HOME environment variable is set correctly

Step 2: Build with CMake

cd library\src\windowsMain\cpp
mkdir build
cd build
cmake .. -G "Visual Studio 16 2019" -A x64
cmake --build . --config Release

The output bluefalcon-windows.dll will be in the Release directory.

Step 3: Install the native library

Copy the DLL to one of the following locations:

Usage

Basic Usage

import dev.bluefalcon.*

// Create BlueFalcon instance
val blueFalcon = BlueFalcon(
    log = PrintLnLogger,  // or your custom logger
    context = ApplicationContext(),  // Empty context for Windows
    autoDiscoverAllServicesAndCharacteristics = true
)

// Implement delegate to receive callbacks
blueFalcon.delegates.add(object : BlueFalconDelegate {
    override fun didDiscoverDevice(
        bluetoothPeripheral: BluetoothPeripheral,
        advertisementData: Map<AdvertisementDataRetrievalKeys, Any>
    ) {
        println("Found device: ${bluetoothPeripheral.name} - ${bluetoothPeripheral.uuid}")
    }
    
    override fun didConnect(bluetoothPeripheral: BluetoothPeripheral) {
        println("Connected to ${bluetoothPeripheral.name}")
    }
    
    override fun didDiscoverServices(bluetoothPeripheral: BluetoothPeripheral) {
        println("Discovered ${bluetoothPeripheral.services.size} services")
    }
    
    override fun didCharacteristcValueChanged(
        bluetoothPeripheral: BluetoothPeripheral,
        bluetoothCharacteristic: BluetoothCharacteristic
    ) {
        println("Characteristic changed: ${bluetoothCharacteristic.uuid}")
        println("Value: ${bluetoothCharacteristic.value?.contentToString()}")
    }
    
    // Implement other delegate methods...
})

// Start scanning
blueFalcon.scan()

// Stop scanning
blueFalcon.stopScanning()

// Connect to a device
blueFalcon.connect(device, autoConnect = false)

// Read a characteristic
blueFalcon.readCharacteristic(device, characteristic)

// Write to a characteristic
blueFalcon.writeCharacteristic(device, characteristic, data)

// Enable notifications
blueFalcon.notifyCharacteristic(device, characteristic, true)

Pairing with the core Windows engine

The legacy dev.bluefalcon.BlueFalcon API does not support pairing. Use the core facade with WindowsEngine and a peripheral discovered by that engine:

import dev.bluefalcon.core.BlueFalcon
import dev.bluefalcon.engine.windows.WindowsEngine
import dev.bluefalcon.plugins.bonding.BondingPlugin
import kotlinx.coroutines.flow.first

suspend fun pairWithDiscoveredDevice() {
    val engine = WindowsEngine()
    val blueFalcon = BlueFalcon(engine)
    val bonding = BondingPlugin.create()
    blueFalcon.plugins.install(bonding)
    bonding.bind(blueFalcon)

    blueFalcon.scan()
    val device = engine.peripherals.first { it.isNotEmpty() }.first()
    blueFalcon.connect(device)

    val result = bonding.requestBond(device)
    println("Pairing result: $result")
}

Windows pairing uses custom pairing with encryption protection. Confirmation-only, displayed-PIN, and PIN-match requests show a Windows consent prompt; PIN-entry requests are not currently supported.

Filtering Devices

// Scan for devices with specific service UUID
val heartRateServiceUuid = kotlin.uuid.Uuid.parse("0000180d-0000-1000-8000-00805f9b34fb")
val filters = listOf(
    ServiceFilter(serviceUuids = listOf(heartRateServiceUuid))
)
blueFalcon.scan(filters)

API Compatibility

The Windows implementation supports all standard Blue Falcon APIs:

Scanning

Connection Management

Service & Characteristic Discovery

GATT Operations

Descriptor Operations

MTU Management

Windows-Specific Details

Adapter Enumeration and Selection

Device Identifiers

MTU Negotiation

Connection Priority

Permissions

Windows 10 version 1803+ requires the following capabilities in your application manifest:

Thread Safety

Limitations

  1. Descriptor Operations: Full descriptor read/write support is partially implemented
  2. Background Operation: Continuous background scanning may be limited by Windows power management
  3. Pairing: Pairing uses the Windows system pairing flow and requests at least encryption-level protection. Windows may display a system confirmation prompt; the peripheral must support pairing.
  4. Multiple Adapters: Supports adapter enumeration and selection through adapters() and selectAdapter() on Windows.

Troubleshooting

“Cannot find bluefalcon-windows.dll”

“Bluetooth adapter not found”

“Access denied” or “Permission denied”

Build Errors

Implementation Notes

Asynchronous Operations

All Bluetooth operations are asynchronous, using Kotlin coroutines on the Kotlin side and WinRT async patterns on the native side. Callbacks are marshaled back to Java/Kotlin through JNI.

Memory Management

Error Handling

Contributing

When contributing to the Windows implementation:

  1. Follow the existing code style
  2. Test on multiple Windows 10 versions if possible
  3. Ensure thread safety in native code
  4. Document any Windows-specific behaviors
  5. Update this documentation with any changes

References