UWPでBLEデバイスとペアリングして値を取得する

(2017-05-13)

ManifestからBluetoothを許可しておく。

BLEデバイスを見つける

CreateWatcherにBluetooth LEプロトコルのAEP(Association EndPoint)サービスクラスIDと requestPropaertiesで必要なデバイス情報を渡している。 最後のAssociationEndpointSystem.Devices.Aep.ProtocolIdのAepと対応している

using Windows.Devices.Enumeration;

string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };

deviceWatcher = DeviceInformation.CreateWatcher(
                        "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")",
                        requestedProperties,
                        DeviceInformationKind.AssociationEndpoint);

deviceWatcher.Start();
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Removed += DeviceWatcher_Removed;
deviceWatcher.Updated += DeviceWatcher_Updated;
/*
deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
deviceWatcher.Stopped += DeviceWatcher_Stopped;
*/

Dictionary<string, DeviceInformation> deviceInfos = new Dictionary<string, DeviceInformation>();

private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
{

    if (sender == deviceWatcher)
    {
        if (deviceInfo.Name != string.Empty)
        {
            deviceInfos.Add(deviceInfo.Id, deviceInfo);   
        }
    }
}

private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
    if (sender == deviceWatcher)
    {
        deviceInfos[deviceInfoUpdate.id].Update(deviceInfoUpdate);
    }
}

 private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
    if (sender == deviceWatcher)
    {
        deviceInfos.Remove(deviceInfoUpdate.id);
    }
}

ペアリング

DevicePairingResult result = await deviceInfo.Pairing.PairAsync();
if (result.Status == DevicePairingResultStatus.Paired || result.Status == DevicePairingResultStatus.AlreadyPaired){
    // success
} else{
    // fail
}

こんなウィンドウが出てくる。

ペアリング確認

OSの設定からペアリングすることもできる。

serviceのcharacteristicを取得する

ペアリングしたらこんな感じで値を取得できる。 GetGattServicesForUuidAsyc などはCreaters Update(15063)から追加されたAPI。 Anniversary Edition(14393)まで対応する場合GetGattServiceを使う。いずれにしても最小バージョンをそれ以上にしておく。 deviceの値が取得できない場合はBluetoothが許可されているか確認する。 あと、characteristicが一つも取れない場合、他のアプリケーションからアクセスしていないか注意。 ドキュメントにも書いてあるけど、一つのサービスには一つのアプリケーションしかアクセスできない。 そもそも接続できない場合、一旦お互いの接続設定を消して再ペアリングするとよくなることがある。 ペアリングもできないようだったらBluetoothをオフにしてみるとか。

var device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);

var services = await device.GetGattServicesForUuidAsync(serviceUUID);

var characteristics = await services.Services[0].GetCharacteristicsForUuidAsync(characteristicUUID);

characteristics.Characteristics[0].ValueChanged += characteristicChanged;

await characteristics.Characteristics[0].WriteClientCharacteristicConfigurationDescriptorAsync(
    GattClientCharacteristicConfigurationDescriptorValue.Notify
);

void characteristicChanged(
    GattCharacteristic sender,
    GattValueChangedEventArgs eventArgs
){
    byte[] data = new byte[eventArgs.CharacteristicValue.Length];
    Streams.DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(data);
    var str = System.Text.Encoding.ASCII.GetString(data)
}

Unity/UWPでBLEを扱うプラグインを作る - sambaiz-net