Azure IoT HUBの接続文字列(SAS入り)を生成 (C#)
Azure IoT HUBに独自のデバイスを接続したいけど、Device ExplorerやVSから接続文字列を生成する方法は、サンプル的な確認では良いけど運用には向きません(SASの有効期限の問題があるからです)。MicrosoftのSDKを使うにしても「64KByte以上」のRAMを確保する必要があり、組み込み向けの小さなマイコンでは荷が重い。SDKから必要なもの以外を削ればいいという話もありますが、やりたいことは IoT HUBとつなぐことではなく、IoT HUBを利用して「目的を達成したい」です。なので、手段に過ぎない IoT HUBに「つなぐためだけ」に大きな労力を使うのは勿体ない。
色々なコマンド ベースのサンプルや実行モジュールがネット上では見受けられますが、いずれにしてもDevice ExplorerやVSから接続文字列を生成する方法と大差がありません。これでは、SASの有効期限の問題をクリアでません。
< 一つの解決方法 >
SASの有効期限内であれば、デバイス接続時に新たな接続文字列をデバイスに渡す(Azure IoT HUBのCloud to Deviceを利用)。もし、SASの有効期限が切れている場合は、USBかBLE経由でデバイス内の接続文字列を更新。
この方法で行う場合は、接続文字列の生成をAzure Functions、PC/Mac/モバイル デバイスのプログラムで行うことになります。これなら非力なマイコンで無理やり生成する必要はなくなります。
接続文字列の生成自体は簡単で、以下のようなメソッドを作成して呼び出すだけです。
/// <summary>
/// IoT HUB接続文字列の生成
/// </summary>
/// <param name=”iotHubHostName”>IoT HUBのホスト名</param>
/// <param name=”deviceID”>デバイスID</param>
/// <param name=”primarykey”>デバイスのプライマリー キー</param>
/// <param name=”ttlValue”>トークンの有効期限(単位=日)</param>
/// <returns>接続文字列</returns>
private String GenerateConnectionStrings(String iotHubHostName, String deviceID, String primarykey, Decimal ttlValue)
{
var sasBuilder = new SharedAccessSignatureBuilder()
{
Key = primarykey,
Target = String.Format(“{0}/devices/{1}”, iotHubHostName, WebUtility.UrlEncode(deviceID)),
TimeToLive = TimeSpan.FromDays(Convert.ToDouble(ttlValue))
};
String result = String.Format(“HostName={0};DeviceId={1};SharedAccessSignature={2}”, iotHubHostName, deviceID, sasBuilder.ToSignature());
return result;
}
PC上で以下のようなコードで、生成した接続文字列が正しいかを確認することができます(Azure IoT HUBにMQTTでJSONを投げています)。
String IoTHubHostName = “{IoT HUBのホスト名}”;
String DeviceID = “{デバイスID}”;
String Primarykey = “{主キー}”;
private async void ButtonTest_ClickAsync(object sender, EventArgs e)
{
try
{
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(
GenerateConnectionStrings(IoTHubHostName, DeviceID, Primarykey, 1),
Microsoft.Azure.Devices.Client.TransportType.Mqtt))
{
// 適当なメッセージを作成
String messageBody = JsonSerializer.Serialize(
new
{
temperature = 12.5,
humidity = 36.9,
});
var message = new Microsoft.Azure.Devices.Client.Message(Encoding.ASCII.GetBytes(messageBody))
{
ContentType = “application/json”,
ContentEncoding = “utf-8”,
};
// オープン
await deviceClient.OpenAsync();
// 送る
await deviceClient.SendEventAsync(message);
// クローズ
await deviceClient.CloseAsync();
}
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, “ERROR”);
}
}