IoT Hub 経由でデバイスにメッセージを送信する

IoT Hub にはデバイスにメッセージを送信する機能がありますが、前の記事では送信元として Device Explorer を使用しました。API が用意されているので、任意のアプリケーションから IoT Hub を経由してメッセージを送信することができます。今回はそのお話。

IoT Hub とデバイス(主に Windows 10 IoT)との通信や管理についての記事をいくつか投稿しました。本稿と合わせてご覧ください(以下の記事を順に読んで、最後に本稿を読むことをお勧めします)。


■ メッセージの送信の仕方

アプリケーションから IoT Hub 経由でデバイスにメッセージを送信するには、ServiceClient クラスの SendAsync メソッドを使います。

ServiceClient _client = ServiceClient.CreateFromConnectionString(ConnectionString);
await _client.SendAsync([デバイスID], [Message]);

こんな感じです。

Message は

var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));

こんな感じでバイト配列にしておけば OK。

デバイスから IoT Hub にメッセージを送るのにそっくりです。
違いは、デバイスから IoT Hub に送る場合は DeviceClient クラスを使い、IoT Hub からデバイスにメッセージを送るには ServiceClient クラスを使うこと。
どちらも Client クラスのインスタンス生成は CreateFromConnectionString スタティックメソッドを使うのは同じです。


■ サンプルコード

サンプルコードのベースは こちらの記事 ですが、MainWindow.xaml および MainWindow.xaml.cs を以下のように変更してみました。デバイスにメッセージを送信するのは SendMessageButton_Click メソッドの部分です。

DeviceMaiager.cs は今回の内容には関係ないので、前の記事のままで持ってくればビルドに成功するはず。
もちろん送信元のアプリが WPF である必要はありません。

<Window x:Class="IoTDeviceManager.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:IoTDeviceManager"         mc:Ignorable="d"         Title="IoT Hub Device Manager" Height="350" Width="525">
    <Grid>
        <Label x:Name="DeviceIdLabel" Content="デバイスID" HorizontalAlignment="Left" Margin="31,28,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceIdBox" HorizontalAlignment="Left" Height="23" Margin="115,31,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Label x:Name="PrimaryKeyLabel" Content="プライマリキー" HorizontalAlignment="Left" Margin="31,81,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="PrimaryKeyBox" HorizontalAlignment="Left" Height="23" Margin="115,81,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360" IsReadOnly="True"/>
        <Label x:Name="StateLabel" Content="状態" HorizontalAlignment="Left" Margin="31,131,0,0" VerticalAlignment="Top"/>
        <RadioButton x:Name="EnabledButton" Content="有効" HorizontalAlignment="Left" Margin="115,137,0,0" VerticalAlignment="Top" GroupName="StateGroup" IsChecked="True"/>
        <RadioButton x:Name="DisabledButton" Content="無効" HorizontalAlignment="Left" Margin="190,137,0,0" VerticalAlignment="Top" GroupName="StateGroup"/>
        <Label x:Name="DeviceMesageLabel" Content="メッセージ" HorizontalAlignment="Left" Margin="31,183,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceMessageBox" HorizontalAlignment="Left" Height="23" Margin="115,186,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Button x:Name="CreateButton" Content="登録" HorizontalAlignment="Left" Margin="31,260,0,0" VerticalAlignment="Top" Width="75" Click="CreateButton_Click"/>
        <Button x:Name="GetButton" Content="取得" HorizontalAlignment="Left" Margin="111,260,0,0" VerticalAlignment="Top" Width="75" Click="GetButton_Click"/>
        <Button x:Name="SetStateButton" Content="状態変更" HorizontalAlignment="Left" Margin="191,260,0,0" VerticalAlignment="Top" Width="75" Click="SetStateButton_Click"/>
        <Button x:Name="SendMessageButton" Content="送信" HorizontalAlignment="Left" Margin="271,260,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.353,0.629" Click="SendMessageButton_Click"/>
        <Button x:Name="DeleteButton" Content="削除" HorizontalAlignment="Left" Margin="400,260,0,0" VerticalAlignment="Top" Width="75" Click="DeleteButton_Click"/>
    </Grid>
</Window>
using System.Text;
using System.Windows;
using Microsoft.Azure.Devices;

namespace IoTDeviceManager
{
    public partial class MainWindow : Window
    {
        private const string ConnectionString = "HostName=[ホスト名].azure-devices.net;SharedAccessKeyName=[アクセスキー名];SharedAccessKey=[アクセスキー]";

        private readonly DeviceManager _manager;
        private readonly ServiceClient _client;

        public MainWindow()
        {
            InitializeComponent();

            _manager = new DeviceManager(ConnectionString);
            _client = ServiceClient.CreateFromConnectionString(ConnectionString);
        }

        private async void CreateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.CreateDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void GetButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void SetStateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            device.Status =
                EnabledButton.IsChecked.HasValue && EnabledButton.IsChecked.Value ?
                DeviceStatus.Enabled : DeviceStatus.Disabled;

            device = await _manager.SetDeviceStatus(device);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            await _manager.DeleteDevice(DeviceIdBox.Text);
        }

        // アプリから Iot Hub 経由でデバイスにメッセージを送信する
        private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
        {
            var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));
            await _client.SendAsync(DeviceIdBox.Text, message);
        }
    }
}

 

本稿を含めて 4会の記事で、IoT Hub とデバイスとの通信についての説明は終わり。
IoT Hub を使って面白いシステムをどんどん作ってみてください。

カテゴリー: IoT, Iot Hub, Windows 10 IoT | タグ: , , | 1件のコメント

2017年は Windows Development のカテゴリーで MVP を受賞しました

あけましておめでとうございます。

今年もマイクロソフトの MVP を受賞しました。
今回は Windows Development カテゴリーでの受賞です。

昨年は活動の「数」は例年より少なくなってしまい(マイクを持っていた時間は増えているんですが)、それに対して情報の範囲が広くなったために散漫な感じになってしまったかもしれません。

今年は受賞対象である Windows Development  を核に情報発信していきたいと考えています。もちろん他の分野の技術についても、デバイス開発との関連を意識して扱っていきます。

本年も、イベントでブログで、よろしくお願いします。

カテゴリー: 未分類 | コメントをどうぞ

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 | タグ: , , , | 1件のコメント

Intel Joule に Windows 10 IoT をインストールするステップ・バイ・ステップ

高性能マイコンボード(高価格でもありますけど)の Intel Joule
Windows 10 IoT Core が動作するボードでもあります。温度や加速度を取得するだけの単なるセンサーデバイスとして使うよりは、性能を生かして画像処理などをさせるといいんでしょうね。

DSC_0094

DSC_0095

Windows 10 IoT のインストールは手順が多くて面倒ではありますが、難しいところはありません。Windows 10 IoT の Get Started の手順通りにやるだけです。
ただ日本語の情報をほとんど見かけないので、ここでは画面キャプチャとともにステップバイステップで紹介します。


■ 用意するもの

Joule に Windows 10 IoT をインストールするにはいくつか用意するものがあります。

  • USB メモリー・・・インストールメディアとして使用します。空のもの、または中身をすべて削除してもいいものを用意してください。インストール完了後は不要です。
  • USB 接続のキーボードおよびマウス
  • USB ハブ・・・Joule は USB ポートを1個しか持っていません。が、インストールメディ、USB キーボード、USB マウスをすべて接続しなければなりません。ということでハブが必要です。
  • micro HDMI のケーブルまたはアダプターとディスプレイ・・・Joule は HDMI ディスプレイが接続できますが、端子がmicro HDMI です。
  • 12V 3A の電源ケーブル・・・ここが落とし穴ですね。なかなか持ってないと思います。私の場合は運よく NVIDIA Jetson TK1 を持っていて、これの電源ケーブルが使えました。持ってない方は、スイッチサイエンスさんあたりで買えます。

■ デバイスの選択

Get Started に沿って、まずはデバイスを選択します。ここでは当然 “Intel Joule” です。

2016-12-25 10-17-14

母艦が Windows 10 であることが前提ですが・・・確認するまでもないですね。

 


■ Windows Assessment and Deployment Kit のダウンロードとインストール

Windows Assessment and Deployment Kit をダウンロードします。

2016-12-25 10-42-12

インストールは特に迷うところはないと思います。デフォルトのままでウィザードを進めます。

2016-12-25 10-45-28

デフォルトで進めると、Windows ADK は “C:\Program Files (x86)\Windows Kits\10” にインストールされます。

2016-12-25 22-40-25

ここで Windows  を再起動します。

 

■ インストールメディアを USB メモリーに作成

Joule で Windows をブートしてインストールするために Windows PE を作成します。先ほどインストールした Windows ADK を使用します。
インストールメディアとして使用するのは空または中身をすべて削除してもよい USB メモリーです。容量は 16GB で十分です。(もっと小さくてもいいと思いますが、私の手元にはありませんでした・・・)
以下のツールを実行するとドライブの中身がすべて消されるので注意してください。(この手の作業の基本的な注意事項ですね)

Windows のメニューにある [Windows Kit]-[展開およびイメージングツール環境]管理者として実行します。

2016-12-25 14-45-47

コマンドプロンプトが開いたら、

copype amd64 C:\WinPE_amd64

を実行して、作業フォルダー(C:\WinPE_amd64)に WinPE のファイルを展開します。

2016-12-25 22-50-51

続いて、

MakeWinPEMedia /UFD C:\WinPE_amd64 E:

を実行します。(※最後の “E:” の部分は、インストールメディアを作成する USBメモリーのドライブ名)

2016-12-25 23-52-46

 

■ インストールコマンドのダウンロード

Joule に Windows 10 IoT をインストールするためのコマンドを、インテルのサイトからダウンロードします。

2016-12-25 14-55-52

ZIP ファイルを展開すると、”JouleInstaller.cmd”なるファイルがあります。これを先ほど作ったインストールメディアのルートにコピーします。

2016-12-25 15-04-51

 

■ Windows 10 IoT Core のイメージのダウンロードとコピー

Windows Insider Preview Downloads のサイトから、Joule 用の Windows 10 IoT Core のイメージをダウンロードします。

2016-12-25 14-56-192016-12-25 14-56-40

ダウンロードした iso ファイルをダブルクリックでマウントすると、msi ファイルがあるので、これをインストールします。

2016-12-25 15-02-28

これで “C:\Program Files (x86)\Microsoft IoT\FFU\Broxton” に “flash.ffu” というファイルがあります。

これをインストールメディアの USB メモリーのルートにコピーします。

2016-12-25 15-04-25

以上で、インストールメディアは完成です。次はこれを Joule に接続して Windows 10 IoT をインストールします。

 


■ BIOS アップデート用に PC にドライバーインストール

Windows 10 IoT をインストールする前に、Joule の BIOS のアップデートが必要です。この手順は購入後に一度だけ必要です。

Intel の こちらのページ にアクセスして、BIOS アップデートに必要なドライバーを PC にインストールします。
Joule_BIOS_2016-11-15-161-Public.zip” (今後ファイル名が変更される可能性はあります)がそれです。ダウンロードしてください。

2016-12-25 15-14-412016-12-25 15-14-55

ダウンロードしたファイルを展開したら、”FlashUsbDriver-1.0.0.exe”を実行して、ドライバーをインストールします。。”DNX\DNX-dldrcli\installer”フォルダーにあるはず。

2016-12-26 23-29-25

 

■ Joule 本体の BIOS アップデート

Joule 本体の BIOS をアップデートします。購入後に一度だけ必要です。

このあと、PC と接続するために Type C USB ケーブルを接続しますが、それ以外は USB、micro SDなどすべて取り外します。ここでは電源ケーブルも繋ぎません

すべての周辺機器が接続されていない状態で、Joule 本体の “DNX Boot” ボタンを抑えたままで、PC と Joule とを付属の USB ケーブルで接続します。接続後は DNX Boot ボタンを離してもかまいません。

Joule が認識されれば、PC のデバイスマネージャーでは、ユニバーサルシリアルバスデバイスに “Inte DnX Device”というデバイスが見えるはず。

2016-12-25 15-38-05

 

Joule が認識されることを確認したら、BIOS アップデートを行います。
展開したフォルダーにある “Joule_C0-X64-Release-161-Public_DNX.bin”が BIOS ファイルです。コマンドプロンプトを開き、“DNX”フォルダーにある “Flash.bat”で bin ファイルをインストールします。

Flash.bat Joule_C0-X64-Release-161-Public_DNX.bin

2016-12-26 23-39-132016-12-26 23-38-41

2016-12-25 15-40-12

私は bin ファイルが一つ上のフォルダーにある状態で実行しましたが、特に問題なく BIOS アップデートに成功しました。念のため、スペースや日本を含まない場所に置くのがいいと思います。

 

■ Joule の準備

いよいよ Joule 側の作業に入ります。まずは、通電する前に以下を確認します。

  • USB ハブ経由で、インストールメディアの USB メモリー、USB キーボード、USB マウスを接続
  • インストールメディア以外の USB メモリー、microSD が接続されていない
  • HDMI ディスプレイに接続

確認できたら通電します。

 

■ Joule の BIOS 設定変更

Intel のロゴが表示されたら、すぐに F2 キーを押します。これで BIOS 画面に遷移します。

DSC_0090

[Device Manager]-[System Setup]-[Boot] と進んで、”OS Selection” を “Windows” にします。(デフォルトでは “Linux” が選択されているはず)

DSC_0091

F4 キーで設定を保存すると、自動的に Joule が再起動されます。Intel ロゴでもう一度 F2 キーを押します。

[Select Boot Manager] で “EFI USB Device” を選択します。これでインストールメディアから起動します。

 

■ Windows 10 IoT のインストール

いよいよインストールの最後の手順です。

コマンドプロンプトが自動的に開くので、C ドライブに移動して、ルートにある “JouleInstaller.cmd” を実行します。(先ほどこのファイルをコピーしたはず)

DSC_0092

しばらく時間がかかりますが、バーが 100% まで伸びて、”The operation completed successfully” と表示されればインストール成功です。

引き続きコマンドプロンプトで “wpeutil reboot” と入力して、Joule を再起動します。

 

■ Windows 10 IoT の起動

Joule が再起動されると、Windows 10  IoT が起動します。初回は少し時間がかかりますが、あとは他の Windows 10 IoT デバイスと同様です。

言語、ネットワーク (Wifi) の設定をします。

DSC_0093

 

IoT Dashboard でもちゃんと見えますし、デバイスポータルで設定確認・変更することもできます。
デバイスポータル、Raspberry Pi のものに比べると、ちょっとかっこいいですね。

2016-12-25 16-28-13

2016-12-25 16-29-11

おつかれさまです。以上で、Joule への Windows 10 IoT のインストールは完了です。高性能 Windows 10 IoT デバイスなので、おもしろい使い方をしたいですね。

カテゴリー: Intel Joule, Windows 10 IoT | タグ: , | コメントをどうぞ

Windows 10 IoT Core から IoT Hub にメッセージを送信するアプリをスクラッチで書いてみる

ちょっと思うところがあり、Windows 10 IoT Core から IoT Hub にメッセージを送信するアプリケーションをスクラッチで書いてみます。
(※先日の機械学習の勉強会で、「デバイス側の話も聞きたい」という意見をいただいたので。まあ、過去の勉強会でやった内容ではあるので、その時に参加してもらえれば・・・ということではあるのですが。)

これまで Windows 10 IoT Core のコーディングの話をした際には、IoT キットハンズオンの内容をベースにしてきました。IoT 全体を俯瞰できるようスピードアップするため、Windows 10 IoT 部分の基本的なコーディングが完了した状態の資料です。
ただそれと引き換えに、新規プロジェクトで Windows 10 IoT Core から IoT Hub にメッセージを送信する手順はお話できていませんでした。
IoT Hub の情報って意外と少ない気がするのです・・・。そこで、基本に立ち返ってみます。・・・前置きが長くなりました (汗

 


■ プロジェクト新規作成

プロジェクトテンプレートは、[Windows]-[ユニバーサル] の [空白のアプリ] です。UI を持たないセンサーデバイスの場合は、空白のアプリで問題ありません。

2016-12-23 22-12-43

 

■ IoT 用拡張機能ライブラリの参照を追加

“Windows IoT Extensions for the UWP”の参照を追加します。[Universal Windows]-[拡張] にあります。複数バージョンが見つかるかもしれませんので、どれを参照するかはターゲットの Windows 10 IoT 次第。

2016-12-23 22-15-44

なお今回のアプリはセンサーモジュールを接続していない、環境データの測定などを行わない、単なる「エミュレーター」です。ということで、実は今回に限り IoT Extensions の参照追加は不要です。
なのですが、一般には必須の手順なのでここで紹介しました。

 

■ NuGet パッケージの追加

Windows 10 IoT アプリから Azure IoT Hub にメッセージを送信するために必要な NuGet パッケージは2つ。

  • Microsoft.Azure.Devices.Client
  • Newtonsoft.Json

この2つがあれば、びっくりするくらい簡単に IoT Hub にメッセージを送信できます。

2016-12-23 22-19-572016-12-23 22-20-47

 

■ 送信データの Entity クラスを作成

いよいよお楽しみのコーディング。

まずは送信データのエンティティクラスを作成します。こんな感じ。

namespace IoTHubSendMessageDemo
{
    internal class SensorData
    {
        public string DeviceId { get; set; }
        public double SensorValue { get; set; }
    }
}

 

■ MainPage.xaml.cs の編集

この部分はアプリによって変わる部分だと思いますが、例えば今回は MainPage.xaml の Page_Loaded メソッドで、データ送信クラスを操作してみます。

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace IoTHubSendMessageDemo
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            var device = new SensorDevice();
            await device.Run();
        }
    }
}

 

■ メッセージ送信クラスを作成

IoT Hub にメッセージを送信するクラスです。「本体」の部分です。

メッセージ送信を行うのは、SDK で提供されている DeviceClient です。スタティックな CreateFromConnectionString メソッドを使うのがいいです。必要な情報は IoT Hub への接続文字列ですが、この中には DeviceId も含まれているので、あらかじめデバイスが登録されていることが前提。
ではデバイスの登録はどうするかというと、

  • IoT Dashboard
  • Device Explorer
  • 自作のデバイス管理アプリ(例えば、こんなもの

2016-12-23 22-32-522016-12-24 21-43-24

のいずれかを使います。

DeviceClient が作れたら、メッセージ送信の手順は、

  1. 送信のためのエンティティを作る
  2. エンティティを JSON で永続化
  3. Message クラスを作る(エンティティを永続化したもののバイト配列をコンストラクターに渡す)
  4. DeviceClient の SendMessageAsync メソッドで IoT Hub にメッセージ送信

これだけです。

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 = "SendMsgDevice";

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

        internal async Task Run()
        {
            for (var i = 0; i < 10; i++)
            {
                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(5)).Wait();
            }

            Debug.WriteLine("End of Run Method");
        }
    }
}

IoT Hub にちゃんと届いているのは、Device Explorer で確認できます。

2016-12-23 23-25-41

 

以上で、メッセージ送信は完了です。
データを集めて、集めたデータを活用するには、大量のデータをクラウドに送ることが必要。今回は、そのお話でした。

 

送信するべきデータ(センサーデータ)はどうやって取得するのか、IoT Hub に送ったデータはどうやって活用するのか(Stream Analytics)は、別のテーマなので今回は省略。別に機会にでも(または このあたり を参考に)。

カテゴリー: IoT, Iot Hub, Raspberry Pi, Windows 10 IoT | タグ: , , , | 2件のコメント

Bot Service (preview) で日本語 LUIS を使う

本稿は、Microsoft Cognitive Services & Bot Framework Advent Calendar 2016 に参加しています。

Azure Bot Service が公開されたことで、Bot アプリケーションがとても作りやすくなりました。(現時点では preview)
Bot Service なしの状態だと、Bot Framework + Azure Functions + LUIS アプリケーション をそれぞれ作る必要があったものが、Azure 管理ポータルでワンストップで作れるようになったわけです。

2016-12-18 12-08-502016-12-18 12-21-132016-12-18 12-21-392016-12-18 15-07-12
2016-12-18 12-24-41


「よしよし、簡単にできたぞ」と LUIS で日本語を学習させようとすると、こんな風になります。

2016-12-18 15-06-21

・・・日本語の形態素解析に失敗しています。
Bot Service で LUIS テンプレートを使って作ったアプリケーションは、言語が “English” なので当然のこと。

2016-12-18 14-44-16


これを回避するには、Bot Service のプレビューが取れるのを待つか、または Bot Framework と LUIS とを組み合わせて Azure 上に公開するか、という方法が考えられます。

もう一つ、LUIS の日本語対応のアプリケーションを作る方法があります。

前置きが長くなりましたが、本稿ではその方法を紹介します。
といっても、とても簡単。

  1. 日本語対応の LUIS アプリケーションを作成
    2016-12-18 15-11-462016-12-18 15-36-20
  2. 作成した LUIS アプリの App Id を取得
    LUIS の [App settings] で参照できます。
    2016-12-18 15-52-57
  3. Bot Service の設定画面で取得した LUIS App Id を設定
    Bot Service の [Settings] メニューから [Application settings] を開きます。
    2016-12-18 15-50-372016-12-18 15-51-18ブレードが開くと画面下部に設定値一覧があります。[LuisAppId] に先ほど取得した LUIS の App Id を貼り付けて設定を保存します。
    2016-12-18 15-55-01

これで OK。
まずは Bot Service の開発画面で試してみると、日本語を正しく解析して Intent を返してくれるのがわかります。
2016-12-18 15-59-29

せっかくなので(?)Skype に接続してみると、これも当然ですがちゃんと動作しています。
2016-12-18 16-04-512016-12-18 16-09-09
Screenshot_2016-12-18-21-01-53

簡単に ChatBot を作れるようになりました。ぜひ楽しみながら、どんなふうに使うか、何に使うか、アイデアを出してみてください。


本稿の内容は、12月20日(火) に開催された 「第3回 Cogbot勉強会!~ Cognitive Servicesで音声認識&LT」 の LT でも発表しました。
当日の資料は こちら。

https://docs.com/d/embed/D25192002-3603-4099-2420-000115616833%7eBfe5a7bff-fc39-9c7d-d35f-86e930988702

カテゴリー: Cogbot | タグ: , , | コメントをどうぞ

Azure IoT Hub のデバイス管理機能を利用する

本稿は、Windows 10 IoT Core Advent Calendar 2016 に参加しています。

Azure IoT Hubデバイス管理機能についてです。
「IoT する上で IoT Hub は必須でしょう」ということで、Windows 10 IoT Core の一部とさせていただきます。
(そのわりに、情報が少ないので・・・)


Azure IoT Hub のデバイス管理

IoT Hub の特徴の一つがデバイス管理機能です。システムに接続可能なデバイスを管理する機能です。

2016-12-11 18-24-32

IoT Hub への接続キーをシステム全体で共有しないので、システム全体を稼働させたままで、デバイス1台ごとに切り離しができます。万一デバイスを乗っ取られたり盗難されたりしても、そのデバイスのみ接続を禁止することができます。


デバイス管理可能なツール

IoT Hub のデバイス管理を行うことができるツールは以下があります。

  • Azure 管理ポータル
    デバイス管理ツールとして最初に挙がるのが Azure 管理ポータル です。
    操作性があまりよくないことと、デバイスの削除ができないことなどから、デバイス一覧を見たり、各デバイスの状態を見たりする簡易的なツールであり、積極的に使うことはないと考えていいです。
    ただしデバイスの無効化は可能なので、緊急時の接続禁止などには便利です。2016-12-11 18-24-322016-12-11 18-37-47

  • Device Explorer
    Azure IoT SDKs に含まれる Device Explorer でもデバイス管理が可能です。ただし、SDK に含まれるツールなので、実運用時には適さないかもしれません。
    (開発中には、かなり便利なツールです)
    2016-12-11 18-47-30

  • SDK を利用する独自アプリケーション
    SDKが公開されているわけなので、これを使ったアプリケーションでもデバイス管理が可能です。要件に合わせて柔軟なデバイス管理ができるでしょう。
    Get Started なドキュメントもありますが、端折った部分もあります。ということで、C# でのデバイス管理 API の使い方を紹介します。

IoT Hub デバイス管理アプリケーション (C#)

C# のアプリケーションで、IoT Hub のデバイスを管理するアプリケーションを作ってみます。
今回は WPF で作りましたが、もちろんそれに限定されるものはありません。

ここでは非常に薄いラッパーで、Azure IoT SDKs のデバイス管理機能を見ていきます。

なお、デバイス管理を利用するにあたって、NuGet で “Microsoft.Azure.Devices” をインストールしてください。

2016-12-11 0-39-39

using System.Threading.Tasks;
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Exceptions;

namespace IoTDeviceManager
{
    public class DeviceManager
    {
        private readonly RegistryManager _manager;

        public DeviceManager(string connectionString)
        {
            _manager = RegistryManager.CreateFromConnectionString(connectionString);
        }

        public async Task<Device> CreateDevice(string deviceId)
        {
            try
            {
                return await _manager.AddDeviceAsync(new Device(deviceId));
            }
            catch (DeviceAlreadyExistsException)
            {
                return await GetDevice(deviceId);
            }
        }

        public async Task<Device> GetDevice(string deviceId)
        {
            return await _manager.GetDeviceAsync(deviceId);
        }

        public async Task<Device> SetDeviceStatus(Device device)
        {
            return await _manager.UpdateDeviceAsync(device);
        }

        public async Task<bool> DeleteDevice(string deviceId)
        {
            var device = await GetDevice(deviceId);
            if (device == null)
                return false;

            await _manager.RemoveDeviceAsync(device);
            return true;
        }
    }
}
  • デバイス管理クラスのインスタンス
    IoT Hub のデバイスを管理するには RegistryManager クラスを使います。
    スタティックな CreateFromConnectionString メソッドがあるので、接続文字列を渡してインスタンスを作ります。
  • デバイス情報の取得
    デバイス情報を取得するには GetDeviceAsync メソッドを使います。
    引数は string のデバイス名です。
    取得したデバイス情報(Device クラス)は、Authentication.SymmetricKey.PrimaryKey プロパティ(接続時のプライマリキー)や Status プロパティ(デバイスの有効状態、DeviceStatus.Enabled / DeviceStatus.Disabled を取る)を使ってデバイス固有の情報を得ることができます。
    指定した名前のデバイスが登録されていない場合には、null が返ってきます。(後述の AddDeviceAsync が例外をスローするのとは違っていて面白いです)
  • デバイスの新規登録
    デバイスを新規登録するには、AddDeviceAsync メソッドを使います。
    引数には Device クラスのインスタンス(コンストラクタの引数は string 型でデバイス名)を渡します。GetDeviceAsync では string のデバイス名を引数に取るのとは異なります。
    同じ名前のデバイスがすでに存在する場合には、DeviceAlreadyExistsException がスローされます。前述の GetDeviceAsync メソッドで同名デバイスがないことを確認してから呼び出すのが行儀のいい呼び出し方かもしれませんが、例外に任せるのも “アリ” かもしれません。
  • デバイス情報の更新
    デバイス個別の無効化する(もちろん有効化もできますが)場合は、UpdateDeviceAsync メソッドを使います。
    あらかじめ GetDeviceAsync メソッドでデバイスの情報を取得して Status を変更した上で、UpdateDeviceAsync を呼び出します。
  • デバイスの削除
    登録済みのデバイスが壊れた・盗まれたなどの場合に使うのが、RemoveDeviceAsync メソッドです。
    これも引数は Device 型です。最低限、デバイス名を指定します。

他に複数のデバイス一覧を取得する、GetDevicesAsync メソッドがありますが、最大 1000台までという制限があること、概算の個数を返す(?)ことから、本番では使わないほうがよさそうです。
ではデバイス一覧を欲しい時はどうするかというと、ExportDevicesAsync メソッドを使います。結果は Blob ストレージに出力されます。これについては別の機会にでも。


驚くことではありませんが、IoT Hub で管理できるデバイスは Windows 10 IoT のデバイスに限りません。

mbed でも Arduino でも .NET Micro Framework のデバイスでも、IoT Hub にデータを投げることができるデバイスはすべて管理できます。デバイス側のロジックによらず、接続をコントロールしたり、個別にデバイスを無効化かできたりします。汎用性が高いですね。Azure で IoT をやるなら、デバイスの種類によらず、IoT Hub のデバイス管理機能を使ってみてください。

WPF の簡単なサンプル(デバイス管理の使い方に集中したいため、古き良きコードビハインドな実装です)を用意しました。自身でデバイスを管理する際の参考に。

カテゴリー: IoT, Iot Hub, Windows 10 IoT | タグ: , , | 1件のコメント