private static void WatcherReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args) { ulong MyBtAddress = 0xF5E5E7BD08AE; // Your MicroBit Bleutooth Address if (args.BluetoothAddress != MyBtAddress) { return; } BluetoothLEAdvertisementDataSection x = args.Advertisement.GetSectionsByType(22)[0]; 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]; 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"); }
定義は、MSDNのここ。重要なのは、2つめの引数argだ。このargさえ得られれば、アドバタイズパケットの処理は終わったも同然といえる。BluetoothLEAdvertisementReceivedEventArgs Classは、前記定義ページにあるように、複数のプロパティを持っており、たとえば、パケットの送信元のBluetoothアドレスなら、BluetoothAddressプロパティを読み出せばよい。また、信号強度を調べるならRawSignalStrengthInDBmプロパティ、イベントの受信日時ならTimestampプロパティだ。重要なのは、Advertisementプロパティで、これは、 BluetoothLEAdvertisement Classを返す。ここには、アドバタイズパケットそのものが入っているほか、そこから解釈したデータがプロパティとして含まれている。
イベントハンドラが呼び出されたらmicro:bit v2のものかどうかをBtアドレスで判定して、違うなら戻る。フィルターをかけているので、EddyStoneのアドバタイズパケットのときだけ、イベントハンドラーが呼び出される。不要ならBtアドレスによる判定はなくてもよい。
ulong MyBtAddress = 0x000000000000; //Your Microbit Bluetooth Address if (args.BluetoothAddress != MyBtAddress) { return; }
アドバタイズパケットのデータは、args.Advertisement.DataSectionsの中にある(複数形に注意)。これがパケットデータそのもので、複数のDataSetion(こっちは単数形)から構成されている(DataSectionsは、DataSectionのList)。実データはパケット内で1バイトのDataSize、DataTypeとペイロード(複数バイト)から構成されているが、DataSectionは、DataTypeとDataになっていて、DataのLengthが実データの先頭にあるDataSizeになる。Dataは、バイトの配列で、これを必要に応じて解釈する必要がある。
EddyStoneの場合には、DataTypeが22(0x16)のデータが含まれる。この中にmicro:bitの「Buletooth UUIDアドバタイズ」に設定する「Name Space」と「Instance ID」が入っている。
これを取り出すのが、.GetSectionsByType(22)[0]である(4行目)。GetSectionsByTypeメソッドは、引数で指定されたDataTypeを取り出す。ただし、複数のDataSectionが対応する可能性があるのでListとしてかえされるが、EditStoneでは1つだけなので「[0]」として先頭のものだけを取り出している。最初のバージョンでは、これを使わず、foreachですべてのDataSectionsをスキャンして、DataTypeが22のものだけをifで見付けて処理していた。しかし、.GetSectionsByTypeメソッドを使えば、1行で目的のDataSectionを取り出せる。
バイト列を読み込むには“ Windows.Storage.Streams.DataReader.FromBuffer”を使う(5行目)。あらかじめバイト配列(var r = new Byte[x.Data.Length];)を用意しておき、「dataReader.ReadBytes(r);」で読み込む(9行目)。
EddyStone(micro:bitのBluetoothアドバタイズ)のNameSpaceは、読み込んだバイト列の4バイト目から10バイト分(10行目)、InstanceIDは、14バイト目からの5バイトになる(12行目)。ただしInstanceIDは逆順で入っているので、ひっくり返す必要がある(13行目)。
0 件のコメント:
コメントを投稿