Windows 8.1ストアアプリでBluetooth 2.0接続周辺デバイスと通信する

Windows 8.1で強化されたWinRT APIによる周辺デバイス連携に関するポスト、第一弾です。

Bluetooth 2.0でPCにリモート接続され、仮想COMポートにマップされてシリアル通信する周辺デバイスは沢山あります。このポストでは、WinRT APIを使って、このような周辺デバイスと通信する方法を解説します。

Bluetooth 2.0デバイスと通信するには、手動でWindows 8.1 PCと周辺デバイスのペアリングが必要です。Windows 8.1では、設定チャーム→PC設定の変更→PCとデバイス→Bluetoothで、つなぎたいデバイスとペアリングができます。

プログラムの流れは、以下の通りです。

  1. つなぎたいデバイスに関するRfcommDeviceServiceを検索
  2. 見つけたRfcommDeviceServiceを基にStreamSocketを作成
  3. 通信用のDataWriterとDataReaderを作成
  4. DataWriter、DataReaderでデータを送受信

具体的なコードを以下に説明していきます。以下の名前空間に対するusing宣言をしておいてください。

using Windows.Devices.Enumeration;
using Windows.Devices.Bluetooth.Rfcomm;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

1. つなぎたいデバイスに関するRfcommDeviceServiceを検索

通信するデバイスの名前は、”NXT”とします。

    RfcommDeviceService deviceService;
    var servicesInfos = await DeviceInformation.FindAllAsync(
        RfcommDeviceSrevice.GetDeviceSelector(RfcommServiceId.SerialPort));
    foreach (var serviceInfo in serviceInfos)
    {
        if (serviceInfo.Name == "NXT")
        {
            deviceService = await RfcommDeviceService.FromIdAsync(serviceInfo.Id);
            break;
        }
    }

これで、Bluetooth 2.0で接続するためのDeviceServiceを取得できました。

2.見つけたRfcommDeviceServiceを基にStreamSocketを作成

    var btSocket = new StreamSocket();
    await btSocket.ConnectAsync(
        deviceService.ConnectionHostName,
        deviceService.ConnectionServiceName,
        SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);

これで、通信の基となるStreamSocketの準備が出来ました。

3.通信用のDataWriter、DataReaderを作成

次に、データ送受信様の、DataWriter、DataReaderを作成します。

    var dataWriter = new DataWriter(btSocket.OutputStream);
    var dataReader = new DataReader(btSocket.InputStream);

後は、データをデバイスに送信する場合にはdataWriterにデータを書き込み、データをデバイスから受信する場合には、dataReaderからデータを読み込みます。
周辺デバイスとの通信は、StreamSocketのOutputStream、InputStreamからそれぞれ、DataWriter、DataReaderを作る、というのがパターンです。

4.DataWriter、DataReaderでデータを送受信

データの送信は、

    var data = new byte[packetSize];
    // dataのセット
    …
    dataWriter.WriteBytes[data];
    var sendResult = await dataWriter.StoreAsync();

で行います。データをDataWriterに書き込んで、StoreAsync()メソッドでデバイスに送り出すというステップを踏みます。例ではWriteBytesメソッドを使用していますが、送信するデータの型に応じたWriteXXXメソッドが多数用意されています。

データの受信は、

    var data = new byte[packetSize];
    var receiveStored = await dataReader.LoadAsync(packetSize);
    dataReader.ReadBytes(data);

と、読み込むデータのサイズを指定してLoadAsync()メソッドをコールしてから、実際にReadBytesメソッドで読み込むというステップを踏みます。WriteXXXと同様、ReadXXXメソッドが多数用意されています。

データ送受信の基本は以上の通りです。送受信するデータ長やデータの中身はそれぞれのデバイスに合わせて試してみてください。例えば、Lego Mindstorms NXTの場合は、https://nxtnet.codeplex.com/ のコードが参考になります。

実際に動かすには、もう一つ設定の追加が必要です。Package.appxmanifestに以下の定義を追加しないとストアアプリからデータを送受信することはできないので注意してください。

Package.appxmanifestを”コードの表示”で開き、最後の方のCapabilitiesタグに以下の宣言(太字の部分)を追加します。

    <Capability Name="internetClient"/>
      <m2:DeviceCapability Name="bluetooth.rfcomm">
        <m2:Device Id="any">
           <m2:Function Type="name:serialPort" />
        </m2:Device>
      </m2:DeviceCapability>
    </m2:DeviceCapability>
  </Capabilities>
</Package>

周辺デバイスの接続は、アプリ実行時、ユーザーの承認が必要になります。この辺り、カメラやマイク、位置情報と同じ扱いなので、Bluetooth SPPを使うよという定義が必要になります。もしうまくつながらない場合は、FromIdAsync()メソッドに渡す、deviceServiceのIdの値に格納されている値の最初に出てくるUUIDで、serviceId:の値を修正すれば動くはずです。

Windows 7以前から.NET FrameworkやWin32 APIで、仮想COMポートを使った周辺デバイス連携アプリを開発されてきた方も多いと思います。WinRT APIでアプリを作れば、ARM版のWindows 8.1でも動作可能なアプリを開発できるだけでなく、加速度センサーやジャイロセンサーなど、Windows 8.1の様々な機能と組み合わせたタブレット向けアプリなど、面白そうなアプリを開発可能です。是非、開発にトライしてWindows ストアから世界に向けて発信してくださいね。