Windows のコンソールアプリで RFCOMM を利用する

Arduino で Bluetooth シリアル変換モジュール(HC-05)を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6819

では、Windows ストアアプリを使って Bluetooth の RFCOMM を利用したわけですが、これってストアアプリとか Windows Phone からしか出来ないのか?と思っていたのですが、コンソールからもできました。ということは、Windows フォームや WPF からもできます。

デスクトップからWinRTを参照させる

デスクトップアプリからWinRT APIを使用する – 酢ろぐ!
http://blog.ch3cooh.jp/entry/20121204/1354596483
デスクトップ アプリからのWinRT API利用 | ++C++; // 未確認飛行 C ブログ
https://ufcpp.wordpress.com/2012/09/18/%e3%83%87%e3%82%b9%e3%82%af%e3%83%88%e3%83%83%e3%83%97-%e3%82%a2%e3%83%97%e3%83%aa%e3%81%8b%e3%82%89%e3%81%aewinrt-api%e5%88%a9%e7%94%a8/

そうそう、デスクトップアプリから WinRT を参照させれば RfcommDeviceService クラスが使えるかもしれない。ということで上記を参考にして設定をします。

TargetPlatformVersion を 8.1 にして挿入します。8.0 だとデバイス関係がないので「8.1」で。

  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{9B7AD65D-3475-4D63-B5AC-6AB73477AC30}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>BluetoothConsole</RootNamespace>
    <AssemblyName>BluetoothConsole</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <TargetPlatformVersion>8.1</TargetPlatformVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>

Windows.winmd を追加します。

System.Runtime.WindowsRuntime.dll を参照設定します。
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll

Windows ストアアプリ版のコードを書き換えて、コンソールアプリで呼び出せるようにします。ストアアプリではマニフェストの追加が必要ですが、デスクトップアプリの場合は必要ありません。アクセス権が自由なので、これだと作りやすいですよね(配布はしづらいですが)。

class Program
{
	static void Main(string[] args)
	{
		new Program().mainAsync().Wait();
	}

	Guid serviceGuid = Guid.Parse("00001101-0000-1000-8000-00805f9b34fb");
	RfcommDeviceService rfcommService;
	StreamSocket socket;
	DataWriter writer;
	DataReader reader;

	async Task mainAsync()
	{
		/// 接続
		string selector = RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(serviceGuid));
		DeviceInformationCollection collection = await DeviceInformation.FindAllAsync(selector);
		if (collection.Count > 0)
		{
			try
			{
				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);
				Console.WriteLine("{0} 接続しました", rfcommService.ConnectionHostName );
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
		}
		else
		{
			Console.WriteLine("デバイスが見つかりませんでした");
			return;
		}
		// 試しに最初のキーを送る
		SendCommand("start");
		while (true)
		{
			// コマンド待ち受けfs
			string text = Console.ReadLine();
			if (text == "quit" || text == "end") break;
			SendCommand(text);
		}
		/// 切断する
		writer.Dispose();
		reader.Dispose();
	}

	async void SendCommand(string text)
	{
		Console.WriteLine("W:" + text);
		// 8文字にして送る
		if (text.Length < 8)
		{
			text = text.PadRight(8, '*');
		}
		else
		{
			text = text.Substring(0, 8);
		}
		writer.WriteString(text);
		await writer.StoreAsync();
		// そのまま受信待ち
		var res = await reader.LoadAsync(8);
		var text2 = reader.ReadString(8);
		Console.WriteLine("R:" + text2 );
	}
}

お次は、iPhone から…と思っていたのですが、調べていくと iPhone からは RFCOMM が使えないことが判明。正確には MFi というのを Apple から取得して作成すれば使えるようになるそうなのですが、個人アプリレベルでは無理話。そうなると Bluetooth LE を使っての接続が必要になるのです。
Arudino に BLE のシールドも無くはないのですが結構高い。2,3台作るとなると結構な値段になるし、ちょっと手が出しにくい(まあ、1個だけは RedBearLab に注文して買うんですけど)。このあたりは、コントローラー自体が iPhone である必要もないので、RFCOMM をそのまま使うか、WiFi でさっくり作ってテストするかって感じですかね。ちょっと思案中。
Xamarin.iOS で BLE はやっておきたいので、これはまた別途。iPhone からノートPCのUSB付けた Bluetooth 4.0 で実験すればよいので。

カテゴリー: Arduino, WinRT パーマリンク