Sensorデータをデータベースに蓄積・活用する

7月3日のオープンソースセミナー2010@愛媛でお見せした、センサーデータをWindows 7 Sensor & Location Platform APIで取出し、ADO.NET Entity Data Modelで作成したSQL Serverのデータベースに格納・格納したデータをグラフや3Dモデルで見せるデモの、Entity Data Modelの部分について詳細を紹介します。

これまで、いろんな機会で紹介してきたセンサーデモですが、今までのものは、Sensor APIから取得した情報を元にWPFの各種コントロールを制御するものでした。センサーデータを取得する方法は全く同じです。https://msdn.microsoft.com/ja-jp/windows/ff432707.aspx で紹介しているように、Windows 7 API Code Packを通じて取得します。

デモアプリは、“LCASensorCloud”という名前でWPFアプリケーション(C#)を一つ作っておき、Windows 7 API CodepackのCore、Shell、Sensorsを参照として追加しておきます。

※私の環境はVisual Studio 2010の英語版が入ってます。メニューやコマンドなど適宜日本語への読み替えをお願いします。

取得したデータを格納するデータベースが必要になる訳ですが、次の手順で作っていきます。

  1. SQL Server Management Studioで、“LocationContextSensorDB”という名前のデータベースを新たに作成。
  2. Visual Studio 2010で“LCASensorCloud”プロジェクトに、データのADO.NET Entity Data Modelテンプレートを使って、新規項目を追加する。名前は”LCADataModel.edmx”としておきましょう。
    EDMItemTemplate
  3. Entity Data Model Wizardで、”Empty Model”を選択し、”Finish”ボタンをクリック。

すると、空のEntity Data Model Designer(いかにもDSL Toolkitで作りましたといった感じ)が開きます。蓄積したいSensorのデータ、及び、関連データを蓄積するためのEntity Modelを作成します。ツールボックスのEntityを配置、Entity間のAssociationを定義していきます。デモでは、下図のようなEntity Modelを作成しています。定義の要領は、Shlaer-Mellor法のクラスモデルの作り方と同じ。(関連クラスがないぐらいか)

LCAEntityModel

一応説明しておくと、

エンティティ 説明
Device センサーが装着されているPCや機器
Sensor Deviceの各種環境情報を計測するセンサーデバイス、Deviceには複数のセンサーが装着されてよい。 SensorIdは、センサーデバイスの一意のID
SensorSpec Windows 7 Sensor & Location Platformで規定されているセンサーのタイプ。このEntity Instanceは手入力。 SensorのEntityはこのエンティティを参照として一つ関連付けられ、そのSensorデバイスがどんな種類のSensorかがわかる。 ※Executable UMLのレシピパターン
SensorPropertySpec Windows 7 Sensor & Location Platformで規定されているセンサープロパティ。 EDMでは複合型が使えるので、PropertyIdTypeという型(Guid値とInt値)を定義し、PropertyIdの型としている。
MeasuredSession あるDeviceのあるSensorによるひとまとまりの測定区間。
MeasurePoint あるMeasuredSessionがターゲットとするSensorのMeasuredSessionに属する計測点。計測した時間を保持
MeasuredProperty MeasurePointのSensor計測値。SensorPropertySpecと関連を持つことにより。どのSensorのどのPropertyなのかを示す。 一つのセンサーで一度に複数の計測値を上げてくるセンサーデバイス向けに、MeasurePointから見て多になっている。

といったところ。
モデルを理解したところで、次にSQL Server上のデータベースにテーブルを生成します。手順は以下の通り。

  • Entity Data Model Designerビューの白地で右クリック→”Generate Database from Model..."を選択
  • データコネクションを選択し”Next”をクリック。一覧に冒頭で作ったLocationContextSensorDBが表示されない場合は、New Connection…をクリックし、Server NameにSQL Serverのサーバー名を入力して、下の方のデータベースコンボボックスから”LocationContextSensorDB”を選択し、”OK”ボタンをクリック
  • テーブルを定義するためのSQLのDDLスクリプトが生成され、一応内容をざっと見て、”Finish”をクリック。
  • 生成されたSQLファイルを表示し、Visual Studioのメニューの下図のパートで、左からデータベースに接続(Click&Select)、ターゲットデータベースの選択(コンボボックスから選択)、SQLの実行(アイコンクリック)を順に実施
    ExecuteSQL

これで、SQL ServerのLocationContextSensorDB上にEDMモデルで定義されたEntityがテーブルとして生成されます。更に、このEDMモデルのセマンティクスのレベルでデータにLINQでアクセスするためのManagedライブラリが生成されます。アプリケーションでは、このライブラリを使用します。

デモアプリでは、予め、SensorSpecとSensorPropertySpecのEntityは、SQL Server Management Studioで手入力(当日は、Accelerometer3D、Ambient Light、Human Presence、Brainwaveの四種類)しておきました。センサーから取得したデータを、EDM層を通じて書き込めば、センサーデータを蓄積する側のコードの出来上がりです。

Ambient Lightの場合で、このコードを例示します。

まず計測開始時のコード:

AmbientLightSensor al = ...;    // Windows 7 API Codepackのクラス using (var entityContainer = new LocationContextDataModelContainer())  // EDM Toolが生成したデータベースコンテナ {     // 登録済みのSensorSpec、SensorPropertySpecを検索     var sspecs = from sspec in entityContainer.SensorSpec                               where sspec.TypeName.CompareTo("AmbientLight")==0                               select sspec;     SensorSpec alSpec = sspecs.First();     SensorPropertySpec  alPropSpecLux = alSpec.SensorPropertySpec.First();     // Sensorインスタンスを作成 ※このクラスはEDM Toolが生成したクラス。     // ※Win 7 API Codepackのものではないことに注意     Sensor alSensor = new Sensor();     alSensor.SensorSpec = alSpec;     alSensor.Device = targetDevice;    // targetDeviceインスタンスはDeviceエンティティのインスタンス。予め作成しておく     ...     entityContainer.AddToSensor(alSensor);     entityContainer.SaveChanges();     // ここでIdの値が確定     // 計測セッションを作成     MeasuredSession session = new MeasuredSession();     session.Device = targetDevice;     session.Sensor = alSensor;     entityContainer.AddToMeasuredSession(session);     entityContainer.SaveChanges();

LocationContextDataModelContainerやSensorSpec、SensorPropertySpec、Sensor等は、先ほど図示したEntity Modelから生成されたクラス群です。
こんな感じで、SQLを知らなくても、データベース上のクエリや、レコード生成が可能です。
そして、Ambient Lightセンサーがデータを通知してくるたびに、以下のようなコードを実行します。

    double lux = al.CurrentLuminousIntensity.Intensity;     var mp = new MeasurePoint();    // EDM ToolがMesuarePointエンティティの定義から生成したクラス     mp.MeasuredSession = session;    // MeasuredSessionのインスタンスは、計測開始時に作っておく     mp.MeasuredTime = al.DataReport.TimeStamp;     entityContainer.AddToMeasurePointSet(mp);    // コンテナに追加し     entityContainer.SaveChanges();    // データベースに保存。Idはここで確定     var mprop = new MeasuredProperty();     mprop.MeasurePoint = mp;     mprop.Value = lux.ToString();     mprop.SensorPropertySpec = alPropSpecLux;    // alPropSpecLuxは、SensorPropertySpecの照度センサーの照度プロパティをあらかじめ検索しておく     entityContainer.AddToMeasuredPropertySet(mprop);     entityContainer.SaveChanges();

※実際にはエラーハンドリングのコードが必要だが、煩雑なので割愛。スコープの関係で、実際には変数の定義場所、スコープの維持等で工夫が必要なことにご注意。

私が良く使っているFreescaleのSensor Development Kitボードの場合、100msec毎にデータが通知されます。そのハンドラーにこのコードを書けば100msec毎にデータベースに値が蓄積されます。

さて、次は、蓄積されたセンサーデータを利用する側のコードを説明します。

// 一秒間隔でデータ取得コードを起動するコード var timer = new System.Window.Threading.DispatcherTimer timer(); timer.Interval = new TimeSpan(0,0,1); timer.Tick += new EventHandler(timer_Tick); timer.Start(); .... void timer_Tick(object sender, EventArgs e)  {     using (var entityContainer = new LocationContextDataModelContainer())     {         // Ambient Lightの計測データで計測された最後の値をクエリ         var mps = from mp in entityContainer.MeasurePoint                             mp.Sensor.SensorSpec.TypeName.CompareTo("AmbientLight")==0                               && mp.MeasuredSession.Device.EqualTo(targetDevice)                             orderby mp.MeasuredTime descending select mp;         var lastMProp = mps.First().MeasuredProperty.First();         // 取得したMeasuredPropertyに格納された値をdouble化         double lux = Double.Parse(lastMProp.Value);         ....         // 後は煮るなり、焼くなり勝手にしてね。     } }

こんな風にコードを書いて、データを蓄積する側のコードの実行と並行して、このコードを実行すれば、一秒単位でその時点での最新データを取得できます。後はそのデータをグラフ化するなり、https://msdn.microsoft.com/ja-jp/windows/ff423757.aspx#02で公開している脳波で地球を回すアプリの、脳波センサーからデータを取得するところを置き換えたりと、活用することができます。

実はこのEDM、ETロボコンの競技計測システムのデータベースアクセスの部分で使用しています。SQLでゴリゴリ書いたりしなくて非常に便利です。EDMを使った部分の不具合も今のところ皆無です。
他にも、私が連載中の「デバイス+クラウド」のコラムでも、現実世界に無数のセンサーノードを設置して、センサー値を蓄積していくシナリオが紹介されていますが、そんなシーンでも活躍することでしょう。
このテクノロジーは、Windows 7の特殊用途向けライセンスでももちろんそのまま使えますし、Windows 7の組込み向けOS、Windows Embedded Standard 7でも利用可能です。ぜひご活用ください。

 

 

 

ちなみに、イベント当日にお見せしたアプリケーションは、こんな感じ。

蓄積側
LCAClient
利用側
LCAAppGraph
Sensorデータベース版Brain Earth
image