2021年1月25日月曜日

Windows10でEddyStone Beaconを受信する その1

EddyStone Beaconを受信しているところ
 Bleutooth Low Energy Beacon(以下BtLE Beacon)は,Bluetoothのアドバタイズ(存在通知)の仕組みを使った,簡易な情報通知手段。Windows10で受信プログラムを作ってみた。
 Bleutoothデバイスは,存在を通知するためにアドバタイズという仕組みを使って,自分のIDなどを通知する。通常は,これを受信して,存在を確認(たとえば,Bluetoothアドレスを取得)などして,その後ペアリング,通信という段取りなのだが,Beaconは,アドバタイズのパケットに簡易な情報を載せ,単に送信するだけだ。受信側で,アドバタイズパケットを受信したとき,Beaconであることを確認して情報を受け取る。もちろん,受け取る,受け取らない,情報を使う,使わないは,受信側の自由である。面倒なペアリングが不要で,Beaconデバイスの近所にあるスマートフォンやPCなどにデータを送信できるというメリットがある。ただし,本来は,通信の前段階である存在通知のためのパケットなので,載せることができる情報はごくわずかである。
 Beaconには,Applieのやつと,Googleの作ったEddyStoneなどがある。こういうのは,共通仕様として認識されないと,どんなにいいものを作っても無駄である。ほかのBeaconもあるのかもしれないが,残念ながら知らない。
 筆者が手に入れた,BBC Micro:bitsには,このEddyStone Beaconを送信する機能がある。これを使って,ちょっしたものを作ってみたのだが,残念ながら,Windowsには,まともにEddyStoneを受信するプログラムがなさそうだ。ということで自分で作ることにした。とりあえず作ったのは,例によってコマンドラインプログラム。開発中ということで,ここでは,Windows10でBluetoothのアドバタイズを受信するやり方を解説しておくことにする。
 まずは,アルゴリズムだけ解説して,具体的な作り方に関しては別途解説するが、分かっている人向けにいうと、プロジェクトにnugetで“Microsoft.Windows.SDK.contract”を参照しておく。そうしないと「Windows.Devices.Bluetooth.Advertisement」が使えない。あとは、普通のコンソールプロジェクトで問題ない。
 そのやり方は、別記事「Who's next?: Win32デスクトップアプリでWinRT APIを呼び出す(Visual Studio 2019) 」を参照してほしい。

BtLEアドバタイズの受信

 とりあえずは、動作するプログラムがList01である。
List01
using System;
using Windows.Devices.Bluetooth.Advertisement;
namespace MicroBitAdv {
	class Program {
    	static void Main(string[] args) {
        	BluetoothLEAdvertisementWatcher MyWatcher;
        	MyWatcher = new BluetoothLEAdvertisementWatcher();
        	MyWatcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(100);
        	MyWatcher.ScanningMode = BluetoothLEScanningMode.Passive;
        	MyWatcher.AdvertisementFilter = new BluetoothLEAdvertisementFilter() {
        		Advertisement = new BluetoothLEAdvertisement { ServiceUuids = { new Guid("0000FEAA-0000-1000-8000-00805F9B34FB") } } };
        	MyWatcher.Received += WatcherReceived;
        	MyWatcher.Start();
        	Console.ReadKey();
        	MyWatcher.Stop();
        }
        private static void WatcherReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args) {
        	ulong MyBtAddress = 0x000000000000; //<- Your MicroBit Bleutooth Address
            if (args.BluetoothAddress != MyBtAddress) { return; }
            foreach (var x in args.Advertisement.DataSections) {
            	var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(x.Data);
                var r = new Byte[x.Data.Length];
                var MyInstaceID = new Byte[8];
                var MyNameSpace = new Byte[10];
                if (x.DataType == 22) {
                	dataReader.ReadBytes(r);
                    for (var i = 0; i < 10; i++) { MyNameSpace[i] = r[i + 4]; }
                    Console.WriteLine($"MicroBit NameSpace:{BitConverter.ToInt32(MyNameSpace, 6):X8}");
                    for (var i = 0; i < 6; i++) { MyInstaceID[i] = r[14 + i]; }
                    Array.Reverse(MyInstaceID);
                    Console.WriteLine($"     InstanceID:{BitConverter.ToUInt64(MyInstaceID, 0) / 0x10000:X8}\n");
                }
            }
        }
    }
}
 簡単にいうと「BluetoothLEAdvertisementWatcher()」オブジェクトを作り,そのRecivedイベントを定義してやる。Windowsがアドバタイズパケットを受信するたびにイベントが発生してイベントハンドラが呼び出されるので,そこで処理すればいいわけだ。

 次回は、プログラムの動作を解説する。

2021年2月5日 追記
WinRT APIの呼び出し方を解説した記事へのリンクを追加。

0 件のコメント:

コメントを投稿