スキップしてメイン コンテンツに移動

HTTP REST APIでAzure IoT Hubにメッセージを送信する (C#)

Azure IoT Hubに、HTTP REST APIでメッセージを送る方法です。
Azure IoT Device Client SDKは使いません。

AZURE IOT HUBにRest APIでメッセージを送信する

HTTP RESTでメッセージを送信するまでの流れは、こんな感じになります。

  1. デバイスの登録 (Azureポータルで作業)
  2. SASトークンの作成 (C#)
  3. RESTでメッセージを送信 (C#)

やってみる

デバイスの登録

Azureポータルで、メッセージを送信するデバイスを登録します。

Iot Hubのページから、[IoT devices] -> [Add]を選択
enter image description here

下の画面で、Iotデバイスを登録します。
Device IDは任意の値、認証には Symmetric keyを選択します。
Iotデバイスの登録

デバイスが登録されると、一覧にデバイスが追加されます。
登録後のデバイス一覧

一覧から登録したデバイスを選択して、デバイスの詳細を表示します。
ここに表示される、[Device ID][Primary Key(共有アクセスキー)]を、後から使うのでメモしておきます。

デバイス詳細

SASトークンの作成 (C#)

ここからC#のコードを組んでいきます。

デバイスIDと共有アクセスキーから、SASトークンを生成するメソッドを作ります。
ここで作成するGenerateSasToken()メソッドを、後述するメッセージ送信のサンプルコードから呼びます。

using System;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;

/// <summary>
/// Azure IOT Hub用のSASトークンの作成
/// </summary>
/// <returns>SASトークン</returns>
/// <param name="resourceUri">リソースURL</param>
/// <param name="key">共有アクセスキー</param>
/// <param name="policyName">ポリシー名(今回使用しない)</param>
/// <param name="expiryInSeconds">有効期限(秒)</param>
public static string GenerateSasToken(string resourceUri, string key, string policyName, int expiryInSeconds = 3600) {
    TimeSpan fromEpochStart = DateTime.UtcNow - new DateTime(1970, 1, 1);
    string expiry = Convert.ToString((int)fromEpochStart.TotalSeconds + expiryInSeconds);

    string stringToSign = WebUtility.UrlEncode(resourceUri) + "\n" + expiry;

    HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(key));
    string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    string token = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}", WebUtility.UrlEncode(resourceUri), WebUtility.UrlEncode(signature), expiry);

    if (!String.IsNullOrEmpty(policyName)) {
        token += "&skn=" + policyName;
    }

    return token;
}

RESTでメッセージを送信 (C#)

.NET Framework標準の HttpClientクラスを使って、RESTでメッセージを送信します。
今回は、JSONのデータを送ります。

//(1)環境設定
private const string IOT_HUB_NAME = "<iothubname>.azure-devices.net";
private const string SIGNING_KEY = "<共有アクセスキー>";
private const string DEVICE_ID = "<デバイスID>";
        
public static void Send() {

    //(2)SASトークンを作成する
    var resourceUri = $"{IOT_HUB_NAME}/devices/{DEVICE_ID}";
    var sasToken = GenerateSasToken(resourceUri, SIGNING_KEY, null);

    //(3)URLの組み立て
    var url = $"https://{IOT_HUB_NAME}/devices/{DEVICE_ID}/messages/events?api-version=2018-06-30";
    HttpResponseMessage res = null;
    
    //HTTP RESTでメッセージを送信する
    using (var client = new HttpClient()) {
        var request = new HttpRequestMessage(HttpMethod.Post, url);

        //(4)HTTPヘッダに、SASトークンを設定
        request.Headers.Add("Authorization", sasToken);

        var json = @"{""msg"":""Test Message""}";
        var content = new StringContent(json, Encoding.UTF8, @"application/json");
        request.Content = content;
        res = client.SendAsync(request).Result;

        //メッセージが正常に送信されると、IoT Hubからは、204が返ってくる
        if (res.StatusCode == HttpStatusCode.NoContent) {
            Console.WriteLine("送信しました。");
        }
    }
}

ポイントは以下の通り。

(1)Iot Hub名、デバイスの共有アクセスキーおよび、デバイスIDを指定します。

Iot Hub名は、Azure Iot Hubのトップページから確認できます。
Iot Hub名の確認

デバイスID、共有アクセスキーは、デバイスの詳細ページから確認できます。
デバイス詳細

(2)上で作成したメソッドを使って、SASトークンを作成します。
(3)送信先URLには、デバイスIDを含めます。
(4)HTTPヘッダに、作成したSASトークンを指定します。

メッセージにプロパティを設定するには

REST APIで、メッセージにプロパティ (application property) を指定する場合は、リクエストヘッダに設定します。
ヘッダに設定するプロパティ名には、iothub-app-の接頭辞を付けて設定します。

<サンプルコード>

// "myprop"というプロパティを IotHubに送信する場合
request.Headers.Add("iothub-app-myprop", value);

(おまけ) RESTでメッセージを受信(C#)

IoT Hubからメッセージ通知し、REST APIで受信する例です。
送信の例と同じように、SASトークンを発行してから、APIを叩きます。
メッセージを受信した後に、Iot Hubに完了通知を送って、メッセージを削除します。

public static void Revive() {

    //SASトークンを作成する
    var resourceUri = $"{IOT_HUB_NAME}/devices/{DEVICE_ID}";
    var sasToken = GenerateSasToken(resourceUri, SIGNING_KEY, null);

    //URLの組み立て
    var url = $"https://{IOT_HUB_NAME}/devices/{DEVICE_ID}/messages/deviceBound?api-version=2018-06-30";
    HttpResponseMessage res = null;

    using (var client = new HttpClient()) {
        var request = new HttpRequestMessage(HttpMethod.Get, url);

        //HTTPヘッダに、SASトークンを設定
        request.Headers.Add("Authorization", sasToken);
        res = client.SendAsync(request).Result;

        if (res.StatusCode == HttpStatusCode.OK) {
            Console.WriteLine(res.Content.ReadAsStringAsync().Result);
        } else {
            //通知がない場合
            Console.WriteLine("No Message!");
        }

        //受信したメッセージの完了通知をIoT Hubに送信します。
        //これにより、Iot Hubよりメッセージが削除される模様
        var etag = res.Headers.ETag?.Tag.Replace("\"", string.Empty);
        if (etag != null) {
            var restUriComplete = $"https://{IOT_HUB_NAME}/devices/{DEVICE_ID}/messages/deviceBound/{etag}?api-version=2018-06-30";
            var deleteRequest = new HttpRequestMessage(HttpMethod.Delete, restUriComplete);
            deleteRequest.Headers.Add("Authorization", sasToken);
            var resDelete = client.SendAsync(deleteRequest).Result;
        }
    }
}

上のコードを試す為に、Azureポータルからメッセージを送信してみます。
Iot Hubのデバイス詳細ページから[Message to device]を選択して、メッセージを送信します。
デバイスへメッセージを送信する

実行すると、コンソールにAzureポータルから送信したメッセージが表示されると思います。
コードを実行し、送信されたメッセージがコンソールに表示される

おわりに

<関連記事>

C# (.net) で使える MQTT クライアント (Paho M2Mqtt)

C#で 、MQTTメッセージを送受信するライブラリの、「M2Mqtt」の使い方について、解説しています。
無料のBrokerサーバを使って、簡単にお試しする事が出来ます。

参考

共有アクセスキーの、プライマリ・セカンダリについて

共有アクセスキーには、プライマリとセカンダリの2つがあり、セキュリティの観点からアクセスキーを一定期間でローテーションすることを目的としています。

運用として、アクセスに使うキーをプライマリからセカンダリに変更し、その間にプライマリのキーを再生成してから元に戻す運用を行います。

共有アクセスキーのローテイションは、Azureポータルから行います。
デバイス詳細画面の [Regenerate keys]をクリックして、共有アクセスキーの再生成を行います。
共有アクセスキーの再生成

Azure IoT Hubを生MQTTS(mosquitto)やHTTP RESTで使う方法

https://qiita.com/ma2shita/items/032370350cba282d35ff

Azure IoT Hubを使ってみた

https://qiita.com/linyixian/items/e319c5f63f9e57459ac0

IoT Hub へのアクセスの制御

https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-devguide-security#scope-iot-hub-level-credentials

Azure IoT Device Client SDK

今回は使っていませんが、Azure IoT Device Client SDKは、nuget からインストールできます。

スポンサーリンク
スポンサーリンク
スポンサーリンク

コメント

このブログの人気の投稿

axiosの使い方まとめ (GET/POST/例外処理)

axiosの使い方まとめ (GET/POST/例外処理)最近何かとよく使うJavaScriptでAJAX通信を行うaxiosについて、簡単に使い方をまとめました。GETリクエストをaxiosで送るまずはGETリクエストをaxiosで送る方法です。const res =await axios.get('/users') console.log(res.data)分割代入の記法を使うと、以下のようにも書けますconst{data}=await axios.get('/users') console.log(data)クエリパラメータ (URLパラメータ)を指定クエリパラメータを指定する方法は2つあります。1つ目は、axios.getに指定するURLに直接記述する方法です。axios.get('/user?id=123')2つめは、axios.getの第2引数に、オプション指定する方法です。axios.get('/user',{ params:{ id:123}})POSTリクエストをaxiosで送る次はPOSTリクエストをaxiosで送る方法です。JSON形式でPOSTするJSON形式でPOSTする場合は、axios.postの第2引数に、送信するデータをJavaScriptオブジェクトで指定します。const res =await axios.post('/user',{ id:123, name:'Yamada Tarou'})application/x-www-form-urlencoded形式でPOSTするapplication/x-www-form-urlencoded形式でPOSTする場合は、URLSearchParamsを使います。var params =newURLSearchParams() params.append('id',123) params.append('name','Yamada Tarou')const res =await axios.post('/user', params)axios でファイルをアップロードする画像などのファイルを、axiosでアッ…

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決する

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決するタイトルの通りですが、Windows 8 以降では Windows Form アプリケーションで、コントロールの ImeMode に Katakana や KatakanaHalf を設定しても、カタカナになってくれません。なぜ ImeMode が効かないのか?Windows 8 以降、IME Mode の切り替えは、ユーザー単位で切り替わるようになった為、アプリから IME Mode 制御が出来ないようになりました。
(IME をON にした場合、常に ひらがな モードになます)※ Windows 7までは、IME Modeの切り替えはアプリ単位で行われていた為、問題なくアプリから IME制御が行えました。対処方法Windows 8 以降、IMEの制御は、InputScope クラスの利用が推奨されています。
しかし、InputScope クラスは、WPF、Windows ストアアプリでしか使えない為、Windows Formアプリでは使用できません。
(Windows Form はもう使うな!という事でしょうか (涙) )結論としては、コントールパネルの設定で、IMEの制御をユーザ単位から アプリ単位に変更する事ができます。
これで、Windows Formアプリでも 従来通りIMEの制御を行う事が出来ます。おわりにこの方法だと、アプリをインストールする端末すべてに設定が必要となり、とっても面倒です。。。
しかし、今の所これしか方法がない状態です。
これからは Windows Formではなく、WPFや Windows ストアアプリで作れという事ですかね (^^;)

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]MailKitを使ってメールを送るサンプルコードです。(C#)UTF8/iso-2022-jpのエンコーディング指定、GMail/YahooのSMTPサーバで送るなど、4つのサンプルコードでMailKitの使い方を紹介します。MailKitって何?2017年に.NET標準のSystem.Net.Mail.SmtpClientが廃止予定となり、Microsoftより今後はオープンソースライブラリである、MailKitに置き換えるとアナウンスがありました。既にSmtpClientは非推奨になっており、今後は廃止されていきます。現在、SmtpClientを使用したソースコードには、Visual StudioからMailKitを使うよう警告が出るようになっています。さっそく、MailKitを使ってメールを送信するサンプルコードを作っていきます。UTF8でメールを送信文字エンコーディングを、UTF8でメールを送信するサンプルコードです。
MailKitは、デフォルトの文字エンコーディングがUTF8なっている為、シンプルなコードでメールを送信する事ができます。var host ="<smtp server name>"; var port =25;// or 587using(var smtp =new MailKit.Net.Smtp.SmtpClient()){//SMTPサーバに接続する smtp.Connect(host, port, MailKit.Security.SecureSocketOptions.Auto);//認証が必要な場合は、以下のコメントを解除//smtp.Authenticate("<id>", "<password>");//送信するメールを作成する var mail =new MimeKit.MimeMessage(); var builder =new MimeKit.BodyBuilder(); mail.From.Add(new MimeKit.MailboxAddress("",&quo…