Руководство для разработчиков служб IoT Plug and Play

IoT Plug and Play позволяет создавать устройства Интернета вещей, которые объявляют свои возможности приложениям Интернета вещей Azure. IoT Plug and Play не нуждаются в ручной настройке, когда клиент подключает их к приложениям с поддержкой самонастраивающегося Интернета вещей.

IoT Plug and Play позволяет использовать устройства, которые объявили свой ID модели с помощью вашего центра Интернета вещей. Например, можно напрямую обращаться к свойствам и командам устройства.

Если вы используете IoT Central, вы можете использовать пользовательский интерфейс IoT Central и REST API для взаимодействия с устройствами IoT самонастраивающийся, подключенными к приложению.

Пакеты SDK службы

Используйте пакеты SDK службы Интернета вещей Azure в решении для взаимодействия с устройствами и модулями. Например, пакеты SDK для служб можно использовать для чтения и обновления свойств двойника и вызова команд. Поддерживаются следующие языки: C#, Java, Node.js и Python.

Пакеты SDK для службы Интернета вещей Azure содержат код, который облегчает создание приложений, взаимодействующих непосредственно с Центром Интернета вещей, для управления устройствами и безопасностью.

Платформа Пакет Репозиторий кода Примеры Справочные материалы
.NET NuGet GitHub Примеры Справочные материалы
Java Maven GitHub Примеры Справочные материалы
Узел npm GitHub Примеры Справочные материалы
Python pip GitHub Примеры Справочные материалы

Пакеты SDK службы позволяют получать доступ к сведениям об устройстве из компонента решения, например рабочего стола или веб-приложения. Пакеты SDK для служб включают два пространства имен и объектные модели, которые можно использовать для получения идентификатора модели:

  • Клиент службы Центра Интернета вещей. Эта служба раскрывает идентификатор модели как свойство дневника устройства.

  • Клиент Digital Twins. Новый API Digital Twins работает с такими конструкциями модели языка определения цифровых двойников (Digital Twins Definition Language, DTDL), как компоненты, свойства и команды. Интерфейсы API цифровых двойников упрощают создание самонастраивающихся решений IoT для построителя решений.

Доступны также следующие ресурсы:

Примеры клиентов службы центра Интернета вещей

В этом разделе приведены примеры на языке C# с использованием клиента службы центра Интернета вещей, а также классов RegistryManager и ServiceClient. Класс RegistryManager следует использовать для взаимодействия с состоянием устройства с помощью двойников устройства. Также можно использовать класс RegistryManager для запроса регистрации устройств в центре Интернета вещей. Для вызова команд на устройстве используется класс ServiceClient. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством. Во фрагментах кода переменная deviceTwinId содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение двойника устройства и идентификатора модели

Чтобы получить двойник устройства и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

RegistryManager registryManager = RegistryManager.CreateFromConnectionString(parameters.HubConnectionString);

Twin twin = await registryManager.GetTwinAsync(deviceTwinId);
Console.WriteLine($"Device twin: \n{JsonConvert.SerializeObject(twin, Formatting.Indented)}");
Console.WriteLine($"Model ID: {twin.ModelId}.");

Обновление двойников устройств

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. В этом примере показано, как получить ETag двойника перед его обновлением. Свойство определено в стандартном компоненте устройства:

Twin twin = await registryManager.GetTwinAsync(deviceTwinId);

int desiredTargetTemperature = 60;

// Update the twin
var twinPatch = new Twin();
twinPatch.Properties.Desired["targetTemperature"] = desiredTargetTemperature;

Console.WriteLine($"Update the targetTemperature property to {desiredTargetTemperature}.");

await registryManager.UpdateTwinAsync(deviceTwinId, twinPatch, twin.ETag);

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. В этом примере показано, как получить ETag двойника перед его обновлением. Свойство определено в компоненте Thermostat1:

Twin twin = await registryManager.GetTwinAsync(deviceTwinId);

int desiredTargetTemperature = 60;

var twinPatch = CreatePropertyPatch("targetTemperature", desiredTargetTemperature, "thermostat1");

await registryManager.UpdateTwinAsync(deviceTwinId, twinPatch, twin.ETag);

// ...

private static Twin CreatePropertyPatch(string propertyName, object propertyValue, string componentName)
{
    var twinPatch = new Twin();
    twinPatch.Properties.Desired[componentName] = new
    {
        __t = "c"
    };
    twinPatch.Properties.Desired[componentName][propertyName] = JsonConvert.SerializeObject(propertyValue);
    return twinPatch;
}

Исправление свойства в компоненте выглядит так, как показано в следующем примере:

{
"sampleComponentName":
  {
    "__t": "c",
    "samplePropertyName": 20
  }
}

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(parameters.HubConnectionString);

var commandInvocation = new CloudToDeviceMethod("getMaxMinReport") { ResponseTimeout = TimeSpan.FromSeconds(30) };

// Set command payload
DateTimeOffset since = DateTimeOffset.Now.Subtract(TimeSpan.FromMinutes(2));
string componentCommandPayload = JsonConvert.SerializeObject(since);
commandInvocation.SetPayloadJson(componentCommandPayload);

try
{
  CloudToDeviceMethodResult result = await serviceClient.InvokeDeviceMethodAsync(deviceTwinId, commandInvocation);

  Console.WriteLine($"Command getMaxMinReport was invoked." +
      $"\nDevice returned status: {result.Status}. \nReport: {result.GetPayloadAsJson()}");
}
catch (DeviceNotFoundException)
{
    Console.WriteLine($"Unable to execute command getMaxMinReport on {deviceTwinId}.";
}

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте Thermostat1:

// Create command name to invoke for component. The command is formatted as <component name>*<command name>
string commandToInvoke = "thermostat1*getMaxMinReport";
var commandInvocation = new CloudToDeviceMethod(commandToInvoke) { ResponseTimeout = TimeSpan.FromSeconds(30) };

// Set command payload
DateTimeOffset since = DateTimeOffset.Now.Subtract(TimeSpan.FromMinutes(2));
string componentCommandPayload = JsonConvert.SerializeObject(since);
commandInvocation.SetPayloadJson(componentCommandPayload);

try
{
    CloudToDeviceMethodResult result = await serviceClient.InvokeDeviceMethodAsync(deviceTwinId, commandInvocation);
    Console.WriteLine($"Command getMaxMinReport was invoked on component thermostat1." +
        $"\nDevice returned status: {result.Status}. \nReport: {result.GetPayloadAsJson()}");
}
catch (DeviceNotFoundException)
{
    Console.WriteLine("Unable to execute command getMaxMinReport on component thermostat1.");
}

Примеры цифровых двойников в центре Интернета вещей

Для взаимодействия с состоянием устройства с помощью цифровых двойников используется класс DigitalTwinClient. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством.

В этом разделе приводятся примеры на языке C# с использованием API цифровых двойников. В представленных далее фрагментах кода используются следующие классы для представления цифровых двойников устройств термостата и контроллера температуры:

using Microsoft.Azure.Devices.Serialization;
using Newtonsoft.Json;
using System;

namespace Microsoft.Azure.Devices.Samples
{
  internal class ThermostatTwin : BasicDigitalTwin
  {
    [JsonProperty("$metadata")]
    public new ThermostatMetadata Metadata { get; set; }

    [JsonProperty("maxTempSinceLastReboot")]
    public double? MaxTempSinceLastReboot { get; set; }

    [JsonProperty("targetTemperature")]
    public double? TargetTemperature { get; set; }
  }

  internal class ThermostatMetadata : DigitalTwinMetadata
  {
    [JsonProperty("maxTempSinceLastReboot")]
    public ReportedPropertyMetadata MaxTempSinceLastReboot { get; set; }

    [JsonProperty("targetTemperature")]
    public WritableProperty TargetTemperature { get; set; }
  }

  internal class ReportedPropertyMetadata
  {
    [JsonProperty("lastUpdateTime")]
    public DateTimeOffset LastUpdateTime { get; set; }
  }

  internal class TemperatureControllerTwin : BasicDigitalTwin
  {
    [JsonProperty("$metadata")]
    public new TemperatureControllerMetadata Metadata { get; set; }

    [JsonProperty("serialNumber")]
    public string SerialNumber { get; set; }

    [JsonProperty("thermostat1")]
    public ThermostatTwin Thermostat1 { get; set; }

    [JsonProperty("thermostat2")]
    public ThermostatTwin Thermostat2 { get; set; }
  }

  internal class TemperatureControllerMetadata : DigitalTwinMetadata
  {
    [JsonProperty("serialNumber")]
    public ReportedPropertyMetadata SerialNumber { get; set; }

    [JsonProperty("thermostat1")]
    public WritableProperty Thermostat1 { get; set; }

    [JsonProperty("thermostat2")]
    public WritableProperty Thermostat2 { get; set; }
  }
}

Переменная digitalTwinId содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение цифрового двойника и идентификатора модели

Чтобы получить цифровой двойник и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

DigitalTwinClient digitalTwinClient = DigitalTwinClient.CreateFromConnectionString(parameters.HubConnectionString);
HttpOperationResponse<ThermostatTwin, DigitalTwinGetHeaders> getDigitalTwinResponse = await digitalTwinClient
    .GetDigitalTwinAsync<ThermostatTwin>(digitalTwinId);
ThermostatTwin thermostatTwin = getDigitalTwinResponse.Body;
Console.WriteLine($"Model ID: {thermostatTwin.Metadata.ModelId}.");
Console.WriteLine($"Digital Twin: \n{JsonConvert.SerializeObject(thermostatTwin, Formatting.Indented)}");

Обновление цифрового двойника

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. Свойство определено в стандартном компоненте устройства:

var updateOperation = new UpdateOperationsUtility();

int desiredTargetTemperature = 60;

// Get the current value of the targetTemperature property
HttpOperationResponse<ThermostatTwin, DigitalTwinGetHeaders> getDigitalTwinResponse = await digitalTwinClient
    .GetDigitalTwinAsync<ThermostatTwin>(digitalTwinId);
double? currentTargetTemperature = getDigitalTwinResponse.Body.TargetTemperature;

// Has the targetTemperature property previously been set?
if (currentTargetTemperature != null)
{
  // Update the existing property
  // Prepend the property path with a '/'
  updateOperation.AppendReplacePropertyOp($"/targetTemperature",   desiredTargetTemperature);
}
else
{
  // Add a new property
  // Prepend the property path with a '/'
  updateOperation.AppendAddPropertyOp($"/targetTemperature", desiredTargetTemperature);
}

// Update the targetTemperature property on the digital twin
HttpOperationHeaderResponse<DigitalTwinUpdateHeaders> updateDigitalTwinResponse = await digitalTwinClient
    .UpdateDigitalTwinAsync(digitalTwinId, updateOperation.Serialize());

Console.WriteLine($"Update {digitalTwinId} digital twin response: {updateDigitalTwinResponse.Response.StatusCode}.");

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. Свойство определено в компоненте Thermostat1:

int desiredTargetTemperature = 60;

var updateOperation = new UpdateOperationsUtility();

// Look at when the property was updated and what was it set to.
HttpOperationResponse<TemperatureControllerTwin, DigitalTwinGetHeaders> getDigitalTwinResponse = await digitalTwinClient
  .GetDigitalTwinAsync<TemperatureControllerTwin>(digitalTwinId);

ThermostatTwin thermostat1 = getDigitalTwinResponse.Body.Thermostat1;

if (thermostat1 != null)
{
  // Thermostat1 is present in the TemperatureController twin. You can add/replace the component-level property "targetTemperature"
  double? currentComponentTargetTemperature = getDigitalTwinResponse.Body.Thermostat1.TargetTemperature;
  if (currentComponentTargetTemperature != null)
  {
      DateTimeOffset targetTemperatureDesiredLastUpdateTime = getDigitalTwinResponse.Body.Thermostat1.Metadata.TargetTemperature.LastUpdateTime;

      // The property path to be replaced should be prepended with a '/'
      updateOperation.AppendReplacePropertyOp("/thermostat1/targetTemperature", desiredTargetTemperature);
  }
  else
  {
      // The property path to be added should be prepended with a '/'
      updateOperation.AppendAddPropertyOp("/thermostat1/targetTemperature", desiredTargetTemperature);
  }
}
else
{
    // Thermostat1 is not present in the TemperatureController twin. Add the component.
    var componentProperty = new Dictionary<string, object> { { "targetTemperature", desiredTargetTemperature }, { "$metadata", new object() } };

    // The property path to be replaced should be prepended with a '/'
    updateOperation.AppendAddComponentOp("/thermostat1", componentProperty);
}

HttpOperationHeaderResponse<DigitalTwinUpdateHeaders> updateDigitalTwinResponse = await digitalTwinClient
    .UpdateDigitalTwinAsync(digitalTwinId, updateOperation.Serialize());

Console.WriteLine($"Update {digitalTwinId} digital twin response: {updateDigitalTwinResponse.Response.StatusCode}.");

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

DateTimeOffset since = DateTimeOffset.Now.Subtract(TimeSpan.FromMinutes(2));

try
{
  HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders> invokeCommandResponse = await digitalTwinClient
    .InvokeCommandAsync(digitalTwinId, "getMaxMinReport", JsonConvert.SerializeObject(since));

  Console.WriteLine($"Command getMaxMinReport was invoked. \nDevice returned status: {invokeCommandResponse.Body.Status}." +
    $"\nReport: {invokeCommandResponse.Body.Payload}");
}
catch (HttpOperationException e)
{
  if (e.Response.StatusCode == HttpStatusCode.NotFound)
  {
    Console.WriteLine($"Unable to execute command getMaxMinReport on {digitalTwinId}.");
  }
}

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте Thermostat1:

DateTimeOffset since = DateTimeOffset.Now.Subtract(TimeSpan.FromMinutes(2));

try
{
    HttpOperationResponse<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders> invokeCommandResponse = await digitalTwinClient
        .InvokeComponentCommandAsync(digitalTwinId, "thermostat1", "getMaxMinReport", JsonConvert.SerializeObject(since));

    Console.WriteLine("Command getMaxMinReport was invoked on component thermostat1." +
        $"\nDevice returned status: {invokeCommandResponse.Body.Status}. \nReport: {invokeCommandResponse.Body.Payload}");
}
catch (HttpOperationException e)
{
    if (e.Response.StatusCode == HttpStatusCode.NotFound)
    {
        Console.WriteLine("Unable to execute command getMaxMinReport on component thermostat1.");
    }
}

Чтение телеметрии устройства

Устройства IoT Plug and Play отправляют данные телеметрии, определенные в модели DTDL, в центр Интернета вещей. По умолчанию центр Интернета вещей направляет данные телеметрии в конечную точку центров событий, где их можно использовать. Дополнительные сведения см. в разделе Использование маршрутизации сообщений в Центре Интернета вещей для отправки с устройства в облако в разные конечные точки.

В следующем фрагменте кода показано, как считывать данные телеметрии из конечной точки центров событий по умолчанию. Код в этом фрагменте взят из краткого руководства по использованию центра Интернета вещей Отправка данных телеметрии с устройства в центр Интернета вещей и их чтение с помощью серверного приложения:

await using EventHubConsumerClient consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, EventHubName);

Console.WriteLine("Listening for messages on all partitions");

try
{
    await foreach (PartitionEvent partitionEvent in consumer.ReadEventsAsync(cancellationToken))
    {
        Console.WriteLine("Message received on partition {0}:", partitionEvent.Partition.PartitionId);

        string data = Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray());
        Console.WriteLine("\t{0}:", data);

        Console.WriteLine("Application properties (set by device):");
        foreach (var prop in partitionEvent.Data.Properties)
        {
            Console.WriteLine("\t{0}: {1}", prop.Key, prop.Value);
        }

        Console.WriteLine("System properties (set by IoT Hub):");
        foreach (var prop in partitionEvent.Data.SystemProperties)
        {
            Console.WriteLine("\t{0}: {1}", prop.Key, prop.Value);
        }
    }
}
catch (TaskCanceledException)
{
    // This is expected when the token is signaled; it should not be considered an
    // error in this scenario.
}

В следующих выходных данных из предыдущего кода показаны данные телеметрии температуры, отправленные бескомпонентным устройством IoT Plug and Play под названием Thermostat, которое имеет только компонент по умолчанию. Системное свойство dt-dataschema показывает идентификатор модели:

Message received on partition 1:
        { "temperature": 25.5 }:
Application properties (set by device):
System properties (set by IoT Hub):
        iothub-connection-device-id: my-pnp-device
        iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}
        iothub-connection-auth-generation-id: 637375045610235418
        iothub-enqueuedtime: 05/10/2020 14:30:58
        iothub-message-source: Telemetry
        dt-dataschema: dtmi:com:example:Thermostat;1
        content-type: application/json
        content-encoding: utf-8

В следующих выходных данных, полученных с помощью предыдущего кода, показаны данные телеметрии температуры, отправленные с помощью многокомпонентного устройства IoT Plug and Play под названием TemperatureController. Системное свойство dt-subject показывает имя компонента, который отправил телеметрию. В этом примере двумя компонентами являются thermostat1 и thermostat2, которые определены в модели DTDL. Системное свойство dt-dataschema показывает идентификатор модели:

Message received on partition 1:
        {"temperature":11.1}:
Application properties (set by device):
System properties (set by IoT Hub):
        dt-subject: thermostat1
        iothub-connection-device-id: my-pnp-device
        iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}
        iothub-connection-auth-generation-id: 637375045610235418
        iothub-enqueuedtime: 05/10/2020 14:23:36
        iothub-message-source: Telemetry
        dt-dataschema: dtmi:com:example:TemperatureController;1
        content-type: application/json
        content-encoding: utf-8
Message received on partition 1:
        {"temperature":41.2}:
Application properties (set by device):
System properties (set by IoT Hub):
        dt-subject: thermostat2
        iothub-connection-device-id: my-pnp-device
        iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}
        iothub-connection-auth-generation-id: 637375045610235418
        iothub-enqueuedtime: 05/10/2020 14:23:36
        iothub-message-source: Telemetry
        dt-dataschema: dtmi:com:example:TemperatureController;1
        content-type: application/json
        content-encoding: utf-8

Чтение уведомлений об изменениях двойников устройств

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях двойников устройств для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода на языке C# дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Message received on partition 1:
        {"version":3,"properties":{"reported":{"maxTempSinceLastReboot":9.6,"$metadata":{"$lastUpdated":"2020-10-06T10:17:41.7408552Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-06T10:17:41.7408552Z"}},"$version":2}}}:
Application properties (set by device):
        hubName: my-pnp-hub
        deviceId: my-pnp-device
        operationTimestamp: 2020-10-06T10:17:41.7408552+00:00
        iothub-message-schema: twinChangeNotification
        opType: updateTwin
System properties (set by IoT Hub):
        iothub-connection-device-id: my-pnp-device
        iothub-enqueuedtime: 06/10/2020 10:17:41
        iothub-message-source: twinChangeEvents
        user-id: System.ArraySegment`1[System.Byte]
        correlation-id: 61394e8ba7d
        content-type: application/json
        content-encoding: utf-8

Предыдущий фрагмент кода на языке C# дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Message received on partition 1:
        {"version":5,"properties":{"reported":{"thermostat1":{"__t":"c","maxTempSinceLastReboot":9.6},"$metadata":{"$lastUpdated":"2020-10-06T10:27:59.515972Z","thermostat1":{"$lastUpdated":"2020-10-06T10:27:59.515972Z","__t":{"$lastUpdated":"2020-10-06T10:27:59.515972Z"},"maxTempSinceLastReboot":{"$lastUpdated":"2020-10-06T10:27:59.515972Z"}}},"$version":4}}}:
Application properties (set by device):
        hubName: my-pnp-hub
        deviceId: my-pnp-device
        operationTimestamp: 2020-10-06T10:27:59.5159720+00:00
        iothub-message-schema: twinChangeNotification
        opType: updateTwin
System properties (set by IoT Hub):
        iothub-connection-device-id: my-pnp-device
        iothub-enqueuedtime: 06/10/2020 10:27:59
        iothub-message-source: twinChangeEvents
        user-id: System.ArraySegment`1[System.Byte]
        correlation-id: 615051f364e
        content-type: application/json
        content-encoding: utf-8

Чтение уведомлений об изменениях цифровых двойников

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях цифровых двойников для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода на языке C# дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Message received on partition 1:
        [{"op":"add","path":"/$metadata/maxTempSinceLastReboot","value":{"lastUpdateTime":"2020-10-06T10:39:16.0209836Z"}},{"op":"add","path":"/maxTempSinceLastReboot","value":34.9}]:
Application properties (set by device):
        hubName: my-pnp-hub
        deviceId: my-pnp-device
        operationTimestamp: 2020-10-06T10:39:16.0209836+00:00
        iothub-message-schema: digitalTwinChangeNotification
        opType: updateTwin
System properties (set by IoT Hub):
        iothub-connection-device-id: my-pnp-device
        iothub-enqueuedtime: 06/10/2020 10:39:16
        iothub-message-source: digitalTwinChangeEvents
        user-id: System.ArraySegment`1[System.Byte]
        correlation-id: 6169857bf8c
        content-type: application/json-patch+json
        content-encoding: utf-8

Предыдущий фрагмент кода на языке C# дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Message received on partition 1:
        [{"op":"add","path":"/thermostat1","value":{"$metadata":{"maxTempSinceLastReboot":{"lastUpdateTime":"2020-10-06T10:41:44.8312666Z"}},"maxTempSinceLastReboot":29.1}}]:
Application properties (set by device):
        hubName: my-pnp-hub
        deviceId: my-pnp-device
        operationTimestamp: 2020-10-06T10:41:44.8312666+00:00
        iothub-message-schema: digitalTwinChangeNotification
        opType: updateTwin
System properties (set by IoT Hub):
        iothub-connection-device-id: my-pnp-device
        iothub-enqueuedtime: 06/10/2020 10:41:44
        iothub-message-source: digitalTwinChangeEvents
        user-id: System.ArraySegment`1[System.Byte]
        correlation-id: 616f108f0e3
        content-type: application/json-patch+json
        content-encoding: utf-8

Доступны также следующие ресурсы:

Примеры клиентов службы центра Интернета вещей

В этом разделе показаны примеры Java с использованием клиента службы центра Интернета вещей и классов DeviceTwin и DeviceMethod из пространства имен com.microsoft.azure.sdk.iot.service.devicetwin. Используйте класс DeviceTwin для взаимодействия с состоянием устройства с помощью двойников устройства. Вы также можете использовать класс DeviceTwin для запроса регистрации устройств в центре Интернета вещей. Для вызова команд на устройстве используется класс DeviceMethod. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством. Во фрагментах кода переменная deviceId содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение двойника устройства и идентификатора модели

Чтобы получить двойник устройства и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

DeviceTwin twinClient = DeviceTwin.createFromConnectionString(iotHubConnectionString);

// ...

DeviceTwinDevice twin = new DeviceTwinDevice(deviceId);
twinClient.getTwin(twin);
System.out.println("Model Id of this Twin is: " + twin.getModelId());

Обновление двойников устройств

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. Перед обновлением двойника необходимо получить его. Свойство определено в стандартном компоненте устройства:

DeviceTwin twinClient = DeviceTwin.createFromConnectionString(iotHubConnectionString);
DeviceTwinDevice twin = new DeviceTwinDevice(deviceId);
twinClient.getTwin(twin);

double propertyValue = 60.2;
twin.setDesiredProperties(Collections.singleton(new Pair("targetTemperature", propertyValue)));
twinClient.updateTwin(twin);

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. Перед обновлением двойника необходимо получить его. Свойство определено в компоненте thermostat1:

public static Set<Pair> CreateComponentPropertyPatch(@NonNull String propertyName, @NonNull double propertyValue, @NonNull String componentName)
{
    JsonObject patchJson = new JsonObject();
    patchJson.addProperty("__t", "c");
    patchJson.addProperty(propertyName, propertyValue);
    return singleton(new Pair(componentName, patchJson));
}

// ...

DeviceTwin twinClient = DeviceTwin.createFromConnectionString(iotHubConnectionString);
DeviceTwinDevice twin = new DeviceTwinDevice(deviceId);
twinClient.getTwin(twin);

double propertyValue = 60.2;
twin.setDesiredProperties(CreateComponentPropertyPatch("targetTemperature", propertyValue, "thermostat1"));
twinClient.updateTwin(twin);

Исправление свойства в компоненте выглядит так, как показано в следующем примере:

{
  "thermostat1":
  {
    "__t": "c",
    "targetTemperature": 60.2
  }
}

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

DeviceMethod methodClient = DeviceMethod.createFromConnectionString(iotHubConnectionString);

Long responseTimeout = TimeUnit.SECONDS.toSeconds(200);
Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);

String commandInput = ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(5).format(DateTimeFormatter.ISO_DATE_TIME);
MethodResult result = methodClient.invoke(deviceId, "getMaxMinReport", responseTimeout, connectTimeout, commandInput);

System.out.println("Method result status is: " + result.getStatus());

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

DeviceMethod methodClient = DeviceMethod.createFromConnectionString(iotHubConnectionString);

Long responseTimeout = TimeUnit.SECONDS.toSeconds(200);
Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);

String commandInput = ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(5).format(DateTimeFormatter.ISO_DATE_TIME);
MethodResult result = methodClient.invoke(deviceId, "thermostat1*getMaxMinReport", responseTimeout, connectTimeout, commandInput);

System.out.println("Method result status is: " + result.getStatus());

Примеры цифровых двойников в центре Интернета вещей

Используйте класс DigitalTwinAsyncClient в пространстве имен com.microsoft.azure.sdk.iot.service.digitaltwin для взаимодействия с состоянием устройства с помощью цифровых двойников. В следующих примерах также используются классы UpdateOperationUtility и BasicDigitalTwin из одного и того же пространства имен. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством.

Переменная digitalTwinid содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение цифрового двойника и идентификатора модели

Чтобы получить цифровой двойник и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

DigitalTwinAsyncClient asyncClient = DigitalTwinAsyncClient.createFromConnectionString(iotHubConnectionString);

CountDownLatch latch = new CountDownLatch(1);
asyncClient.getDigitalTwin(digitalTwinid, BasicDigitalTwin.class)
    .subscribe(
        getResponse ->
        {
            System.out.println("Digital Twin Model Id: " + getResponse.getMetadata().getModelId());
            System.out.println("Digital Twin: " + prettyBasicDigitalTwin(getResponse));
            latch.countDown();
        },
        error ->
        {
            System.out.println("Get Digital Twin failed: " + error);
            latch.countDown();
        });

latch.await(10, TimeUnit.SECONDS);

// ...

private static String prettyBasicDigitalTwin(BasicDigitalTwin basicDigitalTwin)
{
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    return gson.toJson(basicDigitalTwin);
}

Обновление цифрового двойника

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. Свойство определено в стандартном компоненте устройства:

DigitalTwinAsyncClient asyncClient = DigitalTwinAsyncClient.createFromConnectionString(iotHubConnectionString);

CountDownLatch latch1 = new CountDownLatch(1);

UpdateOperationUtility updateOperationUtility = new UpdateOperationUtility();

// Add a new property.
updateOperationUtility.appendAddPropertyOperation("/" + "targetTemperature", 35);
asyncClient.updateDigitalTwin(digitalTwinid, updateOperationUtility.getUpdateOperations())
    .subscribe(
        getResponse ->
        {
            System.out.println("Updated Digital Twin");
            latch1.countDown();
        },
        error ->
        {
            System.out.println("Update Digital Twin failed: " + error);
            latch1.countDown();
        });
latch1.await(10, TimeUnit.SECONDS);
GetDigitalTwin();

// Replace an existing property.
CountDownLatch latch2 = new CountDownLatch(1);
updateOperationUtility.appendReplacePropertyOperation("/targetTemperature", 50);
asyncClient.updateDigitalTwin(digitalTwinid, updateOperationUtility.getUpdateOperations())
    .subscribe(
        getResponse ->
        {
            System.out.println("Updated Digital Twin");
            latch2.countDown();
        },
        error ->
        {
            System.out.println("Update Digital Twin failed: " + error);
            latch2.countDown();
        });

latch2.await(10, TimeUnit.SECONDS);
GetDigitalTwin();

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. Свойство определено в компоненте thermostat1:

DigitalTwinClient client = DigitalTwinClient.createFromConnectionString(iotHubConnectionString);

// Get digital twin.
ServiceResponseWithHeaders<String, DigitalTwinGetHeaders> getResponse = client.getDigitalTwinWithResponse(digitalTwinid, String.class);

// Construct the options for conditional update.
DigitalTwinUpdateRequestOptions options = new DigitalTwinUpdateRequestOptions();
options.setIfMatch(getResponse.headers().eTag());

UpdateOperationUtility updateOperationUtility = new UpdateOperationUtility();

Map<String, Object> t1properties = new HashMap<>();
t1properties.put("targetTemperature", 50);
updateOperationUtility.appendReplaceComponentOperation("/thermostat1", t1properties);

digitalTwinUpdateOperations = updateOperationUtility.getUpdateOperations();
updateResponse = client.updateDigitalTwinWithResponse(digitalTwinid, digitalTwinUpdateOperations, options);
System.out.println("Update Digital Twin response status: " + updateResponse.response().message());

getResponse = client.getDigitalTwinWithResponse(digitalTwinid, String.class);

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

CountDownLatch latch = new CountDownLatch(1);

String commandInput = ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(5).format(DateTimeFormatter.ISO_DATE_TIME);

// Invoke a method on root level.
asyncClient.invokeCommand(digitalTwinid, "getMaxMinReport", commandInput)
    .subscribe(
        response ->
        {
            System.out.println("Invoked Command getMaxMinReport response: " + prettyString(response.getPayload()));
            latch.countDown();
        },
        error ->
        {
            RestException ex = (RestException)error;
            if(ex.response().code() == 404) {
                System.out.println("Invoked Command getMaxMinReport failed: " + error);
            }
            else {
                System.out.println("Ensure the device sample is running for this sample to succeed");
            }
            latch.countDown();
        });

latch.await(10, TimeUnit.SECONDS);

// ...

private static String prettyString(String str)
{
    Gson gson = new Gson();
    Gson gsonBuilder = new GsonBuilder().setPrettyPrinting().create();
    return gsonBuilder.toJson(gson.fromJson(str, Object.class));
}

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

DigitalTwinClient client = DigitalTwinClient.createFromConnectionString(iotHubConnectionString);

String commandInput = ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(5).format(DateTimeFormatter.ISO_DATE_TIME);

DigitalTwinInvokeCommandRequestOptions options = new DigitalTwinInvokeCommandRequestOptions();
try {
    ServiceResponseWithHeaders<DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders> commandResponse = client.invokeComponentCommandWithResponse(digitalTwinid, "thermostat1", "getMaxMinReport", commandInput, options);
    System.out.println("Command getMaxMinReport, payload: " + prettyString(commandResponse.body().getPayload()));
    System.out.println("Command getMaxMinReport, status: " + commandResponse.body().getStatus());
} catch (RestException ex)
{
    if(ex.response().code() == 404)
    {
        System.out.println("Ensure the device sample is running for this sample to succeed.");
    }
    else
    {
        throw ex;
    }
}

// ...

private static String prettyString(String str)
{
    Gson gson = new Gson();
    Gson gsonBuilder = new GsonBuilder().setPrettyPrinting().create();
    return gsonBuilder.toJson(gson.fromJson(str, Object.class));
}

Чтение телеметрии устройства

Устройства IoT Plug and Play отправляют данные телеметрии, определенные в модели DTDL, в центр Интернета вещей. По умолчанию центр Интернета вещей направляет данные телеметрии в конечную точку центров событий, где их можно использовать. Дополнительные сведения см. в разделе Использование маршрутизации сообщений в Центре Интернета вещей для отправки с устройства в облако в разные конечные точки.

В следующем фрагменте кода показано, как считывать данные телеметрии из конечной точки центров событий по умолчанию. Код в этом фрагменте взят из краткого руководства по использованию центра Интернета вещей Отправка данных телеметрии с устройства в центр Интернета вещей и их чтение с помощью серверного приложения:

import com.azure.messaging.eventhubs.EventHubClientBuilder;
import com.azure.messaging.eventhubs.EventHubConsumerAsyncClient;

// ...

EventHubClientBuilder eventHubClientBuilder = new EventHubClientBuilder()
    .consumerGroup(EventHubClientBuilder.DEFAULT_CONSUMER_GROUP_NAME)
    .connectionString(eventHubCompatibleConnectionString);

try (EventHubConsumerAsyncClient eventHubConsumerAsyncClient = eventHubClientBuilder.buildAsyncConsumerClient()) {

    receiveFromAllPartitions(eventHubConsumerAsyncClient);

}

// ...

private static void receiveFromAllPartitions(EventHubConsumerAsyncClient eventHubConsumerAsyncClient) {

eventHubConsumerAsyncClient
    .receive(false) // set this to false to read only the newly available events
    .subscribe(partitionEvent -> {
        System.out.println();
        System.out.printf("%nTelemetry received from partition %s:%n%s",
            partitionEvent.getPartitionContext().getPartitionId(), partitionEvent.getData().getBodyAsString());
        System.out.printf("%nApplication properties (set by device):%n%s", partitionEvent.getData().getProperties());
        System.out.printf("%nSystem properties (set by IoT Hub):%n%s",
            partitionEvent.getData().getSystemProperties());
    }, ex -> {
        System.out.println("Error receiving events " + ex);
    }, () -> {
        System.out.println("Completed receiving events");
    });
}

В следующих выходных данных из предыдущего кода показаны данные телеметрии температуры, отправленные бескомпонентным устройством IoT Plug and Play под названием Thermostat, которое имеет только компонент по умолчанию. Системное свойство dt-dataschema показывает идентификатор модели:

Telemetry received from partition 1:
{"temperature": 10.700000}
Application properties (set by device):
{$.cdid=my-pnp-device}
System properties (set by IoT Hub):
{correlation-id=dd960185-6ddb-4b5f-89bb-e26b0b3c201e, content-encoding=UTF-8, iothub-connection-auth-method={"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}, iothub-enqueuedtime=Tue Oct 20 12:28:10 BST 2020, dt-dataschema=dtmi:com:example:Thermostat;1, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, iothub-connection-auth-generation-id=637375776990653481, group-sequence=0, iothub-message-source=Telemetry, creation-time=0, message-id=1c05cece-070b-4e2e-b2e8-e263858594a3, content-type=application/json}

Telemetry received from partition 1:
{"temperature": 10.700000}
Application properties (set by device):
{$.cdid=my-pnp-device}
System properties (set by IoT Hub):
{correlation-id=d10a7350-43ef-4cf6-9db5-a4b08684cd9d, content-encoding=UTF-8, iothub-connection-auth-method={"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}, iothub-enqueuedtime=Tue Oct 20 12:28:15 BST 2020, dt-dataschema=dtmi:com:example:Thermostat;1, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, iothub-connection-auth-generation-id=637375776990653481, group-sequence=0, iothub-message-source=Telemetry, creation-time=0, message-id=d3a80af4-1246-41a0-a09a-582a12c17a00, content-type=application/json}

В следующих выходных данных, полученных с помощью предыдущего кода, показаны данные телеметрии температуры, отправленные с помощью многокомпонентного устройства IoT Plug and Play под названием TemperatureController. Системное свойство dt-subject показывает имя компонента, который отправил телеметрию. В этом примере двумя компонентами являются thermostat1 и thermostat2, которые определены в модели DTDL. Системное свойство dt-dataschema показывает идентификатор модели:

Telemetry received from partition 1:
null
Application properties (set by device):
{$.cdid=my-pnp-device}
System properties (set by IoT Hub):
{correlation-id=413002d0-2107-4c08-8f4a-995ae1f4047b, content-encoding=UTF-8, iothub-connection-auth-method={"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}, iothub-enqueuedtime=Tue Oct 20 12:31:14 BST 2020, dt-dataschema=dtmi:com:example:TemperatureController;1, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, iothub-connection-auth-generation-id=637387902591517456, group-sequence=0, iothub-message-source=Telemetry, creation-time=0, message-id=da8bd068-850e-43fb-862f-66080d5969e4, content-type=application/json, dt-subject=thermostat1}

Telemetry received from partition 1:
null
Application properties (set by device):
{$.cdid=my-pnp-device}
System properties (set by IoT Hub):
{correlation-id=2d9407e5-413f-4f8d-bd30-cd153e03c72f, content-encoding=UTF-8, iothub-connection-auth-method={"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}, iothub-enqueuedtime=Tue Oct 20 12:31:14 BST 2020, dt-dataschema=dtmi:com:example:TemperatureController;1, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, iothub-connection-auth-generation-id=637387902591517456, group-sequence=0, iothub-message-source=Telemetry, creation-time=0, message-id=ed419c4e-ef2c-4acf-8991-6245059c5fdc, content-type=application/json, dt-subject=thermostat2}

Чтение уведомлений об изменениях двойников устройств

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях двойников устройств для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода Java дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received from partition 1:
{"version":11,"properties":{"reported":{"maxTempSinceLastReboot":43.4,"$metadata":{"$lastUpdated":"2020-10-20T11:50:41.123127Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-20T11:50:41.123127Z"}},"$version":10}}}
Application properties (set by device):
{operationTimestamp=2020-10-20T11:50:41.1231270+00:00, opType=updateTwin, hubName=my-pnp-hub, deviceId=my-pnp-device, iothub-message-schema=twinChangeNotification}
System properties (set by IoT Hub):
{user-id=[B@12fd5bb4, correlation-id=11339418426a, content-encoding=utf-8, iothub-enqueuedtime=Tue Oct 20 12:50:41 BST 2020, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, group-sequence=0, iothub-message-source=twinChangeEvents, creation-time=0, content-type=application/json}

Предыдущий фрагмент кода Java дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received from partition 1:
{"version":9,"properties":{"reported":{"thermostat1":{"__t":"c","maxTempSinceLastReboot":32.5},"$metadata":{"$lastUpdated":"2020-10-20T11:48:01.2960851Z","thermostat1":{"$lastUpdated":"2020-10-20T11:48:01.2960851Z","__t":{"$lastUpdated":"2020-10-20T11:48:01.2960851Z"},"maxTempSinceLastReboot":{"$lastUpdated":"2020-10-20T11:48:01.2960851Z"}}},"$version":8}}}
Application properties (set by device):
{operationTimestamp=2020-10-20T11:48:01.2960851+00:00, opType=updateTwin, hubName=my-pnp-hub, deviceId=my-pnp-device, iothub-message-schema=twinChangeNotification}
System properties (set by IoT Hub):
{user-id=[B@23949bae, correlation-id=113334d542e1, content-encoding=utf-8, iothub-enqueuedtime=Tue Oct 20 12:48:01 BST 2020, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, group-sequence=0, iothub-message-source=twinChangeEvents, creation-time=0, content-type=application/json}

Чтение уведомлений об изменениях цифровых двойников

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях цифровых двойников для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода Java дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received from partition 1:
[{"op":"replace","path":"/$metadata/maxTempSinceLastReboot/lastUpdateTime","value":"2020-10-20T11:52:40.627628Z"},{"op":"replace","path":"/maxTempSinceLastReboot","value":16.9}]
Application properties (set by device):
{operationTimestamp=2020-10-20T11:52:40.6276280+00:00, opType=updateTwin, hubName=my-pnp-hub, deviceId=my-pnp-device, iothub-message-schema=digitalTwinChangeNotification}
System properties (set by IoT Hub):
{user-id=[B@4475ce2a, correlation-id=1133db52c0e0, content-encoding=utf-8, iothub-enqueuedtime=Tue Oct 20 12:52:40 BST 2020, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, group-sequence=0, iothub-message-source=digitalTwinChangeEvents, creation-time=0, content-type=application/json-patch+json}

Предыдущий фрагмент кода Java дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received from partition 1:
[{"op":"add","path":"/thermostat1","value":{"$metadata":{"maxTempSinceLastReboot":{"lastUpdateTime":"2020-10-20T11:31:04.7811405Z"}},"maxTempSinceLastReboot":27.2}}]
Application properties (set by device):
{operationTimestamp=2020-10-20T11:31:04.7811405+00:00, opType=updateTwin, hubName=my-pnp-hub, deviceId=my-pnp-device, iothub-message-schema=digitalTwinChangeNotification}
System properties (set by IoT Hub):
{user-id=[B@75981aa, correlation-id=1130d6f4d212, content-encoding=utf-8, iothub-enqueuedtime=Tue Oct 20 12:31:04 BST 2020, absolute-expiry-time=0, iothub-connection-device-id=my-pnp-device, group-sequence=0, iothub-message-source=digitalTwinChangeEvents, creation-time=0, content-type=application/json-patch+json}

Доступны также следующие ресурсы:

Примеры клиентов службы центра Интернета вещей

В этом разделе приведены примеры JavaScript с использованием клиента службы центра Интернета вещей, а также классов Реестр и Клиент. Используйте класс Реестр для взаимодействия с состоянием устройства с помощью двойников устройства. Вы также можете использовать класс Реестр для запроса регистрации устройств в центре Интернета вещей. Для вызова команд на устройстве используется класс Клиент. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством. Во фрагментах кода переменная deviceId содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение двойника устройства и идентификатора модели

Чтобы получить двойник устройства и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

var Registry = require('azure-iothub').Registry;

// ...

var registry = Registry.fromConnectionString(connectionString);
registry.getTwin(deviceId, function(err, twin) {
  if (err) {
    console.error(err.message);
  } else {
    console.log('Model Id: ' + twin.modelId);
    console.log(JSON.stringify(twin, null, 2));
  }
}

Обновление двойников устройств

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. В этом примере показано, как получить двойника перед обновлением. Свойство определено в стандартном компоненте устройства:

var Registry = require('azure-iothub').Registry;
var registry = Registry.fromConnectionString(connectionString);

registry.getTwin(deviceId, function(err, twin) {
  if (err) {
    console.error(err.message);
  } else {
    var twinPatch = {
      properties: {
        desired: {
          targetTemperature: 42
        }
      }
    };
    twin.update(twinPatch, function(err, twin) {
      if (err) {
        console.error(err.message);
      } else {
        console.log(JSON.stringify(twin, null, 2));
      }
    }
  }
}

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. В этом примере показано, как получить двойника перед обновлением. Свойство определено в компоненте thermostat1:

var Registry = require('azure-iothub').Registry;
var registry = Registry.fromConnectionString(connectionString);

registry.getTwin(deviceId, function(err, twin) {
  if (err) {
    console.error(err.message);
  } else {
    var twinPatch = {
      properties: {
        desired: {
          thermostat1:
          {
            __t: "c",
            targetTemperature: 45
          }
        }
      }
    };
    twin.update(twinPatch, function(err, twin) {
      if (err) {
        console.error(err.message);
      } else {
        console.log(JSON.stringify(twin, null, 2));
      }
    }
  }
}

Исправление свойства в компоненте выглядит так, как показано в следующем примере:

{
  "thermostat1":
  {
    "__t": "c",
    "targetTemperature": 20
  }
}

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

var Client = require('azure-iothub').Client;

// ...

var client = Client.fromConnectionString(connectionString);

var methodParams = {
  methodName: "getMaxMinReport",
  payload: new Date().getMinutes -2,
  responseTimeoutInSeconds: 15
};

client.invokeDeviceMethod(deviceId, methodParams, function (err, result) {
  if (err) {
    console.error('Failed to invoke method \'' + methodParams.methodName + '\': ' + err.message);
  } else {
    console.log(methodParams.methodName + ' on ' + deviceId + ':');
    console.log(JSON.stringify(result, null, 2));
  }
});

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

var Client = require('azure-iothub').Client;

// ...

var client = Client.fromConnectionString(connectionString);

var methodParams = {
  methodName: "thermostat1*getMaxMinReport",
  payload: new Date().getMinutes -2,
  responseTimeoutInSeconds: 15
};

client.invokeDeviceMethod(deviceId, methodParams, function (err, result) {
  if (err) {
    console.error('Failed to invoke method \'' + methodParams.methodName + '\': ' + err.message);
  } else {
    console.log(methodParams.methodName + ' on ' + deviceId + ':');
    console.log(JSON.stringify(result, null, 2));
  }
});

Примеры цифровых двойников в центре Интернета вещей

Для взаимодействия с состоянием устройства с помощью цифровых двойников используется класс DigitalTwinClient. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством.

В этом разделе показаны примеры JavaScript с использованием API цифровых двойников.

Переменная digitalTwinId содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение цифрового двойника и идентификатора модели

Чтобы получить цифровой двойник и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

const IoTHubTokenCredentials = require('azure-iothub').IoTHubTokenCredentials;
const DigitalTwinClient = require('azure-iothub').DigitalTwinClient;
const { inspect } = require('util');

// ...

const credentials = new IoTHubTokenCredentials(connectionString);
const digitalTwinClient = new DigitalTwinClient(credentials);

const digitalTwin = await digitalTwinClient.getDigitalTwin(digitalTwinId);

console.log(inspect(digitalTwin));
console.log('Model Id: ' + inspect(digitalTwin.$metadata.$model));

Обновление цифрового двойника

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. Свойство определено в стандартном компоненте устройства:

const IoTHubTokenCredentials = require('azure-iothub').IoTHubTokenCredentials;
const DigitalTwinClient = require('azure-iothub').DigitalTwinClient;

// ...

const credentials = new IoTHubTokenCredentials(connString);
const digitalTwinClient = new DigitalTwinClient(credentials);

const patch = [{
  op: 'add',
  path: '/targetTemperature',
  value: 42
}];
await digitalTwinClient.updateDigitalTwin(digitalTwinId, patch);

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. Свойство определено в компоненте thermostat1:

const IoTHubTokenCredentials = require('azure-iothub').IoTHubTokenCredentials;
const DigitalTwinClient = require('azure-iothub').DigitalTwinClient;

// ...

const credentials = new IoTHubTokenCredentials(connString);
const digitalTwinClient = new DigitalTwinClient(credentials);

const patch = [{
  op: 'add',
  path: '/thermostat1/targetTemperature',
  value: 42
}];
await digitalTwinClient.updateDigitalTwin(digitalTwinId, patch);

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

const IoTHubTokenCredentials = require('azure-iothub').IoTHubTokenCredentials;
const DigitalTwinClient = require('azure-iothub').DigitalTwinClient;
const { inspect } = require('util');

// ...

const commandPayload = new Date().getMinutes -2;

const credentials = new IoTHubTokenCredentials(connectionString);
const digitalTwinClient = new DigitalTwinClient(credentials);

const options = {
  connectTimeoutInSeconds: 30,
  responseTimeoutInSeconds: 40
};
const commandResponse = await digitalTwinClient.invokeCommand(digitalTwinId, "getMaxMinReport", commandPayload, options);

console.log(inspect(commandResponse));

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

const IoTHubTokenCredentials = require('azure-iothub').IoTHubTokenCredentials;
const DigitalTwinClient = require('azure-iothub').DigitalTwinClient;
const { inspect } = require('util');

// ...

const commandPayload = new Date().getMinutes -2;

const credentials = new IoTHubTokenCredentials(connectionString);
const digitalTwinClient = new DigitalTwinClient(credentials);

const options = {
  connectTimeoutInSeconds: 30,
  responseTimeoutInSeconds: 40
};
const commandResponse = await digitalTwinClient.invokeComponentCommand(digitalTwinId, "thermostat1", "getMaxMinReport", commandPayload, options);

console.log(inspect(commandResponse));

Чтение телеметрии устройства

Устройства IoT Plug and Play отправляют данные телеметрии, определенные в модели DTDL, в центр Интернета вещей. По умолчанию центр Интернета вещей направляет данные телеметрии в конечную точку центров событий, где их можно использовать. Дополнительные сведения см. в разделе Использование маршрутизации сообщений в Центре Интернета вещей для отправки с устройства в облако в разные конечные точки.

В следующем фрагменте кода показано, как считывать данные телеметрии из конечной точки центров событий по умолчанию. Код в этом фрагменте взят из краткого руководства по использованию центра Интернета вещей Отправка данных телеметрии с устройства в центр Интернета вещей и их чтение с помощью серверного приложения:

const { EventHubConsumerClient } = require("@azure/event-hubs");

var printError = function (err) {
  console.log(err.message);
};

var printMessages = function (messages) {
  for (const message of messages) {
    console.log("Telemetry received: ");
    console.log(JSON.stringify(message.body));
    console.log("Properties (set by device): ");
    console.log(JSON.stringify(message.properties));
    console.log("System properties (set by IoT Hub): ");
    console.log(JSON.stringify(message.systemProperties));
    console.log("");
  }
};

// ...

const clientOptions = {};

const consumerClient = new EventHubConsumerClient("$Default", connectionString, clientOptions);

consumerClient.subscribe({
  processEvents: printMessages,
  processError: printError,
});

В следующих выходных данных, полученных с помощью предыдущего кода, показаны данные телеметрии температуры, отправленные с помощью многокомпонентного устройства IoT Plug and Play под названием TemperatureController. Системное свойство dt-subject показывает имя компонента, который отправил телеметрию. В этом примере двумя компонентами являются thermostat1 и thermostat2, которые определены в модели DTDL. Системное свойство dt-dataschema показывает идентификатор модели:

Telemetry received:
{"temperature":68.77370855171125}
Properties (set by device):
undefined
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-connection-auth-method":"{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}","iothub-connection-auth-generation-id":"637388034455888246","iothub-enqueuedtime":1603206669320,"iothub-message-source":"Telemetry","dt-subject":"thermostat1","dt-dataschema":"dtmi:com:example:TemperatureController;1","contentType":"application/json","contentEncoding":"utf-8"}

Telemetry received:
{"temperature":30.833394506549226}
Properties (set by device):
undefined
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-connection-auth-method":"{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}","iothub-connection-auth-generation-id":"637388034455888246","iothub-enqueuedtime":1603206665835,"iothub-message-source":"Telemetry","dt-subject":"thermostat2","dt-dataschema":"dtmi:com:example:TemperatureController;1","contentType":"application/json","contentEncoding":"utf-8"}

Чтение уведомлений об изменениях двойников устройств

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях двойников устройств для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода JavaScript дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received:
{"version":4,"properties":{"reported":{"maxTempSinceLastReboot":42.1415152639582,"$metadata":{"$lastUpdated":"2020-10-21T10:01:40.1281138Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-21T10:01:40.1281138Z"}},"$version":3}}}
Properties (set by device):
{"hubName":"my-pnp-hub","deviceId":"my-pnp-device","operationTimestamp":"2020-10-21T10:01:40.1281138+00:00","iothub-message-schema":"twinChangeNotification","opType":"updateTwin"}
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-enqueuedtime":1603274500282,"iothub-message-source":"twinChangeEvents","userId":{"type":"Buffer","data":[109,121,45,112,110,112,45,104,117,98]},"correlationId":"11ed82d13f50","contentType":"application/json","contentEncoding":"utf-8"}

Предыдущий фрагмент кода JavaScript дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received:
{"version":4,"properties":{"reported":{"thermostat1":{"maxTempSinceLastReboot":3.5592971602417913,"__t":"c"},"$metadata":{"$lastUpdated":"2020-10-21T10:07:51.8284866Z","thermostat1":{"$lastUpdated":"2020-10-21T10:07:51.8284866Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-21T10:07:51.8284866Z"},"__t":{"$lastUpdated":"2020-10-21T10:07:51.8284866Z"}}},"$version":3}}}
Properties (set by device):
{"hubName":"my-pnp-hub","deviceId":"my-pnp-device","operationTimestamp":"2020-10-21T10:07:51.8284866+00:00","iothub-message-schema":"twinChangeNotification","opType":"updateTwin"}
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-enqueuedtime":1603274871951,"iothub-message-source":"twinChangeEvents","userId":{"type":"Buffer","data":[109,121,45,112,110,112,45,104,117,98]},"correlationId":"11ee605b195f","contentType":"application/json","contentEncoding":"utf-8"}

Чтение уведомлений об изменениях цифровых двойников

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях цифровых двойников для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода JavaScript дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received:
[{"op":"add","path":"/$metadata/maxTempSinceLastReboot","value":{"lastUpdateTime":"2020-10-21T10:01:40.1281138Z"}},{"op":"add","path":"/maxTempSinceLastReboot","value":42.1415152639582}]
Properties (set by device):
{"hubName":"my-pnp-hub","deviceId":"my-pnp-device","operationTimestamp":"2020-10-21T10:01:40.1281138+00:00","iothub-message-schema":"digitalTwinChangeNotification","opType":"updateTwin"}
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-enqueuedtime":1603274500282,"iothub-message-source":"digitalTwinChangeEvents","userId":{"type":"Buffer","data":[109,121,45,112,110,112,45,104,117,98]},"correlationId":"11ed82d13f50","contentType":"application/json-patch+json","contentEncoding":"utf-8"}

Предыдущий фрагмент кода JavaScript дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Telemetry received:
[{"op":"add","path":"/thermostat1","value":{"$metadata":{"maxTempSinceLastReboot":{"lastUpdateTime":"2020-10-21T10:07:51.8284866Z"}},"maxTempSinceLastReboot":3.5592971602417913}}]
Properties (set by device):
{"hubName":"my-pnp-hub","deviceId":"my-pnp-device","operationTimestamp":"2020-10-21T10:07:51.8284866+00:00","iothub-message-schema":"digitalTwinChangeNotification","opType":"updateTwin"}
System properties (set by IoT Hub):
{"iothub-connection-device-id":"my-pnp-device","iothub-enqueuedtime":1603274871951,"iothub-message-source":"digitalTwinChangeEvents","userId":{"type":"Buffer","data":[109,121,45,112,110,112,45,104,117,98]},"correlationId":"11ee605b195f","contentType":"application/json-patch+json","contentEncoding":"utf-8"}

Доступны также следующие ресурсы:

Примеры клиентов службы центра Интернета вещей

В этом разделе показаны примеры Python с использованием клиента службы центра Интернета вещей и классов IoTHubRegistryManager и CloudToDeviceMethod. Используйте класс IoTHubRegistryManager для взаимодействия с состоянием устройства с помощью двойников устройства. Вы также можете использовать класс IoTHubRegistryManager для запроса регистрации устройств в центре Интернета вещей. Для вызова команд на устройстве используется класс CloudToDeviceMethod. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством. Во фрагментах кода переменная device_id содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение двойника устройства и идентификатора модели

Чтобы получить двойник устройства и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import Twin, TwinProperties

iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

# ...

twin = iothub_registry_manager.get_twin(device_id)
print("The device twin is: ")
print("")
print(twin)
print("")

additional_props = twin.additional_properties
if "modelId" in additional_props:
    print("The Model ID for this device is:")
    print(additional_props["modelId"])
    print("")

Обновление двойников устройств

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. В этом примере показано, как получить etag двойника перед его обновлением. Свойство определено в стандартном компоненте устройства:

iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

twin = iothub_registry_manager.get_twin(device_id)

twin_patch = Twin()

twin_patch.properties = TwinProperties(
    desired={"targetTemperature": 42}
)
updated_twin = iothub_registry_manager.update_twin(device_id, twin_patch, twin.etag)

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. В этом примере показано, как получить ETag двойника перед его обновлением. Свойство определено в компоненте thermostat1:

iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

twin = iothub_registry_manager.get_twin(device_id)

twin_patch = Twin()

twin_patch.properties = TwinProperties(
    desired={ "thermostat1": {
        "__t": "c",
        "targetTemperature": 42}
    }
)
updated_twin = iothub_registry_manager.update_twin(device_id, twin_patch, twin.etag)

Исправление свойства в компоненте выглядит так, как показано в следующем примере:

{
"thermostat1":
  {
    "__t": "c",
    "targetTemperature": 20
  }
}

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod

# ...

iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

method_payload = datetime.datetime.now() - datetime.timedelta(minutes=2)
device_method = CloudToDeviceMethod(method_name="getMaxMinReport", payload=method_payload)
result = iothub_registry_manager.invoke_device_method(device_id, device_method)
print(result.payload)

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod

# ...

iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

method_payload = datetime.datetime.now() - datetime.timedelta(minutes=2)
device_method = CloudToDeviceMethod(method_name="thermostat1*getMaxMinReport", payload=method_payload)
result = iothub_registry_manager.invoke_device_method(device_id, device_method)
print(result.payload)

Примеры цифровых двойников в центре Интернета вещей

Для взаимодействия с состоянием устройства с помощью цифровых двойников используется класс DigitalTwinClient. Модель DTDL для устройства определяет свойства и команды, выполняемые устройством.

Переменная device_id содержит идентификатор устройства IoT Plug and Play, зарегистрированного в центре Интернета вещей.

Получение цифрового двойника и идентификатора модели

Чтобы получить цифровой двойник и идентификатор модели для устройства IoT Plug and Play, подключенного к центру Интернета вещей:

from azure.iot.hub import DigitalTwinClient

digital_twin_client = DigitalTwinClient(iothub_connection_str)

digital_twin = digital_twin_client.get_digital_twin(device_id)
if digital_twin:
    print(digital_twin)
    print("Model Id: " + digital_twin["$metadata"]["$model"])
else:
    print("No digital_twin found")

Обновление цифрового двойника

В следующем фрагменте кода показано, как обновить свойство targetTemperature на устройстве. Свойство определено в стандартном компоненте устройства:

from azure.iot.hub import DigitalTwinClient

digital_twin_client = DigitalTwinClient(iothub_connection_str)

patch = [{"op": "add", "path": "/targetTemperature", "value": 42}]
digital_twin_client.update_digital_twin(device_id, patch)

В следующем фрагменте кода показано, как обновить свойство targetTemperature на компоненте. Свойство определено в компоненте thermostat1:

from azure.iot.hub import DigitalTwinClient

digital_twin_client = DigitalTwinClient(iothub_connection_str)

patch = [{"op": "add", "path": "/targetTemperature", "value": 42}]
digital_twin_client.update_digital_twin(device_id, patch)

Вызов команды

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport, определенную в компоненте по умолчанию:

from azure.iot.hub import DigitalTwinClient

payload = datetime.datetime.now() - datetime.timedelta(minutes=2)

connect_timeout_in_seconds = 3
response_timeout_in_seconds = 7


digital_twin_client = DigitalTwinClient(iothub_connection_str)

invoke_command_result = digital_twin_client.invoke_command(
    device_id, "getMaxMinReport", payload, connect_timeout_in_seconds, response_timeout_in_seconds
)
if invoke_command_result:
    print(invoke_command_result)
else:
    print("No invoke_command_result found")

В следующем фрагменте кода показано, как вызвать команду getMaxMinReport для компонента. Команда определена в компоненте thermostat1:

from azure.iot.hub import DigitalTwinClient

payload = datetime.datetime.now() - datetime.timedelta(minutes=2)

connect_timeout_in_seconds = 3
response_timeout_in_seconds = 7


digital_twin_client = DigitalTwinClient(iothub_connection_str)

invoke_command_result = digital_twin_client.invoke_component_command(
    device_id, "thermostat1", "getMaxMinReport", payload, connect_timeout_in_seconds, response_timeout_in_seconds
)
if invoke_command_result:
    print(invoke_command_result)
else:
    print("No invoke_command_result found")

Чтение телеметрии устройства

Устройства IoT Plug and Play отправляют данные телеметрии, определенные в модели DTDL, в центр Интернета вещей. По умолчанию центр Интернета вещей направляет данные телеметрии в конечную точку центров событий, где их можно использовать. Дополнительные сведения см. в разделе Использование маршрутизации сообщений в Центре Интернета вещей для отправки с устройства в облако в разные конечные точки.

В следующем фрагменте кода показано, как считывать данные телеметрии из конечной точки центров событий по умолчанию. Код в этом фрагменте взят из краткого руководства по использованию центра Интернета вещей Отправка данных телеметрии с устройства в центр Интернета вещей и их чтение с помощью серверного приложения:

import asyncio
from azure.eventhub import TransportType
from azure.eventhub.aio import EventHubConsumerClient

# Define callbacks to process events
async def on_event_batch(partition_context, events):
    for event in events:
        print("Received event from partition: {}.".format(partition_context.partition_id))
        print("Telemetry received: ", event.body_as_str())
        print("Properties (set by device): ", event.properties)
        print("System properties (set by IoT Hub): ", event.system_properties)
        print()
    await partition_context.update_checkpoint()

async def on_error(partition_context, error):
    # ...

loop = asyncio.get_event_loop()
client = EventHubConsumerClient.from_connection_string(
    conn_str=CONNECTION_STR,
    consumer_group="$default",
)

try:
    loop.run_until_complete(client.receive_batch(on_event_batch=on_event_batch, on_error=on_error))
except KeyboardInterrupt:
    print("Receiving has stopped.")
finally:
    loop.run_until_complete(client.close())
    loop.stop()

В следующих выходных данных из предыдущего кода показаны данные телеметрии температуры, отправленные бескомпонентным устройством IoT Plug and Play под названием Thermostat, которое имеет только компонент по умолчанию. Системное свойство dt-dataschema показывает идентификатор модели:

Received event from partition: 1.
Telemetry received:  {"temperature": 12}
Properties (set by device):  None
System properties (set by IoT Hub):  {b'content-type': b'application/json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-connection-auth-method': b'{"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}', b'iothub-connection-auth-generation-id': b'637388855582764406', b'iothub-enqueuedtime': 1603288810715, b'iothub-message-source': b'Telemetry', b'dt-dataschema': b'dtmi:com:example:Thermostat;1', b'x-opt-sequence-number': 13280, b'x-opt-offset': b'12890070640', b'x-opt-enqueued-time': 1603288810824}

В следующих выходных данных, полученных с помощью предыдущего кода, показаны данные телеметрии температуры, отправленные с помощью многокомпонентного устройства IoT Plug and Play под названием TemperatureController. Системное свойство dt-subject показывает имя компонента, который отправил телеметрию. В этом примере двумя компонентами являются thermostat1 и thermostat2, которые определены в модели DTDL. Системное свойство dt-dataschema показывает идентификатор модели:

Received event from partition: 1.
Telemetry received:  {"temperature": 45}
Properties (set by device):  None
System properties (set by IoT Hub):  {b'content-type': b'application/json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-connection-auth-method': b'{"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}', b'iothub-connection-auth-generation-id': b'637388858939631652', b'iothub-enqueuedtime': 1603289127844, b'iothub-message-source': b'Telemetry', b'dt-subject': b'thermostat1', b'dt-dataschema': b'dtmi:com:example:TemperatureController;1', b'x-opt-sequence-number': 13328, b'x-opt-offset': b'12890095440', b'x-opt-enqueued-time': 1603289128001}

Received event from partition: 1.
Telemetry received:  {"temperature": 49}
Properties (set by device):  None
System properties (set by IoT Hub):  {b'content-type': b'application/json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-connection-auth-method': b'{"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}', b'iothub-connection-auth-generation-id': b'637388858939631652', b'iothub-enqueuedtime': 1603289133017, b'iothub-message-source': b'Telemetry', b'dt-subject': b'thermostat2', b'dt-dataschema': b'dtmi:com:example:TemperatureController;1', b'x-opt-sequence-number': 13329, b'x-opt-offset': b'12890095928', b'x-opt-enqueued-time': 1603289133173}

Чтение уведомлений об изменениях двойников устройств

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях двойников устройств для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода Python дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Received event from partition: 1.
Telemetry received:  {"version":3,"properties":{"reported":{"maxTempSinceLastReboot":10.96,"$metadata":{"$lastUpdated":"2020-10-21T14:10:42.4171263Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-21T14:10:42.4171263Z"}},"$version":2}}}
Properties (set by device):  {b'hubName': b'my-pnp-hub', b'deviceId': b'my-pnp-device', b'operationTimestamp': b'2020-10-21T14:10:42.4171263+00:00', b'iothub-message-schema': b'twinChangeNotification', b'opType': b'updateTwin'}
System properties (set by IoT Hub):  {b'user-id': b'my-pnp-hub\x81\x0e\xa4\x7f', b'correlation-id': b'12104ced5402', b'content-type': b'application/json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-enqueuedtime': 1603289442519, b'iothub-message-source': b'twinChangeEvents', b'x-opt-sequence-number': 13332, b'x-opt-offset': b'12890097392', b'x-opt-enqueued-time': 1603289442738}

Предыдущий фрагмент кода Python дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях двойника устройства с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Received event from partition: 1.
Telemetry received:  {"version":4,"properties":{"reported":{"thermostat1":{"maxTempSinceLastReboot":98.34,"__t":"c"},"$metadata":{"$lastUpdated":"2020-10-21T14:13:39.36491Z","thermostat1":{"$lastUpdated":"2020-10-21T14:13:39.36491Z","maxTempSinceLastReboot":{"$lastUpdated":"2020-10-21T14:13:39.36491Z"},"__t":{"$lastUpdated":"2020-10-21T14:13:39.36491Z"}}},"$version":3}}}
Properties (set by device):  {b'hubName': b'my-pnp-hub', b'deviceId': b'my-pnp-device', b'operationTimestamp': b'2020-10-21T14:13:39.3649100+00:00', b'iothub-message-schema': b'twinChangeNotification', b'opType': b'updateTwin'}
System properties (set by IoT Hub):  {b'user-id': b'my-pnp-hub', b'correlation-id': b'1210b664ab83', b'content-type': b'application/json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-enqueuedtime': 1603289619481, b'iothub-message-source': b'twinChangeEvents', b'x-opt-sequence-number': 13341, b'x-opt-offset': b'12890102216', b'x-opt-enqueued-time': 1603289619668}

Чтение уведомлений об изменениях цифровых двойников

Вы можете настроить центр Интернета вещей на создание уведомлений об изменениях цифровых двойников для маршрутизации в поддерживаемую конечную точку. Дополнительные сведения см. в статье "Использование маршрутизации сообщений Центр Интернета вещей для отправки сообщений устройства в облако" в разные конечные > точки, не связанные с телеметрией.

Предыдущий фрагмент кода Python дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников для термостата без компонентов. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Received event from partition: 1.
Telemetry received:  [{"op":"add","path":"/$metadata/maxTempSinceLastReboot","value":{"lastUpdateTime":"2020-10-21T14:10:42.4171263Z"}},{"op":"add","path":"/maxTempSinceLastReboot","value":10.96}]
Properties (set by device):  {b'hubName': b'my-pnp-hub', b'deviceId': b'my-pnp-device', b'operationTimestamp': b'2020-10-21T14:10:42.4171263+00:00', b'iothub-message-schema': b'digitalTwinChangeNotification', b'opType': b'updateTwin'}
System properties (set by IoT Hub):  {b'user-id': b'my-pnp-hub\x81\x0e\xa4\x7f', b'correlation-id': b'12104ced5402', b'content-type': b'application/json-patch+json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-enqueuedtime': 1603289442519, b'iothub-message-source': b'digitalTwinChangeEvents', b'x-opt-sequence-number': 13333, b'x-opt-offset': b'12890098024', b'x-opt-enqueued-time': 1603289442738}

Предыдущий фрагмент кода Python дает следующий результат, когда центр Интернета вещей создает уведомления об изменениях цифровых двойников с компонентами. В этом примере показаны выходные данные, когда датчик температуры с термостатом создает уведомления. Свойства приложения iothub-message-schema и opType предоставляют сведения о типе уведомления об изменении:

Received event from partition: 1.
Telemetry received:  [{"op":"add","path":"/thermostat1","value":{"$metadata":{"maxTempSinceLastReboot":{"lastUpdateTime":"2020-10-21T14:13:39.36491Z"}},"maxTempSinceLastReboot":98.34}}]
Properties (set by device):  {b'hubName': b'my-pnp-hub', b'deviceId': b'my-pnp-device', b'operationTimestamp': b'2020-10-21T14:13:39.3649100+00:00', b'iothub-message-schema': b'digitalTwinChangeNotification', b'opType': b'updateTwin'}
System properties (set by IoT Hub):  {b'user-id': b'my-pnp-hub', b'correlation-id': b'1210b664ab83', b'content-type': b'application/json-patch+json', b'content-encoding': b'utf-8', b'iothub-connection-device-id': b'my-pnp-device', b'iothub-enqueuedtime': 1603289619481, b'iothub-message-source': b'digitalTwinChangeEvents', b'x-opt-sequence-number': 13342, b'x-opt-offset': b'12890102984', b'x-opt-enqueued-time': 1603289619668}

Следующие шаги

Теперь, когда вы узнали о моделировании устройств, вот несколько дополнительных ресурсов: