Bluetooth Low Energy (BLE)デバイスからのデータ受信(C#)

プログラミング
公開: 2022年06月02日

BLEデバイスの検出

BLE デバイスからはアドバタイズパケットがブロードキャストされているので、この受信を行う。 アドバタイズパケットの Local Name にデバイス名が設定されているので、機器の識別に使用できる。 この例では「MF500B_0000377」という名前の機器を使用する。

static void Main(string[] args)
{
    var watcher = new BluetoothLEAdvertisementWatcher();
    watcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromSeconds(3);
    watcher.ScanningMode = BluetoothLEScanningMode.Passive;
    watcher.Received += Watcher_Received;
    watcher.Start();
    Console.WriteLine("watching...");
    Console.ReadKey();
}

private static void Watcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
    var localName = args.Advertisement.LocalName.ToString();
    if (string.IsNullOrEmpty(localName))
    {
        return;
    }

    Console.WriteLine("NAME:" + localName);
    if (localName == MF500B_0000377)
    {
        sender.Stop();
        Connect(args);
    }
}

Service への接続と Characteristic(キャラクタリスティック)の取得

BLEデバイスの下に複数のサービス、各サービスの下に複数のキャラクタリスティック(情報)がぶら下がっているイメージ。
サービス、キャラクタリスティック共に固有の UUID(GUID)が決まっており、これは製品の仕様書に記載されている。(製品の個体毎に異なる値にはならない)
以下の例では「Client Characteristic Configuration を Indication に設定」を行っているが、これは MF500B の製品仕様のためで、製品により必要な設定は異なる。

private static async void Connect(BluetoothLEAdvertisementReceivedEventArgs args)
{
    // Service に接続(uuid は固定)
    var device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
    var service = (await device.GetGattServicesForUuidAsync(ServiceGuid)).Services.First();
    Console.WriteLine($"service.Uuid: {service.Uuid}");

    // Characteristic を取得(uuid は固定)
    var characteristic = (await service.GetCharacteristicsForUuidAsync(CharacteristicGuid)).Characteristics.First();
    Console.WriteLine($"characteristic.Uuid: {characteristic.Uuid}");

    // イベントハンドラの設定
    characteristic.ValueChanged += Characteristic_ValueChanged;

    // Client Characteristic Configuration を Indication に設定
    var communicationStatus = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
        GattClientCharacteristicConfigurationDescriptorValue.Indicate);
    Console.WriteLine($"communicationStatus: {communicationStatus}");

    // Client Characteristic Configuration を 確認
    var configuration = await characteristic.ReadClientCharacteristicConfigurationDescriptorAsync();
    Console.WriteLine($"configuration.Status: {configuration.Status}");
    Console.WriteLine($"ClientCharacteristicConfiguration: {configuration.ClientCharacteristicConfigurationDescriptor}");
}

値の取り出し

取得データはバイナリデータなので製品仕様に従って処理する。 この例では先頭2バイトが符号付き整数型(Int16)の観測値(温度値 × 100)なので、Int16 に変換した後、100で割っている。

private static void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
    var value = args.CharacteristicValue;
    var bytes = new byte[value.Length];
    DataReader.FromBuffer(value).ReadBytes(bytes);
    var intValue = BitConverter.ToInt16(bytes[0..2]);
    var decimalValue = ((decimal)intValue) / 100;
    Console.WriteLine($"T:0x{BitConverter.ToString(bytes[0..2]).Replace("-", "")} {decimalValue:0.0}");
}

参考

BLEアドバタイズパケットの中身を調べてみた
C# コンソールアプリでBluetooth通信を行う
C# .NET Frameworkを使ったBluetoothLEデバイスの検出
C#/WinRT Bluetooth v4(BLE)機器と通信する(C#で実装メモ)
【サルでもわかるBLE入門】(2) アドバタイズとGATT通信