IoT Hub から送信されるメッセージを Windows 10 IoT Core デバイスで受信する

Azure IoT Hub の特徴の一つが、IoT Hub からデバイス個別にメッセージをデバイス個別に送信する機能です。

今回は、クラウドから送信されるメッセージを Windows 10 IoT デバイスで受信する方法。
本稿は「Windows 10 IoT Core から IoT Hub にメッセージを送信するアプリをスクラッチで書いてみる」の関連、続きの記事です。新規プロジェクトの作り方は本稿では説明していないので、まずはこちらの記事で読んでから本稿を読むことをお勧めします。


■ IoT Hub からのメッセージの受信の仕方

IoT Hub からメッセージを受信するには、DeviceClient クラスの ReceiveAsync メソッドを使います。

var message = await _client.ReceiveAsync();

こんな感じ。
※ DeviceClient は、DeviceClient.CreateFromConnectionString(ConnectionString); で事前にインスタンス化しておきます。

注意点としては、メッセージを取得した時、またはタイムアウト(デフォルトでは1分)した時(=指定の時間内にメッセージが届かなかった時)に、非同期で ReceiveAsync メソッドが返ってくるところ。タイムアウト時間を明示的に指定できますが、どちらにしてもメッセージがなければ null が返ってくるので、次の ReceiveAsync でメッセージ取得を待ちます。

もう一つ、メッセージを取得して処理に成功したら、DeviceClientCompleteAsync メソッドを呼び出すこと。
サーバー側では ReceiveAsync されてメッセージを渡すと、一時的にそのキューメッセージが不可視になり、一定時間後に改めてキュー上でメッセージが可視になり、改めて同じメッセージが取得可能になります。ということで、処理後には必ず CompleleteAsync してください。

■ サンプルコード

以上を、実際のコードで見てみると以下の通り。

using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;

namespace IoTHubSendMessageDemo
{
    internal class SensorDevice
    {
        private readonly DeviceClient _client;
        private const string ConnectionString = "HostName=[ホスト名].azure-devices.net;DeviceId=[デバイスID];SharedAccessKey=[アクセスキー]";
        private const string DeviceId = "[デバイスID]";

        private double _delaySeconds = 5;

        public SensorDevice()
        {
            _client = DeviceClient.CreateFromConnectionString(ConnectionString);
        }

        internal async Task Run()
        {
            ReceiveMessageAsync();

            while (true)
            {
                var data = new SensorData
                {
                    DeviceId = DeviceId,
                    SensorValue = new Random().NextDouble()
                };

                var dataString = JsonConvert.SerializeObject(data);
                var message = new Message(Encoding.ASCII.GetBytes(dataString));
                await _client.SendEventAsync(message);

                Debug.WriteLine(dataString);

                Task.Delay(TimeSpan.FromSeconds(_delaySeconds)).Wait();
            }
        }

        private async void ReceiveMessageAsync()
        {
            while (true)
            {
                var message = await _client.ReceiveAsync();
                if (message == null)
                    continue;

                var msgString = Encoding.ASCII.GetString(message.GetBytes());
                Debug.WriteLine("Received a message : " + msgString);
                if (double.TryParse(msgString, out _delaySeconds))
                    Debug.WriteLine("Delay Seconds : " + msgString);

                await _client.CompleteAsync(message);
            }
        }
    }
}

■ サンプルコードの動作

念のためにサンプルコードの動作を説明します。

元になるコードは、こちらの記事で作った、疑似的なセンサーデータを送信するコードです。これにクラウドからのメッセージを受信する処理を追加しました。クラウド側は今回作っていないので、Device Explorer を使ってデータを送信してください。

2016-12-31 14-27-08

受信したデータの処は簡単のために数値のみです。(double.TryParse しているのでそれ以外のデータは捨てています)
受信した数値はセンサーデータ送信の間隔(秒)として使います。大きな値を指定すると間隔をあけてゆっくりとセンサーデータをアップロードするようになります。

2016-12-31 14-27-42

■ デバイスからのデータ送信のタイミングでメッセージを受信することに注意

この方法では、IoT Hub からデバイスへのメッセージを随時受信するわけではないことに注意してください。
デバイスから IoT Hub に接続したタイミングで、デバイス専用のキューにメッセージが積まれていた場合に メッセージを1件取得できるというものです。

このためデバイスから定期的に接続を行う、一般的にはセンサーデータの送信する必要があります。センサーデータ送信間隔によっては IoT Hub からのメッセージ取得するまでに時間がかかることに注意してください。だからと言って、通信の間隔が短すぎると余計な通信が発生してしまいます。適切な間隔を指定することが大事です。

万能な通信機能ではありませんが、デバイスごとに通信する内容を管理できますし、送信失敗した場合のリトライまで IoT Hub 側で責任を持ってくれます。
動きを理解した上で、デバイスとクラウドとの双方向の通信を使ってみてください。

広告
カテゴリー: IoT, Iot Hub, Raspberry Pi, Windows 10 IoT タグ: , , , パーマリンク

IoT Hub から送信されるメッセージを Windows 10 IoT Core デバイスで受信する への1件のフィードバック

  1. ピンバック: IoT Hub 経由でデバイスにメッセージを送信する | 技術との戯れ

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中