Windows 7 Sensor & Location Platformを使ってみよう!! - その3

三回目は、いよいよ、センサーデータの取り出し方を説明します。センサーの取得方法は、その2を見てくださいね。

Sensor & Location PlatformのAPIには、センサーデータの取り出し方が二種類用意されています。一つ目は、”見たい時に見る”方法(同期参照)、二つ目は、”データが変化したときに通知を受ける”(非同期参照)です。センサーデバイスやデバイスドライバによっては、同期参照しかできないものもありますが、アプリケーションシナリオで、センサーの値が必要な時だけ見ればよい場合には、同期参照を、ほぼリアルタイムにセンサーの値を見ながら制御をしたい場合には、非同期参照を使います。

では、まず、同期参照から。同期参照の場合は、以下のようなコードで記述します。

Sensor sensor = ...;sensor.TryUpdate();SensorReport report = sensor.DataReport;DateTime updatedTime = report.TimeStamp;foreach (var propertyKey in report.Values.Keys){    Guid propertyId = propertyKey;    foreach(var propertyValue in report.Values[propertyKey])    {        // propertyValueが同一propertyIdに属する一連のプロパティの値    }} 

コードの中で、”一連のプロパティの値”と書いていますが、Windows 7 SDKのsensors.hを覗いてみると、たとえば、3軸加速度センサーの値は、

となっていて、Guidで示されるプロパティ値に、X方向、Y方向、Z方向が、それぞれ2,3,4で定義されているのがわかります。上のコードで3軸加速度センサーの値を取得すると、順にX方向、Y方向、Z方向を取得できます。
上のコードは、色々な種類のセンサーを扱うような場合に、有用なコードですが、特定のセンサーしか使わないアプリケーションの場合は、

PropertyKey propertyKey =    new PropertyKey(        "{3F8A69A2-07C5-4E48-A965-CD797AAB56D5}",        2);var accel3DX = sensor.GetProperty(propertyKey);

といったように、プロパティのGuidと、フォーマットIDを指定して、GetPropertyメソッドで取得できます。

次に、非同期参照を紹介します。この方法は、センサー値が変化したときに呼びだしてもらうイベントハンドラをセンサーに登録しておき、イベントハンドラが呼ばれたら、センサー値を取り出します。

sensor.DataReportChanged +=    new DataReportChangedEventHandler(        sensor_DataReportChanged);....void sensor_DataReportChanged(Sensor sender, EventArgs e){    SensorReport report = sender.DataReport;    // 同期参照と同じ方法で取得}

イベントハンドラが呼ばれたときにセンサー値を見る方法は、同期参照と同じやり方ですが、TryUpdateをコールする必要はありません。たとえば、WPFアプリケーションで、UI要素にバインディングされた変数に、取得したセンサー値を書き込んでやれば、センサーの値が変化するたびに、WPFのUI要素の表示がそれに追従して変化させることができます。TextBoxのContentでも、Labelのテキストでも、透過率でも、回転などの図形変換行列でも構いません。ただし、注意点としては、WPFのUIを司っているスレッドと、イベントハンドラをコールするスレッドが異なっているので、UI要素にバインドした変数への書き込みによる表示の変更は出来ますが、アニメーションの起動やMediaElementのPlay等は、直接は出来ません。その場合には、親ウィンドウのDispatcherにBeginInvokeコールが必要です。それさえ気をつければ、問題ないでしょう。XAML上に照度センサーが計測した照度を表示するサンプルコードを紹介して、3回目は終わり!!

XAML Code:<Window x:Class="WpfSensorSample.MainWindow"        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"        Title="Sensor Sample" Height="300" Width="300">    <Window.Resources>        <src:SensorDataProvider x:Key="myDataProvider"/>    </Window.Resources>    <Grid>      <TextBlock Name="AmbientLevel" Text="{Binding Source={StaticResource myDataProvider}, Path="Level", Mode="OneWay"/>    </Grid></Window>XAML Code Behind C#:MainWindow(){    InitializeComponent();    foreach (var sensor in SensorManager.GetSensorByTypeId<AmbientLightSensor>())    {        sensor.DataReportChanged += new DataReportChangedEventHandler(sensor_DataReportChanged);        break;    }}....void sensor_DataReportChanged(Sensor sender, EventArgs e){    SensorDataProvider myProvider = this.Resources["myProvider"] as SensorDataProvider;    AmbientLightSensor alSensor = sender as AmbientLightSensor;    myProvider.Level = alSensor.CurrentLuminousIntensity;}....class SensorDataProvider : INotifyPropertyChanged{    private double _level;    public double Level    {        get { return _level; }        set {            _level = value;            OnPropertyChanged("Level");        }        #region INotifyPropertyChanged メンバ        public event PropertyChangedEventHandler PropertyChanged;        private void OnPropertyChanged(string paramName)        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(paramName));            }        }        #endregion    }}

ちなみに、Windows API Code Packは、最終的には、COMでしか提供されていない機能を.NETのManagedライブラリ化していく過程のものという位置づけで、実はすでにVisual Studio 2010 Beta 2と一緒に提供されている.NET Framework V4.0には、ロケーション系の機能のManagedライブラリがすでに一部入っています。System.Device.dllというアッセンブリーがそれです。名前空間は、System.Deviceで、その中にロケーション情報をとるためのManagedライブラリが用意されていて、PDC2009のLocation Context Awarenessのセッションで取り上げられていました。次回は、それを紹介してみます。

その4へ 目次へ