.NET SDK を使用して AMQP クライアントを Alibaba Cloud IoT Platform に接続し、サーバーサイドサブスクリプションのメッセージを受信します。
前提条件
トピックのメッセージをサブスクライブするコンシューマーグループの ID を取得します。
DEFAULT_GROUP という名前のデフォルトのコンシューマーグループを使用するか、IoT Platform コンソールでコンシューマーグループを作成できます。詳細については、「コンシューマーグループを管理する」をご参照ください。
コンシューマーグループを使用して、トピックのメッセージをサブスクライブできます。詳細については、「AMQP サーバー側サブスクリプションを設定する」をご参照ください。
開発環境
次の表に、サポートされているフレームワークとバージョンを示します。
|
フレームワーク |
対応バージョン |
|
.NET Framework |
3.5、4.0、4.5 以降 |
|
.NET Micro Framework |
4.2 以降 |
|
.NET nanoFramework |
1.0 以降 |
|
.NET Compact Framework |
3.9 以降 |
|
.NET Core on Windows 10 and Ubuntu 14.04 |
1.0 以降 |
|
Mono |
4.2.1 以降 |
SDK のダウンロード
AMQP.Net Lite ライブラリを推奨します。ライブラリのダウンロードと手順の確認については、AMQP.Net Lite をご参照ください。
依存関係の追加
次の依存関係を packages.config ファイルに追加します。
<packages>
<package id="AMQPNetLite" version="2.2.0" targetFramework="net47" />
</packages>
サンプルコード
using System;
using System.Text;
using Amqp;
using Amqp.Sasl;
using Amqp.Framing;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Security.Cryptography;
namespace amqp
{
class MainClass
{
// エンドポイント。詳細については、「AMQP クライアントの IoT Platform への接続」をご参照ください。
static string Host = "${YourHost}";
static int Port = 5671;
// AccessKey ID と AccessKey Secret をコードにハードコーディングすると、セキュリティリスクが生じます。認証情報は環境変数に保存することを推奨します。この例では、環境変数から AccessKey ID と AccessKey Secret を取得する方法を示します。
static string AccessKey = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_ID");
static string AccessSecret = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
static string consumerGroupId = "${YourConsumerGroupId}";
static string clientId = "${YourClientId}";
// インスタンス ID。
static string iotInstanceId = "${YourIotInstanceId}";
static int Count = 0;
static int IntervalTime = 10000;
static Address address;
public static void Main(string[] args)
{
long timestamp = GetCurrentMilliseconds();
string param = "authId=" + AccessKey + "×tamp=" + timestamp;
// userName パラメーターの作成方法については、「AMQP クライアントの IoT Platform への接続」をご参照ください。
string userName = clientId + "|authMode=aksign,signMethod=hmacmd5,consumerGroupId=" + consumerGroupId
+ ",iotInstanceId=" + iotInstanceId + ",authId=" + AccessKey + ",timestamp=" + timestamp + "|";
// 署名を計算します。password の作成方法については、「AMQP クライアントの IoT Platform への接続」をご参照ください。
string password = doSign(param, AccessSecret, "HmacMD5");
DoConnectAmqp(userName, password);
ManualResetEvent resetEvent = new ManualResetEvent(false);
resetEvent.WaitOne();
}
static void DoConnectAmqp(string userName, string password)
{
address = new Address(Host, Port, userName, password);
// 接続を作成します。
ConnectionFactory cf = new ConnectionFactory();
// オプション:ローカル TLS 証明書を使用します。
//cf.SSL.ClientCertificates.Add(GetCert());
//cf.SSL.RemoteCertificateValidationCallback = ValidateServerCertificate;
cf.SASL.Profile = SaslProfile.External;
cf.AMQP.IdleTimeout = 120000;
// cf.AMQP.ContainerId および cf.AMQP.HostName パラメーターをカスタマイズします。
cf.AMQP.ContainerId = "client.1.2";
cf.AMQP.HostName = "contoso.com";
cf.AMQP.MaxFrameSize = 8 * 1024;
var connection = cf.CreateAsync(address).Result;
// 接続切断を処理するコールバックを登録します。
connection.AddClosedCallback(ConnClosed);
// メッセージを受信します。
DoReceive(connection);
}
static void DoReceive(Connection connection)
{
// セッションを作成します。
var session = new Session(connection);
// レシーバーリンクを作成してメッセージを受信します。
var receiver = new ReceiverLink(session, "queueName", null);
receiver.Start(20, (link, message) =>
{
object messageId = message.ApplicationProperties["messageId"];
object topic = message.ApplicationProperties["topic"];
string body = Encoding.UTF8.GetString((Byte[])message.Body);
// 注:このコールバックでは、長時間実行されるタスクを避けてください。ビジネスロジックを実行する必要がある場合は、別のスレッドで実行します。これにより、コンシューマーがブロックされ、メッセージが再配信されるのを防ぐことができます。
Console.WriteLine("receive message, topic=" + topic + ", messageId=" + messageId + ", body=" + body);
// メッセージを承認します。
link.Accept(message);
});
}
// 接続エラーが発生した場合、クライアントは再接続を試みます。
// これは単純な再試行の例です。本番環境では、エクスポネンシャルバックオフなど、より堅牢な再接続戦略の実装を検討してください。
static void ConnClosed(IAmqpObject _, Error e)
{
Console.WriteLine("An error occurred: " + e);
if(Count < 3)
{
Count += 1;
Thread.Sleep(IntervalTime * Count);
}
else
{
Thread.Sleep(120000);
}
// 再接続します。
DoConnectAmqp(address.User, address.Password);
}
static X509Certificate GetCert()
{
string certPath = Environment.CurrentDirectory + "/root.crt";
X509Certificate crt = new X509Certificate(certPath);
return crt;
}
static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
static long GetCurrentMilliseconds()
{
DateTime dt1970 = new DateTime(1970, 1, 1);
DateTime current = DateTime.Now;
return (long)(current - dt1970).TotalMilliseconds;
}
// 署名メソッド。サポートされているアルゴリズム: hmacmd5、hmacsha1、hmacsha256。
static string doSign(string param, string accessSecret, string signMethod)
{
// 署名メソッドとして HmacMD5 を使用します。
byte[] key = Encoding.UTF8.GetBytes(accessSecret);
byte[] signContent = Encoding.UTF8.GetBytes(param);
var hmac = new HMACMD5(key);
byte[] hashBytes = hmac.ComputeHash(signContent);
return Convert.ToBase64String(hashBytes);
}
}
}
上記のコードのパラメーターを、次の表の説明に従って設定します。詳細については、「AMQP クライアントの IoT Platform への接続」をご参照ください。
有効なパラメーター値を指定してください。そうでない場合、AMQP クライアントは IoT Platform への接続に失敗します。
|
パラメーター |
説明 |
|
Host |
AMQP 接続エンドポイントです。
|
|
AccessKey |
IoT Platform コンソールにログインし、右上のプロフィールアイコンにカーソルを合わせ、[AccessKey の管理] をクリックして AccessKey ID と AccessKey Secret を取得します。 説明
RAM ユーザーを使用する場合、AliyunIOTFullAccess ポリシーを RAM ユーザーにアタッチして、IoT Platform リソースを管理する権限を付与する必要があります。そうでない場合、接続は失敗します。詳細については、「RAM ユーザーとして IoT Platform にアクセスする」をご参照ください。 |
|
AccessSecret |
|
|
consumerGroupId |
IoT Platform インスタンスのコンシューマーグループの ID。 コンシューマーグループの ID を表示するには、次の手順を実行します。IoT Platform コンソールにログインし、管理するインスタンスのカードをクリックします。左側のナビゲーションウィンドウで、 を選択します。コンシューマーグループの ID は、[コンシューマーグループ] タブに表示されます。 |
|
iotInstanceId |
インスタンス ID です。この値は、IoT Platform コンソール の [概要] タブで確認できます。
|
|
clientId |
クライアントの ID。カスタム ID を指定する必要があります。 ID は 1 ~ 64 文字の長さである必要があります。クライアントが実行されているサーバーの UUID、MAC アドレス、IP アドレスなど、一意の識別子をクライアント ID として使用することをお勧めします。 AMQP クライアントが IoT Platform に接続して起動した後、次の手順を実行してクライアントの詳細を表示します。IoT Platform コンソールにログインし、管理する インスタンス のカードをクリックします。左側のナビゲーションウィンドウで、 を選択します。[コンシューマーグループ] タブで、管理するコンシューマーグループを見つけ、[操作] 列の [表示] をクリックします。各クライアントの ID は、[コンシューマーグループステータス] タブに表示されます。クライアント ID を使用して、クライアントを簡単に識別できます。 |
実行結果の例
-
成功: 次の出力は、接続とメッセージの受信が成功したことを示します。
receive message, topic=/xxx/xxx/thing/event/property/post, messageId=xxx, body={"deviceType":"xxx","iotId":"xxx","requestId":"xxx","checkFailedData":{},"productKey":"xxx"} receive message, topic=/xxx/xxx/thing/event/property/post, messageId=xxx, body={"deviceType":"xxx","iotId":"xxx","requestId":"xxx","checkFailedData":{},"productKey":"xxx"} receive message, topic=/xxx/xxx/thing/event/property/post, messageId=xxx, body={"deviceType":"xxx","iotId":"xxx","requestId":"xxx","checkFailedData":{},"productKey":"xxx"}パラメーター
例
説明
topic
/***********/******/thing/event/property/post
デバイスプロパティを送信するためのトピックです。
messageId
2**************7
メッセージ ID です。
body
{"deviceType":"CustomCategory","iotId":"4EwuVV*","requestId":"161268","checkFailedData":{},"productKey":"g4**S","gmtCreate":1612682173249,"deviceName":"Esensor","items":{"temperature":{"value":-1,"time":1612682173247},"humidity":{"value":74,"time":1612682173247}}}
メッセージ本文です。
-
失敗: 次の出力は、接続に失敗したことを示します。
Thread xxx has exited with code 0 (0x0). Exception thrown: xxx (in xxx L) An unhandled exception of type 'Sys xxx n' occurred in m xxx 11 One or more errors occurred.
関連情報
サーバー側サブスクリプション機能に関連するエラーコードの詳細については、「IoT Platform ログ」トピックのメッセージに関連するエラーコードセクションをご参照ください。