.NET対応組み込みデバイス「Netduino」入門(7)
Netduinoの計測結果をクラウド集計
Netduinoで計測した室温データをクラウドに送信してWebから見えるようにしてみよう。
前回作成したLCD付き室温測定回路から、httpプロトコルを使ってMicrosoft Azure(クラウド)上のサービスに室温データを送信する。
使用部品について
前回のおさらいになるが使用部品とブレッドボード上の実装を再度紹介する。
Netduinoからの5V
ラインは、赤いラインを通ってブレッドボードの一番下のプラス電源ラインを経由し、LCDのVDD
とRESET
そして温度センサーのVDD
、1組のプルアップ抵抗へと5Vを供給する。NetduinoのGND
からの線も同様に青いラインを通って下から2番目のGNDラインに接続し、LCDと温度センサーのGND
に接続する。
SCL
とSDA
の2つの信号線は、SCLがA23
、SDAがA22
でNetduinoに接続し、ここからB13
とC14
に分岐してLCD側に接続する。また、プルアップ用の10KΩ抵抗でA13
とA14
からプラス電源ラインの間を接続する。
Microsoft Azure Mobile Serviceの準備
Netduino側のアプリを作成する前に、データを格納するMicrosoft Azure Mobile Service(=いわゆるmBaaS。最新Azureでは「Mobile Apps」と呼ばれている。詳しくはこちらを参照)を作成する。詳細は割愛するが、図2を参考に作成してほしい。
※Azureには、プレビュー版の新ポータルと、従来からの旧ポータルがある。本稿では旧ポータルを利用した。
モバイルサービスを作成したら、[データ]タブから「Item」という名前でテーブルを作成しておく。※なお、作成時に指定できるアクセス許可レベルの設定は、デフォルトのままでOK。
また、一番左の[クイックスタート]タブを開いて、先ほど作成したモバイルサービスのコードサンプルを参照して(具体的には図3のようにして閉じられている項目を開くと[アプリケーションへ接続する]ためのコードとして参照できる)、アクセスキー(=MobileServiceClient
クラス・コンストラクターの第2引数。以下、AccessKey)とURL(=第1引数。以下、MobileServiceURL)をメモしておこう。ここでメモしたAccessKeyとMobileServiceURLはコード作成時に使用する。注意点として、今回はhttpsではなくhttpを使うので、URLのhttpsの「s」を削除すること。
Netduinoのネットワーク設定
Netduino Plus 2にはLANインターフェースが実装されている。LAN接続をするためには、接続する有線LANに合わせて設定しなければならない。この設定は、Netduino Plus 2をUSB接続した後に.NET Micro Framework Deployment Tool(以下、MFDeploy)を起動して[Device]で[USB]を選択することでNetduino Plus 2デバイスを指定してから、上部の[Target]-[Configuration]-[Network]メニューでネットワーク設定ダイアログを表示して行う(図4)。また[MAC Address]欄には、Netduino Plus 2の裏のシールに記載された値を入力しておく。入力したMAC Addressは後でデバイスIDとして使用する。
[Update]ボタンをクリックしてダイアログを閉じる。最後に、有線LANケーブルを接続し、[Ping]ボタンをクリックすると「IP Address」が表示される(※表示されない場合は何度か[Ping]ボタンを押してみたり、有線LANケーブルを抜き差ししたりしてみてほしい)。
NetduinoでのREST/JSONプログラミング
回路が完成したら、Visual Studioで[Netduino Plus 2 Application]テンプレートを選択して、新規にプロジェクトを作成して(本稿の例では、プロジェクト名はVB.NET用は「IoTRestVB」、C#用は「IoTRestCS」とした)、アプリのプログラミングを始める。
前回のクラス構成
まずは前回と同じクラスをプロジェクトに取り込む。
I2C用クラスであるI2CLib
クラスを基本クラスとして、LCD用AQM0802Lib
クラス、温度センサー用ADT7410Lib
クラスに派生させてから呼び出している。
Json.NETクラスライブラリの追加
Azure Mobile Serviceにデータを送信するためには、JSON形式のデータとして送信しなければならない。簡単なものであればJSON形式になるように送信文字列を組み立ててもいいが、今回はNuGetパッケージとして配布されている.NET Micro Framework用クラスライブラリを使用する。NuGetから必要なクラスライブラリを取得するには次の手順で行う。
ソリューションエクスプローラーでプロジェクト項目の右クリックメニューから[NuGet パッケージの管理]を選択する。これによりダイアログが表示されるので、図6の説明手順を実施する。
- 1[オンライン]を選択。
- 1検索欄に「Json.NET」と入力して検索。
- 1検索結果の一覧から「Json.NetMF」を選択して[インストール]ボタンをクリック。
NuGetパッケージとしてインストールすれば自動的に参照設定なども行われるし、更新がかかれば[NuGet パッケージの管理]ダイアログで[更新プログラム]として表示されるので、クラスライブラリが管理しやすくなる。
.NETコンポーネントの追加
今回はネットワーク通信が必要なので、標準提供の[.NET]コンポーネントから「System.Http」と「System.IO」についても参照設定を行う。その手順は、図7を参考にされたい。
C#の場合は、ソリューションエクスプローラーでプロジェクト項目を右クリックしてコンテキストメニューを表示し、そこから[参照の追加]メニューを選択(VBの場合は、プロジェクトプロパティの[参照]タブを開いて[追加]ボタンをクリック)。これにより、このダイアログが表示される。
[Add Reference]ダイアログの[.NET]タブの一覧から「System.Http」と「System.IO」を選択して[OK]ボタンをクリック。
データ送信クラスの追加
クラスライブラリの追加が完了したら、室温を送信するためのRESTLib
クラスを作成する。
Imports System
Imports Microsoft.SPOT
Imports System.Net
Imports System.Text
Imports System.IO
Friend Class RESTLib
Implements IDisposable
Private Const DeviceId As String = "00-04-a3-00-00-00"
Private Const AccessKey As String = "[AccessKey]"
Private Const UrlString As String = "[MobileServiceURL]"
Public Sub Setup()
End Sub
Public Sub Upload(temperature As Single)
Try
Dim request = CType(HttpWebRequest.Create(UrlString + "tables/Item"), HttpWebRequest)
Dim serializer = New Json.NETMF.JsonSerializer()
Dim json As New TItem
request.Headers.Add("X-ZUMO-APPLICATION", AccessKey) ' ……1
request.Accept = "application/json" ' ……1
request.ContentType = "application/json" ' ……1
request.Method = "POST" ' ……1
json.DeviceId = DeviceId.ToString()
SyncLock (Me)
json.Temperature = temperature
End SyncLock
Dim jsonString = serializer.Serialize(json) ' ……2
Dim postDataBytes As Byte() = Encoding.UTF8.GetBytes(jsonString) ' ……3
request.ContentLength = postDataBytes.Length
Using reqStream = request.GetRequestStream()
reqStream.Write(postDataBytes, 0, postDataBytes.Length) ' ……4
End Using
Using res = CType(request.GetResponse, HttpWebResponse)
Debug.Print(res.StatusCode.ToString())
End Using
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
Public Class TItem
Public Property id As String
Public Property DeviceId As String
Public Property Temperature As Single
End Class
#Region "IDisposable Support"
' ……省略……
#End Region
End Class
|
using System;
using Microsoft.SPOT;
using System.Net;
using System.Text;
using System.IO;
namespace IoTRestCS
{
internal class RESTLib : IDisposable
{
private const string DeviceId = "00-04-a3-00-00-00";
private const string AccessKey = "[AccessKey]";
private const string UrlString = "[MobileServiceURL]";
public void Setup()
{
}
public void Upload(Single temperature)
{
try
{
var request = (HttpWebRequest)(HttpWebRequest.Create(UrlString + "tables/Item"));
var serializer = new Json.NETMF.JsonSerializer();
var json = new TItem();
request.Headers.Add("X-ZUMO-APPLICATION", AccessKey); // ……1
request.Accept = "application/json"; // ……1
request.ContentType = "application/json"; // ……1
request.Method = "POST"; // ……1
json.DeviceId = DeviceId.ToString();
lock (this)
{
json.Temperature = temperature;
}
var jsonString = serializer.Serialize(json); // ……2
var postDataBytes = Encoding.UTF8.GetBytes(jsonString); // ……3
request.ContentLength = postDataBytes.Length;
using (var reqStream = request.GetRequestStream())
{
reqStream.Write(postDataBytes, 0, postDataBytes.Length); // ……4
}
using (var res = (HttpWebResponse)request.GetResponse())
{
Debug.Print(res.StatusCode.ToString());
}
}
catch (Exception ex)
{
Debug.Print(ex.Message);
}
}
public class TItem
{
public string id { get; set; }
public string DeviceId { get; set; }
public float Temperature { get; set; }
}
public void Dispose()
{
}
}
}
|
00-04-a3-00-00-00
にはデバイスID(図4参照)を指定する。また、[AccessKey]
と[MobileServiceURL]
(※「https」を「http」に変更しないと正常に動作しないことに注意)を先ほど取得した値(図3参照)に書き換える。
- 1REST/JSONデータ送信用ヘッダーの設定。
- 2クラスからJSON文字列への変換。
- 3JSON文字列からUTF8データへの変換。
- 4データ送信。
メインプログラムの作成
クラスの用意ができたらMain
メソッドからADT7410Lib
クラスとAQM0802Lib
クラスの呼び出しを作成する。
Module Module1
Sub Main()
Using rest As New RESTLib
Using lcd As New AQM0802Lib
lcd.Init() ' ……1
End Using
While (True)
Dim value As Single
Using adt7410 As New ADT7410Lib
value = adt7410.ReadTemperatre ' ……2
End Using
Using lcd As New AQM0802Lib
lcd.Locate(0, 0)
lcd.WriteMessage(value.ToString()) ' ……3
rest.Upload(value) ' ……4
End Using
Thread.Sleep(1000)
End While
End Using
End Sub
End Module
|
……省略……
public class Program
{
public static void Main()
{
using (var rest = new RESTLib())
{
using (AQM0802Lib lcd = new AQM0802Lib())
{
lcd.Init(); // ……1
}
while (true)
{
Single value;
using (ADT7410Lib adt7410 = new ADT7410Lib())
{
value = adt7410.ReadTemperature(); // ……2
}
using (AQM0802Lib lcd = new AQM0802Lib())
{
lcd.Locate(0, 0);
lcd.WriteMessage(value.ToString()); // ……3
rest.Upload(value); // ……4
}
Thread.Sleep(1000);
}
}
}
}
|
- 1LCD初期化(
using
ブロックの間だけ接続)。 - 2温度センサーからの値取得(
using
ブロックの間だけ接続)。 - 3LCDに温度表示(
using
ブロックの間だけ接続)。 - 4温度データ送信。
アプリ実行
アプリを実行すると1秒ごとに気温を送信する。
送信したデータは、Azureのポータルサイトにおける該当のモバイルサービスの[データ]タブで確認できる。
まとめ
Netduino Plus 2では残念ながらリソースの関係でOpenSSLが利用できない。そのため、SSL通信が不要なhttpを使ってAzureに測定結果を送信した。しかし、センサー測定値の送信にはもっと軽量なAMQP(Advanced Message Queuing Protocol)というプロトコルを使用することが主流になりつつある。
AMQPは2003年のJohn O'Hara氏により提唱されたセキュリティも考慮されたメッセージ交換方式だ。AzureのIoT連携機能であるEvent Hubsでも採用され、.NET Micro Framework用のライブラリもオープンソースとして公開されている。
今回も当初はEvent Hubsを使用することを想定してサンプルアプリも作成したが、残念なことにEvent Hubsとの接続にはセキュリティを意識したAMQPSプロトコルが必須であり、その接続にはSSLによる暗号化が必要なため、Netduino Plus 2で実行することはできなかった。
Arduinoとピン互換で.NET Micro Frameworkが動作するハードウェアがないか探したところ、Netduino Plus 2の後継機種であるNetduino 3 WiFiや、ルネサスエレクトロニクスがこの夏に発売予定のGR-Peach ならばSSL通信が可能であると分かった。早期評価版のGR-Peachが入手できたので、次回はSSL対応の.NET Micro Frameworkの設定や、GR-Peachに今回の回路をそのまま使ってEvent Hubsへ測定結果を送信する方法などについて紹介したい。
※以下では、本稿の前後を合わせて5回分(第5回~第9回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
6. Netduinoシリアル通信(I2C)で複数機器接続
シリアル通信(I2C)で2つ以上の機器を同時に使用するサンプルを作成する。温度センサーから室温を取得して液晶ディスプレイ(LCD)にリアルタイム表示してみよう。
8. GR-PEACHボードとAzure Event Hubでクラウド集計
ついに発売開始されたGR-PEACHを利用。Microsoft Azure Event Hubを使って室温データをクラウドに送信してWebから見えるようにしてみよう。
9. サーボモーターをコントロールしよう
Netduinoはセンサー入力系だけでなく豊富な出力系も活用できる。今回は、ラジコン経験者にはなじみがあるサーボモーターをNetduinoから制御してみよう。