デバイス ツインを使ってみる
Azure IoT Hub デバイス SDK とサービス SDK を使用して、一般的なデバイス ツイン タスクを処理するアプリケーションを開発します。 デバイス ツインは、デバイスに関する情報 (メタデータ、構成、状態など) を格納する JSON ドキュメントです。 IoT Hub は、IoT Hub に接続する各デバイスにデバイス ツインを保持します。
デバイス ツインを使用すると、次のことができます。
- ソリューション バックエンドからデバイス メタデータを格納する
- デバイス アプリで利用できる機能や状態 (たとえば、使用される接続方法) などの現在の状態に関する情報をレポートする
- デバイス アプリとバックエンド アプリの間で実行時間の長いワークフロー (ファームウェアや構成の更新など) の状態を同期する
- デバイス メタデータ、構成、または状態のクエリを実行する
デバイス ツインを使用するタイミングなど、デバイス ツインの詳細については、「IoT Hub のデバイス ツインの理解と使用」を参照してください。
Note
この記事で説明されている機能は、Standard レベルの IoT Hub でのみ使用できます。 Basic および Standard または Free レベルの IoT Hub の詳細については、ソリューションに適した IoT Hub のレベルの選択に関するページを参照してください。
この記事では、次の 2 種類のアプリケーションを開発する方法について説明します。
- デバイス アプリは、必要なプロパティを更新する要求を処理し、報告されたプロパティへの変更を応答として返すことができます。
- サービス アプリは、デバイス ツイン タグを更新し、新しい必要なプロパティを設定し、デバイス ツインの値に基づいてデバイスのクエリを実行できます。
Note
この記事は、この記事内から参照される Azure IoT SDK サンプルを補完するためのものです。 SDK ツールを使用して、デバイス アプリケーションとバックエンド アプリケーションの両方を構築できます。
前提条件
IoT ハブ SDK の一部の呼び出しでは、IoT Hub のプライマリ接続文字列が必要であるため、接続文字列を記録しておきます。
登録済みのデバイス。 SDK の一部の呼び出しでは、デバイスのプライマリ接続文字列が必要であるため、接続文字列を記録しておきます。
IoT Hub サービスの接続文字列
この記事では、デバイス ツインに必要なプロパティを追加した後、ID レジストリに対してクエリを実行し、適切に更新された報告されるプロパティを持つデバイスをすべて検索するバックエンド サービスを作成します。 そのサービスには、必要なデバイス ツインのプロパティを変更するためのサービス接続アクセス許可と、ID レジストリに対してクエリを実行するためのレジストリ読み取りアクセス許可が必要となります。 その 2 つのアクセス許可だけを含んだ既定の共有アクセス ポリシーは存在しないため、共有アクセス ポリシーを独自に作成する必要があります。
サービス接続とレジストリ読み取りのアクセス許可を付与する共有アクセス ポリシーを作成し、そのポリシーの接続文字列を取得するには、次の手順を実行します。
Azure portal で、[リソース グループ] を選択します。 ハブが配置されているリソース グループを選択し、リソースの一覧からハブを選択します。
ハブの左側のウィンドウで、 [共有アクセス ポリシー] を選択します。
ポリシー一覧の上にある最初のメニューから、[共有アクセス ポリシーの追加] を選びます。
右側の [共有アクセス ポリシーの追加] ウィンドウで、"serviceAndRegistryRead" などのポリシーのわかりやすい名前を入力します。 [アクセス許可] で [レジストリ読み取り] と [サービス接続] を選び、[追加] を選びます。
ポリシーの一覧から、新しいポリシーを選択します。
[プライマリ接続文字列] のコピー アイコンを選び、その値を保存します。
IoT Hub の共有アクセス ポリシーとアクセス許可の詳細については、「Shared Access Signature を使用して IoT Hub へのアクセスを制御する」を参照してください。
アプリケーションが MQTT プロトコルを使用している場合は、必ずファイアウォールのポート 8883 を開きます。 MQTT プロトコルはポート 8883 経由で通信します。 このポートは、企業や教育用のネットワーク環境によってはブロックされている場合があります。 この問題の詳細と対処方法については、「IoT Hub への接続 (MQTT)」を参照してください。
言語 SDK の要件:
- .NET SDK - Visual Studio が必要です。
- Python SDK - Python バージョン 3.7 以降をお勧めします。 必ず、セットアップに必要な 32 ビットまたは 64 ビットのインストールを使用してください。 インストール中に求められた場合は、プラットフォーム固有の環境変数に Python を追加します。
- Java - Java SE Development Kit 8 が必要です。 必ず「長期サポート」の「Java 8」を選択して JDK 8 のダウンロードに移動します。
- Node.js - Node.js バージョン 10.0.x 以降が必要です。
概要
この記事では、Azure IoT SDK for .NET を使用して、デバイス ツイン用のデバイスおよびバックエンド サービス アプリケーション コードを作成する方法について説明します。
デバイス アプリケーションを作成する
デバイス アプリケーションは、ツインの報告されたプロパティの読み取りと書き込みを行うことができます。また、バックエンド アプリケーションまたは IoT Hub によって設定された必要なツインのプロパティの変更について通知を受け取ることができます。
このセクションでは、デバイス アプリケーション コードを使用して次のことを行う方法について説明します。
- デバイス ツインを取得し、報告されたプロパティを確認する
- 報告されたデバイス ツインのプロパティを更新する
- 必要なプロパティ更新コールバック ハンドラーを作成する
デバイス NuGet パッケージを追加する
C# で記述されたデバイス クライアント アプリケーションには、Microsoft.Azure.Devices.Client NuGet パッケージが必要です。
デバイスへの接続
DeviceClient クラスは、デバイスからデバイス ツインとやりとりするために必要なすべてのメソッドを公開しています。
CreateFromConnectionString メソッドと共にデバイス接続文字列と接続トランスポート プロトコルを使用してデバイスに接続します。
CreateFromConnectionString
TransportType トランスポート プロトコル パラメーターは、次のトランスポート プロトコルをサポートしています。
Mqtt
Mqtt_WebSocket_Only
Mqtt_Tcp_Only
Amqp
Amqp_WebSocket_Only
Amqp_Tcp_Only
Http1
プロトコルは、デバイス ツインの更新ではサポートされていません。
この例では、Mqtt
トランスポート プロトコルを使用してデバイスに接続します。
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;
using Newtonsoft.Json;
static string DeviceConnectionString = "{IoT hub device connection string}";
static _deviceClient = null;
_deviceClient = DeviceClient.CreateFromConnectionString(DeviceConnectionString,
TransportType.Mqtt);
デバイス ツインを取得し、プロパティを確認する
GetTwinAsync を呼び出して、現在のデバイス ツインのプロパティを取得します。 Properties
、Status
、Tags
、Version
など、Twin
JSON データの特定の領域にアクセスするために使用できる Twin オブジェクトのプロパティは多数あります。
この例では、デバイス ツインのプロパティを取得し、ツインの値を JSON 形式で出力します。
Console.WriteLine("Retrieving twin...");
Twin twin = await _deviceClient.GetTwinAsync();
Console.WriteLine("\tInitial twin value received:");
Console.WriteLine($"\t{twin.ToJson()}");
報告されたデバイス ツインのプロパティを更新する
ツインの報告されたプロパティを更新するには:
- 報告されたプロパティの更新用に TwinCollection オブジェクトを作成します
TwinCollection
オブジェクト内の報告されたプロパティを 1 つ以上更新します- UpdateReportedPropertiesAsync を使用して、報告されたプロパティの変更を IoT Hub サービスにプッシュします
次に例を示します。
try
{
Console.WriteLine("Sending sample start time as reported property");
TwinCollection reportedProperties = new TwinCollection();
reportedProperties["DateTimeLastAppLaunch"] = DateTime.UtcNow;
await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("Error in sample: {0}", ex.Message);
}
必要なプロパティ更新コールバック ハンドラーを作成する
コールバック ハンドラー メソッド名を SetDesiredPropertyUpdateCallbackAsync に渡して、デバイス ツインで必要なプロパティが変更されたときに実行される必要なプロパティ更新コールバック ハンドラーを作成します。
たとえば、この呼び出しを使用して、必要なプロパティが変更されるたびに、OnDesiredPropertyChangedAsync
というメソッドに通知するようにシステムを設定します。
await _deviceClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChangedAsync, null);
ツインのプロパティは、TwinCollection としてコールバック メソッドに渡され、KeyValuePair
構造体として調べることができます。
この例では、必要なプロパティの更新を TwinCollection
として受け取り、ループ処理して KeyValuePair
コレクションの更新を出力します。 KeyValuePair
コレクションをループ処理した後、コードで UpdateReportedPropertiesAsync
を呼び出して、報告された DateTimeLastDesiredPropertyChangeReceived
プロパティを更新し、最終更新時刻を最新の状態に保ちます。
private async Task OnDesiredPropertyChangedAsync(TwinCollection desiredProperties, object userContext)
{
var reportedProperties = new TwinCollection();
Console.WriteLine("\tDesired properties requested:");
Console.WriteLine($"\t{desiredProperties.ToJson()}");
// For the purpose of this sample, we'll blindly accept all twin property write requests.
foreach (KeyValuePair<string, object> desiredProperty in desiredProperties)
{
Console.WriteLine($"Setting {desiredProperty.Key} to {desiredProperty.Value}.");
reportedProperties[desiredProperty.Key] = desiredProperty.Value;
}
Console.WriteLine("\tAlso setting current time as reported property");
reportedProperties["DateTimeLastDesiredPropertyChangeReceived"] = DateTime.UtcNow;
await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
}
SDK デバイスのサンプル
Azure IoT SDK for .NET には、デバイス ツイン タスクを処理するデバイス アプリの動作するサンプルが用意されています。 詳細については、TwinSample のページを参照してください。
バックエンド アプリケーションを作成する
バックエンド アプリケーション:
- IoT Hub 経由でデバイスに接続する
- デバイスの報告されたプロパティと必要なプロパティを読み取り、デバイスの必要なプロパティを書き込み、デバイス クエリを実行することができます
RegistryManager クラスは、サービスからデバイス ツインと対話するバックエンド アプリケーションを作成するために必要なすべてのメソッドを公開しています。
このセクションでは、次のことを行うバックエンド アプリケーション コードを作成する方法について説明します。
- デバイス ツイン フィールドの読み取りと更新
- デバイス ツイン クエリを作成する
サービス NuGet パッケージを追加する
バックエンド サービス アプリケーションには、Microsoft.Azure.Devices NuGet パッケージが必要です。
IoT Hub に接続する
CreateFromConnectionString を使用して、バックエンド アプリケーションをデバイスに接続します。 パラメーターとして、「前提条件」セクションで作成した IoT Hub サービス接続文字列を指定します。
using Microsoft.Azure.Devices;
static RegistryManager registryManager;
static string connectionString = "{IoT hub service connection string}";
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
デバイス ツイン フィールドの読み取りと更新
GetTwinAsync を呼び出すことで、現在のデバイス ツイン フィールドを Twin オブジェクトに取得できます。
Twin
クラスには、デバイス ツインの各セクションに対応するプロパティが含まれています。 デバイス ツイン フィールドを表示および更新するには、Twin
クラスのプロパティを使用します。 UpdateTwinAsync
を使用してデバイスに更新を書き込む前に、Twin
オブジェクトのプロパティを使用して複数のツイン フィールドを更新できます。
ツイン フィールドを更新した後、UpdateTwinAsync を呼び出して、Twin
オブジェクト フィールドの更新をデバイスに書き込みます。 try
と catch
のロジックをエラー ハンドラーと組み合わせて使用し、正しくない形式のパッチ エラーを UpdateTwinAsync
からキャッチします。
デバイス ツイン タグの読み取りと更新
デバイス ツインの Tags プロパティを使用して、デバイス タグ情報の読み取りと書き込みを行います。
ツイン オブジェクトを使用してタグを更新する
この例では、location
タグのパッチを作成し、Tags
プロパティを使用してそれを Twin
オブジェクトに割り当て、その後、UpdateTwinAsync
を使用してパッチを適用します。
// Retrieve the device twin
var twin = await registryManager.GetTwinAsync("myDeviceId");
// Create the tag patch
var tagspatch =
@"{
tags: {
location: {
region: 'US',
plant: 'Redmond43'
}
}
}";
// Assign the patch to the Twin object
twin.Tags["location"] = tagspatch;
// Apply the patch to update the device twin tags section
try
{
await registryManager.UpdateTwinAsync(twin.DeviceId, patch, twin.ETag);
}
catch (Exception e)
{
console.WriteLine("Twin update failed.", e.Message);
}
JSON 文字列を使用してタグを更新する
JSON 形式のデバイス ツイン情報更新パッチを作成して適用できます。 パッチの形式が正しければ、IoT Hub はそれを解析して適用します。
この例では、GetTwinAsync
を呼び出して現在のデバイス ツイン フィールドを Twin
オブジェクトに取得し、リージョンと工場の位置情報を含む JSON 形式の tag
パッチを作成してから、UpdateTwinAsync
を呼び出してパッチを適用してデバイス ツインを更新します。 UpdateTwinAsync
が失敗した場合は、エラー メッセージが表示されます。
// Retrieve the device twin
var twin = await registryManager.GetTwinAsync("myDeviceId");
// Create the JSON tags patch
var patch =
@"{
tags: {
location: {
region: 'US',
plant: 'Redmond43'
}
}
}";
// Apply the patch to update the device twin tags
try
{
await registryManager.UpdateTwinAsync(twin.DeviceId, patch, twin.ETag);
}
catch (Exception e)
{
console.WriteLine("Twin update failed.", e.Message);
}
ツインの必要なプロパティの表示と更新
デバイスの必要なプロパティ情報の読み取りと書き込みを行うには、デバイス ツインの TwinProperties.Desired プロパティを使用します。 JSON 形式のパッチを使用して、ツインの Desired
プロパティを更新します。
この例では、GetTwinAsync
を呼び出して現在のデバイス ツイン フィールドを Twin
オブジェクトに取得し、ツイン speed
の必要なプロパティを更新してから、UpdateTwinAsync
を呼び出して Twin
オブジェクトを適用してデバイス ツインを更新します。
// Retrieve the device twin
var twin = await registryManager.GetTwinAsync("myDeviceId");
twin.Properties.Desired["speed"] = "type: '5G'";
await registryManager.UpdateTwinAsync(twin.DeviceId, twin, twin.ETag);
その他のツインの更新方法
次の SDK メソッドを使用して、ツインの更新を適用することもできます。
- デバイス ツイン全体を置き換えるには、ReplaceTwinAsync を呼び出します。
- システム内で以前に作成されたツインの一覧を更新するには、UpdateTwins2Async を呼び出します。
デバイス ツイン クエリを作成する
このセクションでは、2 つのデバイス ツイン クエリを示します。 デバイス ツイン クエリは、デバイス ツインの結果セットを返す SQL のようなクエリです。
デバイス ツイン クエリを作成するには、CreateQuery を呼び出してツイン SQL クエリを送信し、IQuery インターフェイスを取得します。 必要に応じて、2 つ目のパラメーターを指定して CreateQuery
を呼び出し、ページごとの最大項目数を指定できます。
次に、必要な回数だけ GetNextAsTwinAsync
または GetNextAsJsonAsync
メソッドを呼び出し、すべてのツインの結果を取得します。
- GetNextAsTwinAsync で、次のページングされた結果を Twin オブジェクトとして取得します。
- GetNextAsJsonAsync で、次のページングされた結果を JSON 文字列として取得します。
IQuery
インターフェイスには、フェッチするツイン結果が他にもあるかどうかを確認するために使用できる HasMoreResults ブール値プロパティが含まれています。
このクエリ例では、Redmond43 工場にあるデバイスのデバイス ツインのみを選択します。
var query = registryManager.CreateQuery(
"SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'", 100);
var twinsInRedmond43 = await query.GetNextAsTwinAsync();
Console.WriteLine("Devices in Redmond43: {0}",
string.Join(", ", twinsInRedmond43.Select(t => t.DeviceId)));
このクエリ例では、最初のクエリを改良して、移動体通信ネットワーク経由でも接続されているデバイスのみを選択します。
query = registryManager.CreateQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity.type = 'cellular'", 100);
var twinsInRedmond43UsingCellular = await query.GetNextAsTwinAsync();
Console.WriteLine("Devices in Redmond43 using cellular network: {0}",
string.Join(", ", twinsInRedmond43UsingCellular.Select(t => t.DeviceId)));
SDK サービスのサンプル
Azure IoT SDK for .NET には、デバイス ツイン タスクを処理するサービス アプリの動作するサンプルが用意されています。 詳細については、レジストリ マネージャーのサンプルのページを参照してください。
概要
この記事では、Azure IoT SDK for Java を使用して、デバイス ツイン用のデバイスおよびバックエンド サービス アプリケーション コードを作成する方法について説明します。
デバイス アプリケーションを作成する
デバイス アプリケーションは、ツインの報告されたプロパティの読み取りと書き込みを行うことができます。また、バックエンド アプリケーションまたは IoT Hub によって設定された必要なツインのプロパティの変更について通知を受け取ることができます。
このセクションでは、次のことを行うデバイス アプリケーション コードを作成する方法について説明します。
- デバイス ツインの取得と表示
- 報告されたデバイス ツインのプロパティを更新する
- 必要なプロパティの変更をサブスクライブする
DeviceClient クラスは、デバイスからデバイス ツインとやりとりするのに必要なすべてのメソッドを公開しています。
デバイス インポート ステートメント
次のデバイス インポート ステートメントを使用して、Azure IoT SDK for Java にアクセスします。
import com.microsoft.azure.sdk.iot.device.*;
import com.microsoft.azure.sdk.iot.device.DeviceTwin.*;
デバイスに接続する
デバイスに接続するには:
IotHubClientProtocol を使用して、トランスポート プロトコルを選択します。 次に例を示します。
IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
DeviceClient
コンストラクターを使用して、デバイスのプライマリ接続文字列とプロトコルを追加します。String connString = "{IoT hub device connection string}"; DeviceClient client = new DeviceClient(connString, protocol);
open を使用して、デバイスを IoT Hub に接続します。 クライアントが既に開いている場合、メソッドは何も行いません。
client.open(true);
デバイス ツインの取得と表示
クライアント接続を開いたら、getTwin を呼び出して、現在のツイン プロパティを Twin
オブジェクトに取得します。
次に例を示します。
private static Twin twin;
System.out.println("Getting current twin");
twin = client.getTwin();
System.out.println("Received current twin:");
System.out.println(twin);
デバイス ツインの報告されたプロパティを更新する
現在のツインを取得した後、報告されたプロパティの更新を開始できます。 報告されたプロパティの正しいバージョンがある限り、現在のツインを取得しなくても、報告されたプロパティの更新を行うこともできます。 報告されたプロパティを送信して "前提条件が失敗しました" エラーを受け取った場合、報告されたプロパティのバージョンは最新ではありません。 その場合は、getTwin
を再度呼び出して最新バージョンを取得します。
報告されたプロパティを更新するには:
getReportedProperties を呼び出して、ツインの報告されたプロパティを TwinCollection オブジェクトにフェッチします。
put を使用して、
TwinCollection
オブジェクト内の報告されたプロパティを更新します。 報告されたプロパティの更新ごとにput
を呼び出します。updateReportedProperties を使用して、報告されたプロパティのグループ (
put
メソッドを使用して更新されたもの) を適用します。
次に例を示します。
TwinCollection reportedProperties = twin.getReportedProperties();
int newTemperature = new Random().nextInt(80);
reportedProperties.put("HomeTemp(F)", newTemperature);
System.out.println("Updating reported property \"HomeTemp(F)\" to value " + newTemperature);
ReportedPropertiesUpdateResponse response = client.updateReportedProperties(reportedProperties);
System.out.println("Successfully set property \"HomeTemp(F)\" to value " + newTemperature);
必要なプロパティの変更をサブスクライブする
subscribeToDesiredProperties を呼び出して、必要なプロパティの変更をサブスクライブします。 このクライアントは、必要なプロパティが更新されるたびに、Twin
オブジェクトを含むコールバックを受け取ります。 必要なプロパティの変更方法に応じて、このコールバックには、必要なプロパティ セット全体、または更新された必要なプロパティのみが含まれます。
この例では、必要なプロパティの変更をサブスクライブします。 必要なプロパティの変更は、DesiredPropertiesUpdatedHandler
というハンドラーに渡されます。
client.subscribeToDesiredProperties(new DesiredPropertiesUpdatedHandler(), null);
この例では、DesiredPropertiesUpdatedHandler
の必要なプロパティ変更コールバック ハンドラーは、getDesiredProperties を呼び出してプロパティの変更を取得し、更新されたツイン プロパティを出力します。
private static class DesiredPropertiesUpdatedHandler implements DesiredPropertiesCallback
{
@Override
public void onDesiredPropertiesUpdated(Twin desiredPropertyUpdateTwin, Object context)
{
if (twin == null)
{
// No need to care about this update because these properties will be present in the twin retrieved by getTwin.
System.out.println("Received desired properties update before getting current twin. Ignoring this update.");
return;
}
// desiredPropertyUpdateTwin.getDesiredProperties() contains all the newly updated desired properties as well as the new version of the desired properties
twin.getDesiredProperties().putAll(desiredPropertyUpdateTwin.getDesiredProperties());
twin.getDesiredProperties().setVersion(desiredPropertyUpdateTwin.getDesiredProperties().getVersion());
System.out.println("Received desired property update. Current twin:");
System.out.println(twin);
}
}
SDK デバイスのサンプル
Azure IoT SDK for Java には、この記事で説明されているデバイス アプリの概念をテストするための動作するサンプルが含まれています。 詳細については、デバイス ツインのサンプルのページを参照してください。
バックエンド アプリケーションを作成する
このセクションでは、次のようなバックエンド アプリケーションを作成する方法について説明します。
- デバイス ツイン タグを更新する
- タグとプロパティにフィルターを使用してデバイスのクエリを実行する
ServiceClient
DeviceTwin クラスには、サービスがデバイス ツインにアクセスするために使用できるメソッドが含まれています。
サービス インポート ステートメント
次のサービス インポート ステートメントを使用して、Azure IoT SDK for Java にアクセスします。
import com.microsoft.azure.sdk.iot.service.devicetwin.*;
import com.microsoft.azure.sdk.iot.service.exceptions.IotHubException;
IoT Hub サービス クライアントに接続する
IoT Hub に接続してデバイス ツイン情報を表示および更新するには:
- DeviceTwinClientOptions オブジェクトを作成します。 アプリケーションに必要なオプションを設定します。 これらのオプションは
DeviceTwin
オブジェクトに渡されます。 - DeviceTwin コンストラクターを使用して、IoT Hub への接続を作成します。
DeviceTwin
オブジェクトは、IoT Hub との通信を処理します。 パラメーターとして、「前提条件」セクションで作成した IoT Hub サービス接続文字列とDeviceTwinClientOptions
オブジェクトを指定します。 - DeviceTwinDevice オブジェクトは、プロパティとタグを使用してデバイス ツインを表現します。
次に例を示します。
public static final String iotHubConnectionString = "{IoT hub service connection string}";
public static final String deviceId = "myDeviceId";
public static final String region = "US";
public static final String plant = "Redmond43";
// Get the DeviceTwin and DeviceTwinDevice objects
DeviceTwinClientOptions twinOptions = new DeviceTwinClientOptions();
DeviceTwin twinClient = new DeviceTwin(iotHubConnectionString,twinOptions);
DeviceTwinDevice device = new DeviceTwinDevice(deviceId);
デバイス ツインのフィールドを更新する
デバイス ツイン フィールドを更新するには:
getTwin を使用して、現在のデバイス ツイン フィールドを取得します
この例では、デバイス ツイン フィールドを取得して出力します。
// Get the device twin from IoT Hub System.out.println("Device twin before update:"); twinClient.getTwin(device); System.out.println(device);
HashSet
オブジェクトを使用して、ツイン タグ ペアのグループをadd
しますsetTags を使用して、タグ ペアのグループを
tags
オブジェクトからDeviceTwinDevice
オブジェクトに追加しますupdateTwin を使用して、IoT ハブのツインを更新します
この例では、デバイス ツインのリージョンと工場のデバイス ツイン タグを更新します。
// Update device twin tags if they are different // from the existing values String currentTags = device.tagsToString(); if ((!currentTags.contains("region=" + region) && !currentTags.contains("plant=" + plant))) { // Create the tags and attach them to the DeviceTwinDevice object Set<Pair> tags = new HashSet<Pair>(); tags.add(new Pair("region", region)); tags.add(new Pair("plant", plant)); device.setTags(tags); // Update the device twin in IoT Hub System.out.println("Updating device twin"); twinClient.updateTwin(device); } // Retrieve and display the device twin with the tag values from IoT Hub System.out.println("Device twin after update:"); twinClient.getTwin(device); System.out.println(device);
デバイス ツイン クエリを作成する
このセクションでは、2 つのデバイス ツイン クエリを示します。 デバイス ツイン クエリは、デバイス ツインの結果セットを返す SQL のようなクエリです。
Query クラスには、IoT Hub に対してツイン、ジョブ、デバイス ジョブ、または生データに関する SQL スタイルのクエリを作成するために使用できるメソッドが含まれています。
デバイス クエリを作成するには:
createSqlQuery を使用して、ツインの SQL クエリを構築します
queryTwin を使用して、クエリを実行します
hasNextDeviceTwin を使用して、結果セットに別のデバイス ツインがあるかどうかを確認します
getNextDeviceTwin を使用して、結果セットから次のデバイス ツインを取得します
次のクエリ例では、最大 100 台のデバイスが返されます。
このクエリ例では、Redmond43 工場にあるデバイスのデバイス ツインのみを選択します。
// Query the device twins in IoT Hub
System.out.println("Devices in Redmond:");
// Construct the query
SqlQuery sqlQuery = SqlQuery.createSqlQuery("*", SqlQuery.FromType.DEVICES, "tags.plant='Redmond43'", null);
// Run the query, returning a maximum of 100 devices
Query twinQuery = twinClient.queryTwin(sqlQuery.getQuery(), 100);
while (twinClient.hasNextDeviceTwin(twinQuery)) {
DeviceTwinDevice d = twinClient.getNextDeviceTwin(twinQuery);
System.out.println(d.getDeviceId());
}
このクエリ例では、最初のクエリを改良して、移動体通信ネットワーク経由でも接続されているデバイスのみを選択します。
System.out.println("Devices in Redmond using a cellular network:");
// Construct the query
sqlQuery = SqlQuery.createSqlQuery("*", SqlQuery.FromType.DEVICES, "tags.plant='Redmond43' AND properties.reported.connectivityType = 'cellular'", null);
// Run the query, returning a maximum of 100 devices
twinQuery = twinClient.queryTwin(sqlQuery.getQuery(), 3);
while (twinClient.hasNextDeviceTwin(twinQuery)) {
DeviceTwinDevice d = twinClient.getNextDeviceTwin(twinQuery);
System.out.println(d.getDeviceId());
}
SDK サービスのサンプル
Azure IoT SDK for Java には、デバイス ツイン タスクを処理するサービス アプリの動作するサンプルが用意されています。 詳細については、デバイス ツインのサンプルのページを参照してください。
概要
この記事では、Azure IoT SDK for Python を使用して、デバイス ツイン用のデバイスおよびバックエンド サービス アプリケーション コードを作成する方法について説明します。
デバイス アプリケーションを作成する
デバイス アプリケーションは、ツインの報告されたプロパティの読み取りと書き込みを行うことができます。また、バックエンド アプリケーションまたは IoT Hub によって設定された必要なツインのプロパティの変更について通知を受け取ることができます。
IoTHubDeviceClient クラスには、デバイス ツインを操作するために使用できるメソッドが含まれています。
このセクションでは、次のようなデバイス アプリケーション コードを作成する方法について説明します。
- デバイス ツインを取得し、報告されたプロパティを確認する
- 報告されたデバイス ツインのプロパティにパッチを適用する
デバイスへの接続
このセクションでは、共有アクセス キーを含むデバイスの主キーを使用してアプリケーションをデバイスに接続する方法を示します。
アプリケーションをデバイスに接続するには:
- create_from_connection_string を呼び出して、デバイスの接続文字列を追加します
- connect を呼び出して、デバイス クライアントを Azure IoT Hub に接続します
# import the device client library
import asyncio
from azure.iot.device.aio import IoTHubDeviceClient
# substitute the device connection string in conn_str
# and add it to the IoTHubDeviceClient object
conn_str = "{IOT hub device connection string}"
device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)
# connect the application to the device
await device_client.connect()
デバイス ツインを取得し、報告されたプロパティを確認する
タグやプロパティなどのデバイス ツイン情報を取得して確認することができます。 取得されるデバイス ツイン情報は、Azure portal でデバイスについて表示できるデバイス ツインの JSON 形式のデータと一致します。
get_twin を呼び出して、Azure IoT Hub サービスからデバイス ツインを取得します。 ツイン情報は、出力または確認できる変数に配置されます。
この例では、デバイス ツインを取得し、print
コマンドを使用して JSON 形式でデバイス ツインを表示します。
# get the twin
twin = await device_client.get_twin()
print("Twin document:")
print("{}".format(twin))
報告されたデバイス ツインのプロパティにパッチを適用する
パッチを適用して、JSON 形式で報告されたデバイスのプロパティを更新できます。
パッチを適用して報告されたプロパティを更新するには:
- 報告されたプロパティの JSON パッチを変数に割り当てます。
- patch_twin_reported_properties を呼び出して、報告されたプロパティに JSON パッチを適用します。 これは同期呼び出しです。つまり、パッチがサービスに送信されて確認されるまで、この関数は戻りません。
patch_twin_reported_properties
がエラーを返した場合、この関数は対応するエラーを発生させます。
# create the reported properties patch
reported_properties = {"temperature": random.randint(320, 800) / 10}
print("Setting reported temperature to {}".format(reported_properties["temperature"]))
# update the reported properties and wait for the result
await device_client.patch_twin_reported_properties(reported_properties)
これらのメソッドを呼び出してデバイス ツインを更新することもできます。
- replace_twin を呼び出して、デバイス ツイン タグと必要なプロパティを置き換えます。
- update_twin を呼び出して、デバイス ツイン タグと必要なプロパティを更新します。
受信する必要なプロパティ パッチのハンドラー
on_twin_desired_properties_patch_received を呼び出して、ツインの必要なプロパティ パッチを受信したときに呼び出されるハンドラー関数またはコルーチンを作成します。 このハンドラーは引数を 1 つ受け取ります。これは、JSON ディクショナリ オブジェクトの形式のツイン パッチです。
この例では、twin_patch_handler
という必要なプロパティ パッチのハンドラーを設定します。
次に例を示します。
try:
# Set handlers on the client
device_client.on_twin_desired_properties_patch_received = twin_patch_handler
except:
# Clean up in the event of failure
client.shutdown()
twin_patch_handler
は、必要な JSON プロパティの更新を受信して出力します。
# Define behavior for receiving twin desired property patches
def twin_patch_handler(twin_patch):
print("Twin patch received:")
print(twin_patch)
SDK デバイス サンプル
Azure IoT SDK for Python には、次のサンプルが用意されています。
- get_twin - デバイスに接続し、ツイン情報を取得します。
- update_twin_reported_properties - ツインの報告されたプロパティを更新します。
- receive_twin_desired_properties - 必要なプロパティを受信して更新します。
バックエンド アプリケーションを作成する
バックエンド アプリケーションは、IoT Hub 経由でデバイスに接続します。また、デバイスから報告されたプロパティと必要なプロパティを読み取り、デバイスの必要なプロパティを書き込み、デバイス クエリを実行することができます。
このセクションでは、次のことを行うバックエンド アプリケーションを作成する方法について説明します。
- ツイン タグと必要なプロパティを更新する
- タグとプロパティにフィルターを使用してデバイスのクエリを実行する
IoTHubRegistryManager クラスは、サービスからデバイス ツインと対話するバックエンド アプリケーションを作成するために必要なすべてのメソッドを公開しています。
IoT Hub に接続する
from_connection_string を使用して、IoT Hub に接続します。 パラメーターとして、「前提条件」セクションで作成した IoT Hub サービス接続文字列を指定します。
次に例を示します。
import sys
from time import sleep
from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import Twin, TwinProperties, QuerySpecification, QueryResult
# Connect to IoT hub
IOTHUB_CONNECTION_STRING = "{IoT hub service connection string}"
iothub_registry_manager = IoTHubRegistryManager.from_connection_string(IOTHUB_CONNECTION_STRING)
ツイン タグと必要なプロパティを更新する
update_twin を使用すると、デバイス ツイン タグと必要なプロパティの両方をバックエンド アプリケーションから同時に更新できます。
- get_twin を呼び出して、デバイス ツインの現在のバージョンを取得します
- Twin クラスを使用して、JSON 形式でタグとプロパティを追加します。
update_twin
を呼び出して、デバイス ツインにパッチを適用します。 replace_twin を使用して、デバイス ツインの必要なプロパティとタグを置き換えることもできます。
この例では、region
と plant
のタグ情報を更新し、power_level
の必要なプロパティを 1
に設定します。
new_tags = {
'location' : {
'region' : 'US',
'plant' : 'Redmond43'
}
}
DEVICE_ID = "[Device Id]"
twin = iothub_registry_manager.get_twin(DEVICE_ID)
twin_patch = Twin(tags=new_tags, properties= TwinProperties(desired={'power_level' : 1}))
twin = iothub_registry_manager.update_twin(DEVICE_ID, twin_patch, twin.etag)
デバイス ツイン クエリを作成する
デバイス ツイン クエリを使用して、デバイス ツイン情報のクエリを実行できます。 デバイス ツイン クエリは、デバイス ツインの結果セットを返す SQL のようなクエリです。
デバイス ツイン クエリを使用するには:
QuerySpecification オブジェクトを使用して、SQL のようなクエリ要求を定義します。
query_iot_hub を使用して IoTHub にクエリを実行し、SQL のようなクエリ仕様を使用してデバイス ツイン情報を取得します。
この例では 2 つのクエリを実行します。 1 つ目を使用して Redmond43
工場にあるデバイスのデバイス ツインのみを選択し、2 つ目を使用して移動体通信ネットワーク経由でも接続しているデバイスのみを選択するようにクエリを改良します。 結果は各クエリの後に出力されます。
query_spec = QuerySpecification(query="SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'")
query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100)
print("Devices in Redmond43 plant: {}".format(', '.join([twin.device_id for twin in query_result.items])))
print()
query_spec = QuerySpecification(query="SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity = 'cellular'")
query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100)
print("Devices in Redmond43 plant using cellular network: {}".format(', '.join([twin.device_id for twin in query_result.items])))
print()
SDK サービスのサンプル
Azure IoT SDK for Python には、デバイス ツイン タスクを処理するサービス アプリの動作するサンプルが用意されています。 詳細については、レジストリ マネージャー クエリのサンプルのページを参照してください。
概要
この記事では、Azure IoT SDK for Node.js を使用して、デバイス ツイン用のデバイスおよびバックエンド サービス アプリケーション コードを作成する方法について説明します。
デバイス アプリケーションを作成する
デバイス アプリケーションは、ツインの報告されたプロパティの読み取りと書き込みを行うことができます。また、バックエンド アプリケーションまたは IoT Hub によって設定された必要なツインのプロパティの変更について通知を受け取ることができます。
このセクションでは、Azure IoT SDK for Node.js の azure-iot-device パッケージを使用して、次のことを行うデバイス アプリケーションを作成する方法について説明します。
- デバイス ツインを取得し、報告されたプロパティを確認する
- 報告されたデバイス ツインのプロパティを更新する
- 必要なプロパティ変更の通知を受け取る
SDK パッケージをインストールする
次のコマンドを実行して、開発マシンに azure-iot-device デバイス SDK をインストールします。
npm install azure-iot-device --save
azure-iot-device パッケージには、IoT デバイスとやり取りするオブジェクトが含まれています。 Twin クラスには、ツイン固有のオブジェクトが含まれています。 このセクションでは、デバイス ツイン データの読み取りと書き込みに使用される Client
クラス コードについて説明します。
トランスポート プロトコルを選択する
Client
オブジェクトでは、次のプロトコルがサポートされます。
Amqp
Http
-Http
を使用する場合、Client
インスタンスは IoT Hub からのメッセージを頻繁にはチェックしません (少なくとも 25 分ごと)。Mqtt
MqttWs
AmqpWs
必要なトランスポート プロトコルを開発マシンにインストールします。
たとえば、次のコマンドを使用すると、Mqtt
プロトコルをインストールできます。
npm install azure-iot-device-mqtt --save
MQTT、AMQP、および HTTPS のサポートの相違点の詳細については、「cloud-to-device 通信に関するガイダンス」と「通信プロトコルの選択」を参照してください。
クライアント モジュールを作成する
インストールされたパッケージを使用して Client
モジュールを作成します。
次に例を示します。
const Client = require('azure-iot-device').Client;
プロトコル モジュールを作成する
インストールされたトランスポート パッケージを使用して Protocol
モジュールを作成します。
この例では、MQTT プロトコルを割り当てます。
const Protocol = require('azure-iot-device-mqtt').Mqtt;
デバイスの接続文字列とトランスポート プロトコルを追加する
fromConnectionString を呼び出して、デバイス接続パラメーターを指定します。
- connStr - IoT ハブの "デバイス接続" アクセス許可をカプセル化する接続文字列。 接続文字列には、ホスト名、デバイス ID、共有アクセス キーが次の形式で含まれます: "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"。
- transportCtor - トランスポート プロトコル。
この例では、Mqtt
トランスポート プロトコルを使用します。
const deviceConnectionString = "{IoT hub device connection string}"
const Protocol = require('azure-iot-device-mqtt').Mqtt;
let client = Client.fromConnectionString(deviceConnectionString, Protocol);
IoT Hub への接続を開く
open メソッドを使用して、IoT デバイスと IoT Hub の間の接続を開きます。
.catch(err)
を使用してエラーをキャッチし、ハンドラー コードを実行します。
次に例を示します。
client.open() //open the connection
.catch((err) => {
console.error('Could not connect: ' + err.message);
});
デバイス ツインを取得し、報告されたプロパティを確認する
getTwin を呼び出して、現在のデバイス ツイン情報を Twin オブジェクトに取得します。
次に例を示します。
client.getTwin(function(err, twin))
if (err)
console.error('could not get twin');
報告されたデバイス ツインのプロパティを更新する
update を使用して、デバイスの報告されたプロパティを更新します。 JSON 形式のパッチを 1 つ目のパラメーターとして、関数実行状態のコールバック メソッドを 2 つ目のパラメーターとしてメソッドに含めます。
この例では、JSON 形式のデバイス ツイン パッチが patch
変数に格納されます。 パッチには、デバイス ツイン connectivity
の更新値 cellular
が含まれています。 パッチとエラー ハンドラーは update
メソッドに渡されます。 エラーがある場合は、コンソールのエラー メッセージが表示されます。
var patch = {
connectivity: {
type: 'cellular'
}
}
twin.properties.reported.update(patch, function(err)
{
if (err)
{
console.error('could not update twin');
}
else
{
console.log('twin state reported');
process.exit();
}
});
必要なプロパティ変更の通知を受け取る
コールバック ハンドラー メソッド名を twin.on に渡して、デバイス内で必要なプロパティが変更されたときに実行される必要なプロパティ更新イベント リスナーを作成します。
必要なプロパティ イベント リスナーは、次のいずれかの形式を受け取ることができます。
- 1 つのイベント ハンドラーですべてのパッチを受信する
- プロパティ グループで何か変更があった場合にイベントを受信する
- 1 つのプロパティ変更のイベントを受信する
1 つのイベント ハンドラーですべてのパッチを受信する
必要なプロパティの変更を受け取るリスナーを作成できます。
このコード例は、サービスから受信したプロパティを出力します。
twin.on('properties.desired', function (delta) {
console.log('new desired properties received:');
console.log(JSON.stringify(delta));
});
プロパティ グループで何か変更があった場合にイベントを受信する
プロパティ グループの何かが変更された場合にイベントを受信するリスナーを作成できます。
次に例を示します。
minTemperature
とmaxTemperature
の各プロパティは、properties.desired.climate changes
というプロパティ グループに属します。バックエンド サービス アプリケーションは、このパッチを適用して、
minTemperature
とmaxTemperature
という必要なプロパティを更新します。const twinPatch1 = { properties: { desired: { climate: { minTemperature: 68, maxTemperature: 76, }, }, }, };
このコードを使用して、
properties.desired.climate
プロパティ グループ内で変更があった場合にトリガーされる必要なプロパティ変更イベント リスナーを設定します。 このグループ内で必要なプロパティの変更があった場合、最小と最大の温度の変更メッセージがコンソールに表示されます。twin.on('properties.desired.climate', function (delta) { if (delta.minTemperature || delta.maxTemperature) { console.log('updating desired temp:'); console.log('min temp = ' + twin.properties.desired.climate.minTemperature); console.log('max temp = ' + twin.properties.desired.climate.maxTemperature); } });
1 つのプロパティ変更のイベントを受信する
1 つのプロパティ変更に対してリスナーを設定できます。 この例では、このイベントのコードは、fanOn
ブール値がパッチの一部である場合にのみ実行されます。 このコードを使用して、必要な fanOn
の新しい状態がサービスによって更新されるたびに出力します。
バックエンド アプリケーションは、この必要なプロパティ パッチを適用します。
const twinPatch2 = { properties: { desired: { climate: { hvac: { systemControl: { fanOn: true, }, }, }, }, }, };
リスナーは、
fanOn
プロパティが変更された場合にのみトリガーします。twin.on('properties.desired.climate.hvac.systemControl', function (fanOn) { console.log('setting fan state to ' + fanOn); });
Device SDK のサンプル
Azure IoT SDK for Node.js には、次の 2 つのデバイス ツイン サンプルが含まれています。
バックエンド アプリケーションを作成する
バックエンド アプリケーションは、IoT Hub 経由でデバイスに接続します。また、デバイスから報告されたプロパティと必要なプロパティを読み取り、デバイスの必要なプロパティを書き込み、デバイス クエリを実行することができます。
このセクションでは、次のようなバックエンド アプリケーションを作成する方法について説明します。
- デバイス ツインの取得と更新
- デバイス ツイン クエリを作成する
サービス SDK パッケージをインストールする
次のコマンドを実行して、開発マシンに azure-iothub をインストールします。
npm install azure-iothub --save
Registry クラスは、バックエンド アプリケーションからデバイス ツインと対話するために必要なすべてのメソッドを公開しています。
IoT Hub に接続する
fromConnectionString を使用して IoT Hub に接続します。 パラメーターとして、「前提条件」セクションで作成した IoT Hub サービス接続文字列を指定します。
'use strict';
var iothub = require('azure-iothub');
var connectionString = '{Iot Hub service connection string}';
var registry = iothub.Registry.fromConnectionString(connectionString);
デバイス ツインの取得と更新
デバイス ツインのタグと必要なプロパティの更新を含むパッチを作成できます。
デバイス ツインを更新するには:
- getTwin を呼び出して、デバイス ツイン オブジェクトを取得します。
- デバイス ツインの更新を含むパッチの書式を設定します。 「Twin クラス」で説明されているように、パッチは JSON 形式です。 バックエンド サービス パッチには、タグと必要なプロパティの更新を含めることができます。 パッチ形式の詳細については、「タグやプロパティの形式」を参照してください。
- update を呼び出して、デバイス ツインをパッチで更新します。
この例では、myDeviceId
のデバイス ツインが取得され、その後、region: 'US', plant: 'Redmond43'
の location
タグ更新を含むパッチがツインに適用されます。
registry.getTwin('myDeviceId', function(err, twin){
if (err) {
console.error(err.constructor.name + ': ' + err.message);
} else {
var patch = {
tags: {
location: {
region: 'US',
plant: 'Redmond43'
}
}
};
twin.update(patch, function(err) {
if (err) {
console.error('Could not update twin: ' + err.constructor.name + ': ' + err.message);
} else {
console.log(twin.deviceId + ' twin updated successfully');
queryTwins();
}
});
}
});
デバイス ツイン クエリを作成する
SQL のようなデバイス クエリを作成して、デバイス ツインから情報を収集できます。
createQuery を使用して、IoT Hub インスタンス上で実行してデバイスまたはジョブに関する情報を検索できるクエリを作成します。
createQuery
には 2 つのパラメーターがあります。
- sqlQuery - SQL 文字列として記述されたクエリ。
- pageSize - ページごとの必要な結果の数 (省略可能。既定値: 1000、最大値: 10000)。
pageSize パラメーターが指定されている場合、クエリ オブジェクトには hasMoreResults
ブール値プロパティが含まれており、これを確認し、すべての結果を取得するために必要な回数分 nextAsTwin
メソッドを使用して、次のツイン結果ページを取得できます。 next
というメソッドは、集計クエリの結果など、デバイス ツインではない結果で使用できます。
このクエリ例では、Redmond43
工場にあるデバイスのデバイス ツインのみを選択します。
var queryTwins = function() {
var query = registry.createQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43'", 100);
query.nextAsTwin(function(err, results) {
if (err) {
console.error('Failed to fetch the results: ' + err.message);
} else {
console.log("Devices in Redmond43: " + results.map(function(twin) {return twin.deviceId}).join(','));
}
});
このクエリ例では、最初のクエリを改良して、移動体通信ネットワーク経由でも接続されているデバイスのみを選択します。
query = registry.createQuery("SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity.type = 'cellular'", 100);
query.nextAsTwin(function(err, results) {
if (err) {
console.error('Failed to fetch the results: ' + err.message);
} else {
console.log("Devices in Redmond43 using cellular network: " + results.map(function(twin) {return twin.deviceId}).join(','));
}
});
};
Service SDK のサンプル
Azure IoT SDK for Node.js には、デバイス ツイン タスクを処理するサービス アプリの動作するサンプルが用意されています。 詳細については、「デバイス ツイン バックエンド サービス」を参照してください。このプロジェクトは、特定のデバイスのデバイス ツイン パッチ更新を送信するために使用されます。