アルプスのセンサネットワークモジュールからモーションデータを取得するC# .NET Frameworkのコンソールアプリを作成します。なお、アルプスのセンサネットワークモジュールからのアドバタイズメントの受信については、「C# .NET Frameworkを使ったBluetoothLEデバイスの検出」を参照してください。
動作環境
- Windows 10 Professional
- Visual Studio 2019
センサネットワークモジュールの仕様説明
アルプスのセンサネットワークモジュールのアドレスは、「C# .NET Frameworkを使ったBluetoothLEデバイスの検出」で「44674167429270」ということがわかっています。モーションデータの取得するためのUUIDは、「Sensor Network Module 評価キット Application Note Command Guide」の6頁に次のように記述されています。
センサネットワークモジュールモーションデータ取得プログラムの作成
Windows10のBLE周りのAPIはUWPアプリ専用のため、.NET Frameworkからは、WinRTのAPI「Microsoft.Windows.SDK.Contracts」を経由してアクセスする必要があります。WinRTのAPI「Microsoft.Windows.SDK.Contracts」のインストール方法については、「C# .NET Frameworkを使ったBluetoothLEデバイスの検出」を参照してください。
C# .NET Frameworkのコンソールアプリで作成したセンサネットワークモジュールモーションデータ取得プログラムを次に示します。
- 23行目にはアルプスのセンサネットワークモジュールのアドレス、25-29行目にはアルプスのセンサネットワークモジュールのUUIDを設定します。
- アルプスのセンサネットワークモジュールが検出されると、62行目に制御が移ります。
- 78行目でCCCD への書き込みを行います。この設定によりNotifyでパソコンに通知(コールバック)されます。
- 83行目で、データが変化したときに実行されるコールバック関数「Changed_data」を登録します。
- 87-92行目で、アルプスのセンサネットワークモジュールの設定を「モーション(動き)検知 100ms間隔(モーション系センサのみ」とし、動きの計測を開始します。
- 103行目のコールバック関数「Changed_data」では、受信したモーションデータを16進表示します。
SensorAlps\SensorNetwork\Program.cs
using System; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading; using Windows.Devices.Bluetooth; using Windows.Devices.Bluetooth.Advertisement; using Windows.Devices.Bluetooth.GenericAttributeProfile; namespace SensorAlps { class Program { static void Main(string[] args) { SensorModule sensormodule = new SensorModule(); sensormodule.Start(); } } class SensorModule { // address const ulong SENSOR_ADR = 44674167429270; // Bluetooth®サービス static Guid UUID_TEMP_SERV = new Guid("47FE55D8-447F-43EF-9AD9-FE6325E17C47"); // 計測センサデータやモジュール内部ステータスをパソコンに通知 static Guid UUID_TEMP_DATA = new Guid("686A9A3B-4C2C-4231-B871-9CFE92CC6B1E"); // コマンド制御 static Guid UUID_TEMP_CONF = new Guid("B962BDD1-5A77-4797-93A1-EDE8D0FF74BD"); private BluetoothLEAdvertisementWatcher advWatcher; public void Start() { Console.WriteLine("Start"); this.advWatcher = new BluetoothLEAdvertisementWatcher(); this.advWatcher.ScanningMode = BluetoothLEScanningMode.Passive; this.advWatcher.Received += this.Watcher_Received; // スキャン開始 this.advWatcher.Start(); Thread.Sleep(60000); this.advWatcher.Stop(); Console.WriteLine("Stop"); } private void Watcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args) { this.CheckArgs(args); } public async void CheckArgs(BluetoothLEAdvertisementReceivedEventArgs args) { Console.WriteLine("Received"); if (args.BluetoothAddress == SENSOR_ADR) { // 検出 try { Console.WriteLine($"Service Find!"); // スキャンStop this.advWatcher.Stop(); BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress); var services = await device.GetGattServicesForUuidAsync(UUID_TEMP_SERV); var characteristics = await services.Services[0].GetCharacteristicsForUuidAsync(UUID_TEMP_DATA); var characteristics1 = await services.Services[0].GetCharacteristicsForUuidAsync(UUID_TEMP_CONF); if (characteristics.Status == GattCommunicationStatus.Success) { var gattCharacteristic = characteristics.Characteristics.First(); // CCCD への書き込みが必要。これがないとイベントハンドラが呼ばれない。 GattCommunicationStatus status = await gattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); if (status == GattCommunicationStatus.Success) { gattCharacteristic.ValueChanged += Changed_data; } } // モーション(動き)検知 100ms間隔(モーション系センサのみ) await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x2F, 0x03, 0x03 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x01, 0x03, 0x03 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x04, 0x03, 0x01 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x06, 0x04, 0x64, 0x00 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); // 100msec await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x2F, 0x03, 0x01 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); await characteristics1.Characteristics[0].WriteValueAsync(new byte[] { 0x20, 0x03, 0x01 }.AsBuffer(), GattWriteOption.WriteWithoutResponse); } catch (Exception ex) { Console.WriteLine($"Exception...{ex.Message})"); } } } public void Changed_data(GattCharacteristic sender, GattValueChangedEventArgs eventArgs) { Console.WriteLine($"characteristicChanged...Length={eventArgs.CharacteristicValue.Length}"); byte[] data = new byte[eventArgs.CharacteristicValue.Length]; Windows.Storage.Streams.DataReader.FromBuffer(eventArgs.CharacteristicValue).ReadBytes(data); var tmp = BitConverter.ToString(data); Console.WriteLine($"characteristicChanged...{tmp}"); return; } } }
センサネットワークモジュールモーションデータ取得プログラムの実行
センサネットワークモジュールモーションデータ取得プログラムを実行し、アルプスのセンサネットワークモジュールとペアリングできると、次のように受信されたモーションデータを16進表示します。データの最初のバイト「Event Code」が「E0」が ステータス通知、「F2」がデータパケット 1となります。モーションデータのデータ変換式については、「アルプスIoT Smart Moduleの加速度センサと地磁気センサの値をanyPiで取得/表示」を参照してください。
Start Received Service Find! characteristicChanged...Length=20 characteristicChanged...E0-14-00-00-00-00-00-00-00-00-02-00-00-00-00-00-00-00-00-00 characteristicChanged...Length=20 characteristicChanged...E0-14-00-00-00-00-00-00-00-00-02-00-00-00-00-00-00-00-00-00 ・・・・ characteristicChanged...F2-14-56-FF-96-FF-37-FF-4D-01-C9-0F-52-02-64-00-0A-00-00-00 characteristicChanged...Length=20 characteristicChanged...F2-14-56-FF-96-FF-37-FF-4D-01-C9-0F-52-02-64-00-0A-00-00-00 characteristicChanged...Length=20 characteristicChanged...F2-14-5A-FF-92-FF-3B-FF-47-01-A8-0F-E9-01-C8-00-0A-00-00-01 characteristicChanged...Length=20 characteristicChanged...F2-14-5A-FF-92-FF-3B-FF-47-01-A8-0F-E9-01-C8-00-0A-00-00-01 ・・・・