アルプスのセンサネットワークモジュールからモーションデータを取得する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 ・・・・
