Bluetoothでデバイスと通信するには

Rfcomm

WindowsRuntimeではBluetoothの通信プロファイルの一つである、Rfcommをサポートしています。

Rfcommとは、通信上はBluetoothで接続されているデバイスと通信を行いますが、見かけ上はただのシリアル通信としてプログラミングできるプロファイルです。

 

シリアル通信とはCOMポートを使って有線で通信を行う方法ですが、RfcommではBluetoothで繋がったデバイスに仮想的なCOMポートを提供し、そのCOMポートにむかってシリアル通信をするだけで見かけ上のシリアル通信を無線で実現することができます。

73

 

RBT-001

今回は接続するデバイスとして、ArduinoとRBT-001というBluetoothモジュールを用いて通信を行います。

回路図はこんな感じです。

ArduinoのRXソケットをRBT-001のTXソケットに、TXソケットをRXソケットにつなぎます。

74

73

 

 

あらかじめArduino側にプログラムを書き込んでおきます。

シリアル通信でデータが流れてくるとそのままデータをシリアル通信で流し、LEDを1秒光らせる単純なものです。

int ledPin=13;
void setup(){
  pinMode(ledPin,OUTPUT);
  Serial.begin(9600);
}

void loop(){
  int data=Serial.read();
  if(data!=-1){
    
    Serial.write(data);
    digitalWrite(ledPin,HIGH);
    delay(1000);
    digitalWrite(ledPin,LOW);
  }
}

ここまでできると、RBT-001からBluetoothの電波が飛ぶのでWindows側から認識できます。

ペアリングしておきましょう。PINコードはデフォルトで「0000」です。

 

SeviceGUID

RBT-001でRfcommを使うとき、サービスを一意に特定するためにGUID値を利用します。

これはあらかじめRBT-001が提供するGUID値を使います。

 

コントロールパネルからEasyBTのプロパティを見ます。

ハードウエアのタブからBluetoothリンク経由の標準シリアルを選択し、「プロパティ」を押します。

 

75

 

詳細タブを開き、BluetoothサービスGUIDを見るとGUIDを取得できます。

このGUIDを使用するのでコピ-しておきます。

 

マニフェストファイルに書き込む

Rfcommで通信するにはマニフェストファイルに書き込まなければいけません。

Package.manifestファイルを右クリックして「コードを表示」をおしましょう。

37

 

Capabilityタグ内に以下のタグを追加します。

m2:FunctionタグのType属性値は先ほど取得したGUIDに置き換えてください

<m2:DeviceCapability Name="bluetooth.rfcomm">
  <m2:Device Id="any">
    <m2:Function Type="serviceId:00001101-0000-1000-8000-00805f9b34fb" />
  </m2:Device>
</m2:DeviceCapability>

 

 

RfcommDeviceService

WindowsRuntimeでRfcommを使うにはRfcommDeviceServiceAPIを使います。

まずBluetoothデバイスを特定しましょう。

先ほどのGUID値を使うので変数として宣言しておきます。

GUID値を先ほどコピーしたものと置き換えてください。

Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");

 

RfcommDeviceServiceクラスのGetDeviceSelectorメソッドを使ってセレクターを作ります。

セレクターを使ってDeviceInformationのFromAsyncメソッドでデバイスを特定します。

あとはDeviceInformationのIDからRfcommDeviceServiceクラスを初期化します。

RfcommDeviceService rfcommService;
string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
if (collection.Count > 0)
{
    DeviceInformation info = collection.First();
    rfcommService = await RfcommDeviceService.FromIdAsync(info.Id);


}

 

次に作成したRfcommDeviceServiceクラスのConnectHostNameとConnectServiceNameを使ってStreamSocketを作ります。

StreamSocketができたらOutputStreamとInputStreamを使ってDataWriterとDataReaderを作ります。

 

StreamSocket socket;
DataWriter writer;
DataReader reader;
socket = new StreamSocket();
await socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName);

writer = new DataWriter(socket.OutputStream);
reader = new DataReader(socket.InputStream);

 

データを送信する

先ほど作ったDataWriterを使用してbyte値を書き込みます。

これでBluetoothを経由してArduinoのシリアルポートにデータが送られます。

byte data = 3;
writer.WriteByte(data);
await writer.StoreAsync();

 

データを受信する

先ほど作ったDataReaderを使用してbyte値を読み込みます。

ArduinoからBluetooth経由で仮想COMポートに送られてくるデータを取得することができます。

uint byteCount = 1;
await reader.LoadAsync(byteCount);
byte b = reader.ReadByte();

MessageDialog dialog = new MessageDialog(b.ToString());
await dialog.ShowAsync();

 

サンプルコード

public sealed partial class RfcommControl : UserControl
{
    Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");
    RfcommDeviceService rfcommService;
    StreamSocket socket;
    DataWriter writer;
    DataReader reader;

    public RfcommControl()
    {
        this.InitializeComponent();
    }

    private async void btn_findDevice_Click(object sender, RoutedEventArgs e)
    {
        string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
        DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
        if (collection.Count > 0)
        {
            DeviceInformation info = collection.First();
            rfcommService = await RfcommDeviceService.FromIdAsync(info.Id);

            socket = new StreamSocket();
            await socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName);

            writer = new DataWriter(socket.OutputStream);
            reader = new DataReader(socket.InputStream);
        }
        else
        {
            MessageDialog dialog = new MessageDialog("デバイスが見つかりませんでした");
            await dialog.ShowAsync();
        }
    }

    private async void btn_sendMessage_Click(object sender, RoutedEventArgs e)
    {
        
        byte data = 3;
        writer.WriteByte(data);
        await writer.StoreAsync();

    }

    private async void btn_receiveMessage_Click(object sender, RoutedEventArgs e)
    {

        uint byteCount = 1;
        await reader.LoadAsync(byteCount);
        byte b = reader.ReadByte();
        MessageDialog dialog = new MessageDialog(b.ToString());
        await dialog.ShowAsync();

    }

    private void btn_close_Click(object sender, RoutedEventArgs e)
    {
        writer.Dispose();
        reader.Dispose();
    }
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.