銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

RPi2 で Windows IoT (5) Azure IoT Hub その2 メッセージを受け取る

前回の反対にIoT Hubからメッセージを受信する方法です。ドキュメントにもあるのですが、IoT Hubではメッセージを最低1回は受信するように保証(到達保証)する ことができますが、そのためにはデバイス側で受け取ったという通知をIoTHubに返してあげる必要があります。

https://acomdpsstorage.blob.core.windows.net/dpsmedia-prod/azure.microsoft.com/ja-jp/documentation/articles/iot-hub-devguide/20151211010255/lifecycle.png

というわけでコードです。前回のコードに追加して、Gridがロードされた時からメッセージの受信を待機して、受信したらテキストボックスに表示してまた待機するという繰り返しです。

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
    ReceiveDataFromAzure()
        .ContinueWith(t => Debug.WriteLine(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
}

public async Task ReceiveDataFromAzure()
{
    var deviceClient = DeviceClient.CreateFromConnectionString("<ConnectionString>", TransportType.Http1);
    while (true)
    {
        var receivedMessage = await deviceClient.ReceiveAsync();

        if (receivedMessage != null)
        {
            var messageData = Encoding.UTF8.GetString(receivedMessage.GetBytes());
            textBox1.Text = messageData;
            await deviceClient.CompleteAsync(receivedMessage);
        }
    }
}

なお、インストーラーで配布されているDeviceExploreだとマルチバイト文字が正しく送信できません。理由はDevice Explorerで入力した文字列に対してASCIIでバイト配列を取得しているためです... 日本語を送信したい場合は、ソースコードを持ってきてこの部分をUTF8にしてビルドすればOKです。IoT Hub側のやりとりはbyte配列なので特に制約があるわけではないと思うのですが。

azure-iot-sdks/MainForm.cs at 2015-11-30 · Azure/azure-iot-sdks · GitHub

さて、DeviceClientを生成するときの第2引数にHttp1というのを渡しています。その名のとおり、HTTP/1 をプロトコルに選択しているのですが、送信以上にサーバープッシュができないためポーリングせざるをえない受信で負荷がかかるとドキュメントにあります。本番環境では25分に1回未満とあるのでなかなかつらいところでしょう。

azure.microsoft.com

じゃあ、そのドキュメントにあるAMQPにすればいいのでは?となるのですが、残念ながらUWPでは未実装でNotImplementedExceptionが飛んできます。

azure-iot-sdks/DeviceClient.cs at 2015-11-30 · Azure/azure-iot-sdks · GitHub

UWPでAMQPで送信するライブラリもあるみたいですが、Backlogにも載っているようです。

github.com

動きがあれば試してみようと思います。