Azure IoTHubにMQTTでつないでみる（UWP編）

##動作報告
なかなか原因がわからなかったのですが、SASTokenを再設定すると動作しました。
それ以外は特に変更していません。
(2016/11/24)

##注意
現在以下のサンプルは動作しません。
原因は不明ですが、接続はできるけどもデータの送受信ができていません。プログラム側ではエラーが発生しませんが、送受信とも反応がない状態です。
M2MQTTライブラリは更新されていないので、IoTHub側の問題（MQTTプロトコルゲートウェイ？）かと思います。
現在調査中ですが、解決にはもうしばらく時間がかかりそうです。
(2016/10/12 追記)
***

　[前回](http://qiita.com/linyixian/items/0795ff2ab038ea0a3517)のサンプルプログラムはDeviceClientを使って作りました。
ただ、現在のDeviceClientではUWP上でMQTTプロトコルを選択できません。ついでにAMQPも選択できないのでWindows10IoTCoreではHTTPSでの接続しか選べない状況です。
　Azure IoTHubはDeviceClientを使っての接続以外にMQTTクライアント（AMQPクライアントも）で直接接続することもできるのでUWPでも使えるM2MQTTライブラリを利用してみました。

##準備
1.Azure IoTHubを作成（初めての人は[こちら](http://qiita.com/linyixian/items/e319c5f63f9e57459ac0)を参照）
2.VisualStudio2015
3.Windows10搭載PC（Windows10IoTCore上で試すならWindows8.1でも可）
4.VisualStudioで空のアプリ（ユニバーサルWindows）を選んでプロジェクトを作成します。
5.DeviceExplorerのインストール（まだの人は[こちら](http://qiita.com/linyixian/items/e319c5f63f9e57459ac0)を参照）

##プログラム
画面用

```XAML:MainPage.xaml
<Page
    x:Class="IoTHub_MQTT_UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:IoTHub_MQTT_UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBox x:Name="tBox1" HorizontalAlignment="Left" Margin="10,43,0,0" TextWrapping="Wrap" Text="Hello IoTHub" VerticalAlignment="Top" Width="780"/>
        <Button x:Name="btn_send" Content="Send Message" HorizontalAlignment="Left" Margin="10,90,0,0" VerticalAlignment="Top" Click="btn_send_Click"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,160,0,0" TextWrapping="Wrap" Text="Racieved Message" VerticalAlignment="Top"/>
        <TextBlock x:Name="tBlock1" HorizontalAlignment="Left" Margin="10,185,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="780" FontSize="21.333"/>
    </Grid>
</Page>
```

プログラム本体

```C#:MainPage.xaml.cs
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.Diagnostics;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 を参照してください

namespace IoTHub_MQTT_UWP
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        //クライアント
        private static MqttClient Client;
        
        //IoTHub名（URL)
        private const string IoTHubName = "[IoTHub Address]";
        //デバイスID
        private const string DeviceId = "[DeviceId]";
        //MQTTブローカーアドレス
        private string UserName = string.Format("{0}/{1}", IoTHubName, DeviceId);

        //アクセストークン
        private const string SASToken = "[SAS Token]";

        private static string TopicDevice2Service;
        private static string TopicService2Device;

        private const int MqttPort = 8883;

        /// <summary>
        /// 
        /// </summary>
        public MainPage()
        {
            this.InitializeComponent();

            Loaded += MainPage_Loaded;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                Client = new MqttClient(IoTHubName, MqttPort, true, MqttSslProtocols.TLSv1_0);
                //接続
                Client.Connect(DeviceId, UserName, SASToken);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error in sample: {0}", ex.Message);
            }

            //受信イベントの登録
            Client.MqttMsgPublishReceived += this.onReceive;

            //MQTT Topic
            TopicService2Device = string.Format("devices/{0}/messages/devicebound/#", DeviceId);

            //受信するトピックの登録
            Client.Subscribe(new[] { TopicService2Device }, new[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void onReceive(object sender,MqttMsgPublishEventArgs e)
        {
            //受信イベントからメッセージの取り出し
            string msg = Encoding.UTF8.GetString(e.Message);

            //メッセージをUIスレッドに表示
            var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                tBlock1.Text = msg;
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_send_Click(object sender, RoutedEventArgs e)
        {
            //メッセージの送信先
            TopicDevice2Service = string.Format("devices/{0}/messages/events", DeviceId);

            string Data;

            Data = tBox1.Text;
            //メッセージの送信（Publish）
            Client.Publish(TopicDevice2Service, Encoding.UTF8.GetBytes(Data));
        }
    }
}

```

・あらかじめNugetパッケージマネージャーから「M2MQTT」をインストールしておきます。
・22行目の[IoTHub Address]を「IoTHub名.azure-devices.net」に置き換えます。
・24行目の[DeviceId]を自分がつけたDeviceIdに置き換えます。
・DeviceExplorerを立ち上げて、「Generate SAS」ボタンをクリックすると下にSAS Tokenが表示されます。表示された内容をコピーして29行目の[SAS Token]と置き換えます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/62606/a12e79ba-8b98-2cb5-c4d0-6bf5da54d773.png)

##実行
DeviceExplorerを立ち上げたまま、プログラムを実行します。

###送信の確認
DeviceExplorerをDataタブに切り替えて「Monitor」ボタンをクリックします。
![D2C.PNG](https://qiita-image-store.s3.amazonaws.com/0/62606/5be33eaf-3bae-de27-e088-1a273b632b29.png)

プログラムのテキストボックスに好きな文字を入力して、「Send Message」ボタンをクリックすると、DeviceExplorerのEvent Hub Dataに送信した文字が表示されます。（それ以外にもPropertie等も表示されます。これは設定で含まないようにできるんでしょうか?　Dataは問題なく送れているのでそのままにしています。）
![UWP.PNG](https://qiita-image-store.s3.amazonaws.com/0/62606/5a831f0e-3121-bc86-cf4d-8b1d638e4a84.png)

###受信の確認
DeviceExplorerをMessage To Deviceタブを選択します。
![C2D.PNG](https://qiita-image-store.s3.amazonaws.com/0/62606/1811c958-31c4-9ccc-2299-1ecffe2ce268.png)
Message:に送信したい文字を入力します。（日本語は不可。DeviceExplorerが未対応）
「Send」ボタンをクリックすると少し間が空いてからOutputにDeviceに送信した内容が表示されます。プログラムのRecieved Messageの下に送信した文字が表示されたら受信に成功しています。
![UWP1.png](https://qiita-image-store.s3.amazonaws.com/0/62606/6282847f-df45-5cec-bc40-214a616930bc.png)


##最後に
今回はDeviceClientを利用せずにAzure IoTHubに接続してみました。
ArduinoなどでもMQTTクライアントが利用できる環境であれば、Azure IoTHubに接続できると思います。
機会があれば、サンプルプログラムを書いてみたいと思います。