Compartilhar via


Guia para desenvolvedores de serviços do IoT Plug and Play

O IoT Plug and Play permite criar dispositivos IoT que anunciam seus recursos para aplicativos de Internet das Coisas do Azure. Os dispositivos IoT Plug and Play não exigem configuração manual quando um cliente os conecta a aplicativos habilitados para IoT Plug and Play.

O IoT Plug and Play permite que você use dispositivos que anunciaram a ID de modelo com o hub IoT. Por exemplo, você pode acessar as propriedades e comandos de um dispositivo diretamente.

Se você estiver usando o IoT Central, poderá usar a interface do usuário do IoT Central e a API REST para interagir com dispositivos IoT Plug and Play conectados ao seu aplicativo.

SDKs do Serviço

Use os SDKs do serviço IoT do Azure em sua solução para interagir com dispositivos e módulos. Por exemplo, você pode usar os SDKs de serviço para ler e atualizar propriedades de gêmeos e invocar comandos. As linguagens com suporte incluem C#, Java, Node.js e Python.

Os SDKs do serviço de IoT do Azure contêm código para facilitar a criação aplicativos que interagem diretamente com o Hub IoT para gerenciar dispositivos e a segurança.

Plataforma Pacote Repositório de códigos Exemplos Referência
.NET NuGet GitHub Amostras Referência
Java Maven GitHub Amostras Referência
npm GitHub Amostras Referência
Python pip GitHub Amostras Referência

Os SDKs de serviço permitem que você acesse informações de dispositivo a partir de um componente da solução, como uma área de trabalho ou aplicativo Web. Os SDKs de serviço incluem dois namespaces e modelos de objeto que você pode usar para recuperar a ID do modelo:

  • Cliente de serviço do Hub IoT. Esse serviço expõe a ID do modelo como uma propriedade de dispositivo gêmeo.

  • Cliente dos Gêmeos Digitais. A nova API dos Gêmeos Digitais opera em constructos de modelo DTDL (Linguagem de Definição de Gêmeos Digitais), como componentes, propriedades e comandos. As APIs de Gêmeo Digital facilitam para os criadores de solução criar soluções IoT Plug and Play.

Os seguintes recursos também estão disponíveis:

Exemplos de cliente de serviço do Hub IoT

Esta seção mostra exemplos de C# usando o cliente de serviço do Hub IoT e as classes RegistryManager e ServiceClient. Você usa a classe RegistryManager para interagir com o estado do dispositivo usando os dispositivos gêmeos. Também é possível usar a classe RegistryManager para consultar os registros do dispositivo no Hub IoT. Você usa a classe ServiceClient para chamar comandos no dispositivo. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa. Nos snippets de código, a variável deviceTwinId contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o dispositivo gêmeo e a ID do modelo

Para obter o dispositivo gêmeo e a ID de modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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}.");

Atualizar dispositivo gêmeo

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. O exemplo mostra como você precisa obter o ETag do gêmeo antes de atualizá-lo. A propriedade é definida no componente padrão do dispositivo:

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);

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. O exemplo mostra como você precisa obter o ETag do gêmeo antes de atualizá-lo. A propriedade é definida no componente 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;
}

Para uma propriedade em um componente, o patch da propriedade é semelhante ao exemplo a seguir:

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

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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}.";
}

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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.");
}

Exemplos de gêmeo digital do Hub IoT

Você usa a classe DigitalTwinClient para interagir com o estado do dispositivo usando gêmeos digitais. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa.

Esta seção mostra exemplos de C# usando a API de Gêmeos Digitais. Os snippets a seguir usam as seguintes classes para representar o gêmeo digital do termostato e dos dispositivos controladores de temperatura:

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; }
  }
}

A variável digitalTwinId contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o gêmeo digital e a ID do modelo

Para obter o gêmeo digital e a ID do modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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)}");

Atualizar o gêmeo digital

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. A propriedade é definida no componente padrão do dispositivo:

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}.");

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. A propriedade é definida no componente 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}.");

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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}.");
  }
}

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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.");
    }
}

Ler telemetria do dispositivo

Os dispositivos IoT Plug and Play enviam a telemetria definida no modelo DTDL para o Hub IoT. Por padrão, o Hub IoT encaminha a telemetria para um ponto de extremidade de Hubs de Eventos, onde é possível consumi-la. Para saber mais, confira Usar o roteamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade.

O snippet de código a seguir mostra como ler a telemetria do ponto de extremidade padrão dos Hubs de Eventos. O código neste trecho é retirado do início rápido do Hub IoT Enviar telemetria de um dispositivo para um hub IoT e leia com um aplicativo de back-end:

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.
}

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo Thermostat IoT Plug and Play sem componente que tem apenas o componente padrão. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo IoT Plug and Play multicomponente TemperatureController. A propriedade do sistema dt-subject mostra o nome do componente que enviou a telemetria. Neste exemplo, os dois componentes são thermostat1 e thermostat2, conforme definido no modelo DTDL. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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

Ler notificações de alteração de dispositivo gêmeo

É possível configurar o Hub IoT para gerar notificações de alteração de dispositivo gêmeo para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no trecho de código C# anterior gera a seguinte saída quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo de termostato sem componente. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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

O código mostrado no trecho de código C# anterior gera a seguinte saída quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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

Ler notificações de alteração de gêmeo digital

É possível configurar o Hub IoT para gerar notificações de alteração de gêmeo digital para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no fragmento de código C# anterior gera a seguinte saída quando o Hub IoT gera notificações de alteração de gêmeos digitais para um dispositivo de termostato sem componente. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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

O código mostrado no trecho de código C# anterior gera a seguinte saída quando o Hub IoT gera notificações de mudança de gêmeo digital para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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

Os seguintes recursos também estão disponíveis:

Exemplos de cliente de serviço do Hub IoT

Esta seção mostra exemplos de Java usando o cliente de serviço do Hub IoT e as classes DeviceTwin e DeviceMethod do namespace com.microsoft.azure.sdk.iot.service.devicetwin. Você usa a classe DeviceTwin para interagir com o estado do dispositivo usando o dispositivo gêmeos. Também é possível usar a classe DeviceTwin para consultar os registros do dispositivo no Hub IoT. Você usa a classe DeviceMethod para chamar comandos no dispositivo. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa. Nos snippets de código, a variável deviceId contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o dispositivo gêmeo e a ID do modelo

Para obter o dispositivo gêmeo e a ID de modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

DeviceTwin twinClient = DeviceTwin.createFromConnectionString(iotHubConnectionString);

// ...

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

Atualizar dispositivo gêmeo

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. É necessário obter o gêmeo antes de atualizá-lo. A propriedade é definida no componente padrão do dispositivo:

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);

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. É necessário obter o gêmeo antes de atualizá-lo. A propriedade é definida no componente 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);

Para uma propriedade em um componente, o patch da propriedade é semelhante ao exemplo a seguir:

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

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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());

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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());

Exemplos de gêmeo digital do Hub IoT

Você usa a classe DigitalTwinAsyncClient no namespace com.microsoft.azure.sdk.iot.service.digitaltwin para interagir com o estado do dispositivo usando os gêmeos digitais. Os exemplos a seguir também usam as classes UpdateOperationUtility e BasicDigitalTwin do mesmo namespace. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa.

A variável digitalTwinid contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o gêmeo digital e a ID do modelo

Para obter o gêmeo digital e a ID do modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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);
}

Atualizar o gêmeo digital

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. A propriedade é definida no componente padrão do dispositivo:

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();

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. A propriedade é definida no componente 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);

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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));
}

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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));
}

Ler telemetria do dispositivo

Os dispositivos IoT Plug and Play enviam a telemetria definida no modelo DTDL para o Hub IoT. Por padrão, o Hub IoT encaminha a telemetria para um ponto de extremidade de Hubs de Eventos, onde é possível consumi-la. Para saber mais, confira Usar o roteamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade.

O snippet de código a seguir mostra como ler a telemetria do ponto de extremidade padrão dos Hubs de Eventos. O código neste trecho é retirado do início rápido do Hub IoT Enviar telemetria de um dispositivo para um hub IoT e leia com um aplicativo de back-end:

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");
    });
}

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo Thermostat IoT Plug and Play sem componente que tem apenas o componente padrão. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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=aaaa0000-bb11-2222-33cc-444444dddddd, 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=aaaabbbb-0000-cccc-1111-dddd2222eeee, 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=bbbb1111-cc22-3333-44dd-555555eeeeee, 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=bbbbcccc-1111-dddd-2222-eeee3333ffff, content-type=application/json}

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo IoT Plug and Play multicomponente TemperatureController. A propriedade do sistema dt-subject mostra o nome do componente que enviou a telemetria. Neste exemplo, os dois componentes são thermostat1 e thermostat2, conforme definido no modelo DTDL. A propriedade do sistema dt-dataschema mostra a ID do modelo:

Telemetry received from partition 1:
null
Application properties (set by device):
{$.cdid=my-pnp-device}
System properties (set by IoT Hub):
{correlation-id=cccc2222-dd33-4444-55ee-666666ffffff, 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=ccccdddd-2222-eeee-3333-ffff4444aaaa, 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=dddd3333-ee44-5555-66ff-777777aaaaaa, 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=ddddeeee-3333-ffff-4444-aaaa5555bbbb, content-type=application/json, dt-subject=thermostat2}

Ler notificações de alteração de dispositivo gêmeo

É possível configurar o Hub IoT para gerar notificações de alteração de dispositivo gêmeo para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no trecho de código Java anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo do termostato sem componentes. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

O código mostrado no trecho de código Java anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

Ler notificações de alteração de gêmeo digital

É possível configurar o Hub IoT para gerar notificações de alteração de gêmeo digital para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no trecho de código Java anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo do termostato sem componentes. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

O código mostrado no trecho de código Java anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

Os seguintes recursos também estão disponíveis:

Exemplos de cliente de serviço do Hub IoT

Esta seção mostra exemplos de JavaScript usando o cliente de serviço do Hub IoT e as classes Registry e Client. Você usa a classe Registry para interagir com o estado do dispositivo usando os dispositivos gêmeos. Também é possível usar a classe Registry para consultar os registros do dispositivo no Hub IoT. Você usa a classe Client para chamar comandos no dispositivo. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa. Nos snippets de código, a variável deviceId contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o dispositivo gêmeo e a ID do modelo

Para obter o dispositivo gêmeo e a ID de modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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));
  }
}

Atualizar dispositivo gêmeo

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. O exemplo mostra como você precisa obter o gêmeo antes de atualizá-lo. A propriedade é definida no componente padrão do dispositivo:

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));
      }
    }
  }
}

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. O exemplo mostra como você precisa obter o gêmeo antes de atualizá-lo. A propriedade é definida no componente 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));
      }
    }
  }
}

Para uma propriedade em um componente, o patch da propriedade é semelhante ao exemplo a seguir:

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

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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));
  }
});

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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));
  }
});

Exemplos de gêmeo digital do Hub IoT

Você usa a classe DigitalTwinClient para interagir com o estado do dispositivo usando gêmeos digitais. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa.

Esta seção mostra exemplos de JavaScript usando a API dos Gêmeos Digitais.

A variável digitalTwinId contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o gêmeo digital e a ID do modelo

Para obter o gêmeo digital e a ID do modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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));

Atualizar o gêmeo digital

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. A propriedade é definida no componente padrão do dispositivo:

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);

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. A propriedade é definida no componente 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);

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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));

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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));

Ler telemetria do dispositivo

Os dispositivos IoT Plug and Play enviam a telemetria definida no modelo DTDL para o Hub IoT. Por padrão, o Hub IoT encaminha a telemetria para um ponto de extremidade de Hubs de Eventos, onde é possível consumi-la. Para saber mais, confira Usar o roteamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade.

O snippet de código a seguir mostra como ler a telemetria do ponto de extremidade padrão dos Hubs de Eventos. O código neste trecho é retirado do início rápido do Hub IoT Enviar telemetria de um dispositivo para um hub IoT e leia com um aplicativo de back-end:

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,
});

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo IoT Plug and Play multicomponente TemperatureController. A propriedade do sistema dt-subject mostra o nome do componente que enviou a telemetria. Neste exemplo, os dois componentes são thermostat1 e thermostat2, conforme definido no modelo DTDL. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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"}

Ler notificações de alteração de dispositivo gêmeo

É possível configurar o Hub IoT para gerar notificações de alteração de dispositivo gêmeo para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no snippet de código JavaScript anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo sem componente de termostato. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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"}

O código mostrado no snippet de código JavaScript anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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"}

Ler notificações de alteração de gêmeo digital

É possível configurar o Hub IoT para gerar notificações de alteração de gêmeo digital para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no snippet de código JavaScript anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo sem componente de termostato. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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"}

O código mostrado no snippet de código JavaScript anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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"}

Os seguintes recursos também estão disponíveis:

Exemplos de cliente de serviço do Hub IoT

Esta seção mostra exemplos do Python usando o cliente de serviço do Hub IoT e as classes IoTHubRegistryManager e CloudToDeviceMethod. Você usa a classe IoTHubRegistryManager para interagir com o estado do dispositivo usando os dispositivos gêmeos. Também é possível usar a classe IoTHubRegistryManager para consultar os registros do dispositivo no Hub IoT. Você usa a classe CloudToDeviceMethod para chamar comandos no dispositivo. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa. Nos snippets de código, a variável device_id contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o dispositivo gêmeo e a ID do modelo

Para obter o dispositivo gêmeo e a ID de modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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("")

Atualizar dispositivo gêmeo

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. O exemplo mostra como você precisa obter o etag do gêmeo antes de atualizá-lo. A propriedade é definida no componente padrão do dispositivo:

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)

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. O exemplo mostra como você precisa obter o ETag do gêmeo antes de atualizá-lo. A propriedade é definida no componente 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)

Para uma propriedade em um componente, o patch da propriedade é semelhante ao exemplo a seguir:

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

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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)

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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)

Exemplos de gêmeo digital do Hub IoT

Você usa a classe DigitalTwinClient para interagir com o estado do dispositivo usando gêmeos digitais. O modelo de DTDL para o dispositivo define as propriedades e os comandos que o dispositivo implementa.

A variável device_id contém a ID do dispositivo IoT Plug and Play registrada no Hub IoT.

Obter o gêmeo digital e a ID do modelo

Para obter o gêmeo digital e a ID do modelo do dispositivo IoT Plug and Play que se conectou ao Hub IoT:

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")

Atualizar o gêmeo digital

O snippet de código a seguir mostra como atualizar a propriedade targetTemperature em um dispositivo. A propriedade é definida no componente padrão do dispositivo:

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)

O trecho a seguir mostra como atualizar a propriedade targetTemperature em um componente. A propriedade é definida no componente 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)

Comando de chamada

O snippet a seguir mostra como invocar o comando getMaxMinReport definido em um componente padrão:

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")

O snippet a seguir mostra como chamar o comando getMaxMinReport em um componente. O comando é definido no componente 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")

Ler telemetria do dispositivo

Os dispositivos IoT Plug and Play enviam a telemetria definida no modelo DTDL para o Hub IoT. Por padrão, o Hub IoT encaminha a telemetria para um ponto de extremidade de Hubs de Eventos, onde é possível consumi-la. Para saber mais, confira Usar o roteamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade.

O snippet de código a seguir mostra como ler a telemetria do ponto de extremidade padrão dos Hubs de Eventos. O código neste trecho é retirado do início rápido do Hub IoT Enviar telemetria de um dispositivo para um hub IoT e leia com um aplicativo de back-end:

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()

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo Thermostat IoT Plug and Play sem componente que tem apenas o componente padrão. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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}

A saída a seguir do código anterior mostra a telemetria de temperatura enviada pelo dispositivo IoT Plug and Play multicomponente TemperatureController. A propriedade do sistema dt-subject mostra o nome do componente que enviou a telemetria. Neste exemplo, os dois componentes são thermostat1 e thermostat2, conforme definido no modelo DTDL. A propriedade do sistema dt-dataschema mostra a ID do modelo:

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}

Ler notificações de alteração de dispositivo gêmeo

É possível configurar o Hub IoT para gerar notificações de alteração de dispositivo gêmeo para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no trecho de código Python anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo do termostato sem componentes. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

O código mostrado no trecho de código Python anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de dispositivo gêmeo para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

Ler notificações de alteração de gêmeo digital

É possível configurar o Hub IoT para gerar notificações de alteração de gêmeo digital para encaminhar para um ponto de extremidade com suporte. Para saber mais, confira Usar o encaminhamento de mensagens do Hub IoT para enviar mensagens de dispositivo para nuvem para diferentes pontos de extremidade > Eventos que não são de telemetria.

O código mostrado no trecho de código Python anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo do termostato sem componentes. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

O código mostrado no trecho de código Python anterior gera a saída a seguir quando o Hub IoT gera notificações de alteração de gêmeo digital para um dispositivo com componentes. Este exemplo mostra a saída quando um dispositivo de sensor de temperatura com um componente de termostato gera notificações. As propriedades de aplicativo iothub-message-schema e opType fornecem informações sobre o tipo de notificação de alteração:

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}

Próximas etapas

Agora que você conheceu a modelagem de dispositivo, confira mais recursos interessantes: