Entender e usar dispositivos gêmeos no Hub IoT

Dispositivos gêmeos são documentos JSON que armazenam informações do estado do dispositivo, incluindo metadados, configurações e condições. O Hub IoT do Azure mantém um dispositivo gêmeo para cada dispositivo que você conecta ao Hub IoT.

Observação

Os recursos descritos neste artigo estão disponíveis apenas na camada padrão do Hub IoT. Para obter mais informações sobre as camadas básica e padrão/gratuita do Hub IoT, confira Escolher a camada certa do Hub IoT para a sua solução.

Este artigo descreve:

  • A estrutura do dispositivo gêmeo: marcas, propriedades desejadas e propriedades relatadas.
  • As operações que os aplicativos de dispositivo e back-end podem executar nos dispositivos gêmeos.

Use os dispositivos gêmeos para:

  • Armazene os metadados específicos do dispositivo na nuvem. Por exemplo, a localização de uma máquina de vendas.

  • Relate informações de estado atual, como recursos disponíveis e condições do aplicativo do dispositivo. Por exemplo, se um dispositivo é conectado ao hub IoT via celular ou Wi-Fi.

  • Sincronize o estado dos fluxos de trabalho de longa execução entre o aplicativo do dispositivo e o aplicativo do back-end. Por exemplo, quando a solução de back-end especifica a nova versão do firmware para instalação, e o aplicativo do dispositivo relata os diversos estágios do processo de atualização.

  • Consultar os metadados, a configuração ou o estado do seu dispositivo.

Para obter mais informações sobre o uso de propriedades relatadas, mensagens de dispositivo para nuvem ou upload de arquivos, consulte Diretrizes de comunicação de dispositivo para nuvem.

Para obter mais informações sobre o uso de propriedades desejadas, métodos diretos ou mensagens de nuvem para dispositivo, consulte Diretrizes de comunicação de nuvem para dispositivo.

Para saber como os dispositivos gêmeos estão relacionados ao modelo de dispositivo usado por um dispositivo Azure IoT Plug and Play, consulte Entender os dispositivos gêmeos do loT Plug and Play.

Dispositivos gêmeos

Dispositivos gêmeos armazenam informações relacionadas ao dispositivo que:

  • O dispositivo e os back-ends podem usar para sincronizar a configuração e as condições do dispositivo.

  • A solução que o back-end pode usar para consultar e direcionar operações de execução longa.

O ciclo de vida de um dispositivo gêmeo está vinculado à sua identidade do dispositivo correspondente. Os dispositivos gêmeos são criados e excluídos implicitamente quando uma identidade de dispositivo é criada ou excluída no Hub IoT.

Um dispositivo gêmeo é um documento JSON que inclui:

  • Marcas. Uma seção do documento JSON que o back-end de solução pode ler e na qual pode gravar. As marcas não são visíveis para os aplicativos do dispositivo.

  • Propriedades desejadas. Usado junto com as propriedades relatadas para sincronizar a configuração de dispositivo ou condições. O back-end da solução pode definir as propriedades desejadas e o aplicativo de dispositivo pode lê-las. O aplicativo do dispositivo também pode receber notificações de alterações nas propriedades desejadas.

  • Propriedades reportadas. Usado junto com as propriedades desejadas para sincronizar a configuração de dispositivo ou condições. O aplicativo de dispositivo pode definir as propriedades relatadas e o back-end da solução pode lê-las e consultá-las.

  • Propriedades de identidade do dispositivo. A raiz do documento JSON do dispositivo gêmeo contém as propriedades somente leitura da identidade do dispositivo correspondente armazenada no registro identidade. As propriedades connectionStateUpdatedTime e generationId não serão incluídas.

Diagrama mostrando quais aplicativos interagem com quais propriedades do dispositivo gêmeo.

O seguinte exemplo mostra um documento JSON de dispositivo gêmeo:

{
    "deviceId": "devA",
    "etag": "AAAAAAAAAAc=", 
    "status": "enabled",
    "statusReason": "provisioned",
    "statusUpdateTime": "0001-01-01T00:00:00",
    "connectionState": "connected",
    "lastActivityTime": "2015-02-30T16:24:48.789Z",
    "cloudToDeviceMessageCount": 0, 
    "authenticationType": "sas",
    "x509Thumbprint": {     
        "primaryThumbprint": null, 
        "secondaryThumbprint": null 
    }, 
    "version": 2, 
    "tags": {
        "deploymentLocation": {
            "building": "43",
            "floor": "1"
        }
    },
    "properties": {
        "desired": {
            "telemetryConfig": {
                "sendFrequency": "5m"
            },
            "$metadata" : {...},
            "$version": 1
        },
        "reported": {
            "telemetryConfig": {
                "sendFrequency": "5m",
                "status": "success"
            },
            "batteryLevel": 55,
            "$metadata" : {...},
            "$version": 4
        }
    }
}

O objeto raiz contém as propriedades de identidade do dispositivo e os objetos de contêiner para tags e ambas as propriedades reported e desired. O contêiner properties tem alguns elementos somente leitura ($metadata e $version) descritos nas seções Metadados de dispositivo gêmeo e Simultaneidade otimista.

Exemplo da propriedade reportada

No exemplo anterior, o dispositivo gêmeo contém uma propriedade batteryLevel que é reportada pelo aplicativo do dispositivo. Essa propriedade torna possível a consultar e operação em dispositivos com base no último nível da bateria reportado. Outros exemplos incluem os recursos de dispositivo de relatórios de aplicativo de dispositivo ou as opções de conectividade.

Observação

As propriedades relatadas simplificam cenários nos quais o back-end da solução está interessado no último valor conhecido de uma propriedade. Use as mensagens do dispositivo para nuvem se o back-end da solução precisar processar telemetria do dispositivo na forma de sequências de eventos com carimbo de data/hora, como uma série temporal.

Exemplo da propriedade desejada

No exemplo anterior, as propriedades relatadas e desejadas do dispositivo gêmeo telemetryConfig são usadas pelo aplicativo do dispositivo e pelo back-end da solução para sincronizar a configuração de telemetria para o dispositivo em questão. Por exemplo:

  1. O back-end da solução define a propriedade desejada com o valor de configuração desejado. Aqui está a parte do documento com a propriedade desejada definida:

    "desired": {
        "telemetryConfig": {
            "sendFrequency": "5m"
        },
        ...
    },
    
  2. O aplicativo do dispositivo será notificado sobre a alteração imediatamente se o dispositivo estiver conectado. Se ele não estiver conectado, o aplicativo do dispositivo seguirá o fluxo de reconexão do dispositivo quando ele se conectar. Em seguida, o aplicativo do dispositivo reporta a configuração atualizada (ou uma condição de erro usando a propriedade status). Aqui está a parte das propriedades relatadas:

    "reported": {
        "telemetryConfig": {
            "sendFrequency": "5m",
            "status": "success"
        }
        ...
    }
    
  3. O back-end da solução rastreia os resultados da operação de configuração em vários dispositivos consultando os dispositivos gêmeos.

Observação

Os snippets anteriores são exemplos, otimizados para facilitar a leitura, de uma forma de codificar uma configuração de dispositivo e seu status. O Hub IoT não impõe um esquema específico para as propriedades desejadas e reportadas do dispositivo gêmeo nos dispositivos gêmeos.

Importante

A IoT Plug and Play define um esquema que usa várias propriedades adicionais para sincronizar as alterações nas propriedades desejadas e relatadas. Se sua solução usa a IoT Plug and Play, você precisa seguir as convenções de Plug and Play ao atualizar propriedades de gêmeo. Para obter mais informações e um exemplo, confira Propriedades graváveis em IoT Plug and Play.

Você pode usar gêmeos para sincronizar operações de longa execução, como atualizações de firmware. Para obter mais informações sobre como usar propriedades para sincronizar e acompanhar uma operação de longa duração entre dispositivos, confira Usar propriedades desejadas para configurar dispositivos.

Operações de back-end

O back-end da solução funciona no dispositivo gêmeo usando as seguintes operações atômicas, expostas por meio de HTTPS:

  • Recuperar dispositivo gêmeo por ID. Essa operação retorna o documento do dispositivo gêmeo, incluindo marcas e propriedades do sistema desejadas e reportadas.

  • Atualizar parcialmente o dispositivo gêmeo. Essa operação permite que o back-end da solução atualize parcialmente as marcações ou propriedades desejadas em um dispositivo gêmeo. A atualização parcial é expressa como um documento JSON que adiciona ou atualiza qualquer propriedade. As propriedades definidas como null foram removidas. O exemplo a seguir cria uma nova propriedade desejada com o valor {"newProperty": "newValue"}, substitui o valor existente de existingProperty por "otherNewValue" e remove otherOldProperty. Nenhuma outra alteração é feitas nas propriedades desejadas ou marcas existentes:

    {
         "properties": {
             "desired": {
                 "newProperty": {
                     "nestedProperty": "newValue"
                 },
                 "existingProperty": "otherNewValue",
                 "otherOldProperty": null
             }
         }
    }
    
  • Substituir propriedades desejadas. Esta operação permite que o back-end da solução substitua completamente todas as suas propriedades desejadas existentes e substitui um novo documento JSON por properties/desired.

  • Substituir marcas. Esta operação permite que o back-end da solução substitua completamente todas as marcas existentes e substitui um novo documento JSON por tags.

  • Receba notificações gêmeas. Esta operação permite que o back-end de solução seja notificado quando o gêmeo é modificado. Para fazer isso, sua solução de IoT precisa para criar uma rota e definir a Fonte de Dados como twinChangeEvents. Por padrão, essa rota não existe, e portanto nenhuma notificação gêmea é enviada. Se a taxa de alteração for alta demais ou então por outros motivos como falhas internas, o Hub IoT poderá enviar apenas uma notificação contendo todas as alterações. Portanto, se o aplicativo precisar de auditoria e registro em log confiável de todos os estados intermediários, será necessário usar mensagens de dispositivo para nuvem. Para saber mais sobre as propriedades e o corpo retornados na mensagem de notificação gêmea, consulte Esquemas de eventos de não telemetria.

Todas as operações anteriores dão suporte à Simultaneidade otimista e exigem a permissão ServiceConnect, conforme definido no artigo Controlar acesso ao Hub IoT.

Além dessas operações, o back-end da solução pode:

Operações de dispositivo

O aplicativo do dispositivo opera no dispositivo gêmeo usando as seguintes operações atômicas:

  • Recuperar dispositivo gêmeo. Essa operação retorna o documento do dispositivo gêmeo (incluindo propriedades do sistema desejadas e reportadas) para o dispositivo conectado no momento. (As marcas não são visíveis para os aplicativos do dispositivo.)

  • Atualizar parcialmente as propriedades reportadas. Essa operação permite a atualização parcial das propriedades reportadas do dispositivo conectado no momento. Esta operação usa o mesmo formato de atualização JSON que a solução de back-end usa para uma atualização parcial de propriedades desejadas.

  • Observar as propriedades desejadas. O dispositivo conectado no momento pode optar por ser notificado sobre atualizações para as propriedades desejadas quando elas ocorrem. O dispositivo recebe a mesma forma de atualização (substituição total ou parcial) executada pelo back-end da solução.

Todas as operações anteriores exigem a permissão DeviceConnect, conforme definido no Controlar acesso ao Hub IoT.

Os SDKs do dispositivo IoT do Azure facilitam o uso das operações anteriores em várias linguagens e plataformas. Para obter mais informações sobre os detalhes dos primitivos do Hub IoT para sincronização de propriedades desejadas, consulte Fluxo de reconexão do dispositivo.

Formato de marcas e propriedades

Marcas, propriedades desejadas e propriedades reportadas são objetos JSON com as seguintes restrições:

  • Chaves: todas as chaves em objetos JSON são codificadas em UTF-8, diferenciam maiúsculas de minúsculas e têm até 1 KB. Os caracteres permitidos excluem caracteres de controle UNICODE (segmentos C0 e C1) e ., $ e SP.

    Observação

    As consultas do Hub IoT usadas no Roteamento de Mensagens não dão suporte a espaços em branco ou a qualquer um dos seguintes caracteres como parte de um nome da chave: ()<>@,;:\"/?={}.

  • Valores: todos os valores em objetos JSON podem ser dos seguintes tipos de JSON: booliano, número, cadeia de caracteres ou objeto. Também há suporte para matrizes.

    • Os inteiros podem ter um valor mínimo de -4503599627370496 e um valor máximo de 4503599627370495.

    • Os valores de cadeia de caracteres são codificados em UTF-8 e podem ter um comprimento máximo de 4 KB.

  • Profundidade: a profundidade máxima de objetos JSON em marcas, propriedades desejadas e propriedades relatadas é dez. Por exemplo, o seguinte objeto é válido:

    {
         ...
         "tags": {
             "one": {
                 "two": {
                     "three": {
                         "four": {
                             "five": {
                                 "six": {
                                     "seven": {
                                         "eight": {
                                             "nine": {
                                                 "ten": {
                                                     "property": "value"
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         },
         ...
    }
    

Tamanho do dispositivo gêmeo

O Hub IoT impõe um limite de tamanho de 8 KB para o valor de tags, e um limite de tamanho de 32 KB para cada valor de properties/desired e properties/reported. Esses totais são exclusivos de elementos somente leitura como $version e $metadata/$lastUpdated.

O tamanho do gêmeo é calculado da seguinte maneira:

  • Para cada propriedade no documento JSON, o hub IoT é calculado cumulativamente e adiciona o comprimento da chave e do valor da propriedade.

  • As chaves de propriedade são consideradas cadeias de caracteres codificadas em UTF-8.

  • Os valores de propriedades simples são considerados cadeias de caracteres codificadas em UTF-8, valores numéricos (8 bytes) ou valores boolianos (4 bytes).

  • O tamanho das cadeias de caracteres codificadas em UTF-8 é calculado pela contagem de todos os caracteres, exceto caracteres de controle UNICODE (segmentos C0 e C1).

  • Os valores de propriedades complexos (objetos aninhados) são calculados com base no tamanho agregado das chaves de propriedades e dos valores de propriedades que eles contêm.

O Hub IoT rejeita com erro todas as operações que podem aumentar o tamanho dos documentos tags, properties/desired ou properties/reported acima do limite.

Metadados do dispositivo gêmeo

O Hub IoT mantém o carimbo de data e hora da última atualização de cada objeto JSON nas propriedades desejadas e reportadas do dispositivo gêmeo. Os carimbos de data e hora estão em UTC e são codificados no formato ISO8601YYYY-MM-DDTHH:MM:SS.mmmZ.

Por exemplo:

{
    ...
    "properties": {
        "desired": {
            "telemetryConfig": {
                "sendFrequency": "5m"
            },
            "$metadata": {
                "telemetryConfig": {
                    "sendFrequency": {
                        "$lastUpdated": "2016-03-30T16:24:48.789Z"
                    },
                    "$lastUpdated": "2016-03-30T16:24:48.789Z"
                },
                "$lastUpdated": "2016-03-30T16:24:48.789Z"
            },
            "$version": 23
        },
        "reported": {
            "telemetryConfig": {
                "sendFrequency": "5m",
                "status": "success"
            },
            "batteryLevel": "55%",
            "$metadata": {
                "telemetryConfig": {
                    "sendFrequency": {
                        "$lastUpdated": "2016-03-31T16:35:48.789Z"
                    },
                    "status": {
                        "$lastUpdated": "2016-03-31T16:35:48.789Z"
                    },
                    "$lastUpdated": "2016-03-31T16:35:48.789Z"
                },
                "batteryLevel": {
                    "$lastUpdated": "2016-04-01T16:35:48.789Z"
                },
                "$lastUpdated": "2016-04-01T16:24:48.789Z"
            },
            "$version": 123
        }
    }
    ...
}

Essas informações são armazenadas em cada nível (não apenas nas folhas da estrutura JSON) a fim de preservar as atualizações que removem chaves de objeto.

Simultaneidade otimista

As marcas, propriedades desejadas e propriedades reportadas oferecem suporte à simultaneidade otimista. Se você precisar garantir a ordem das atualizações de propriedades gêmeas, implemente a sincronização no nível do aplicativo aguardando o retorno de chamada das propriedades relatadas, antes de enviar a próxima atualização.

Os dispositivos gêmeos têm uma propriedade ETag etag, de acordo com RFC7232, que corresponde à representação JSON do gêmeo. Você pode usar a propriedade etag em operações de atualização condicionais do back-end da solução para garantir a consistência. Essa propriedade é a única opção para garantir a consistência nas operações que envolvem o contêiner de tags.

As propriedades desejadas e reportadas do dispositivo gêmeo também têm um valor $version com garantia de ser incremental. De forma semelhante a uma ETag, a versão pode ser usada pela parte de atualização para impor a consistência das atualizações. Por exemplo, um aplicativo de dispositivo para uma propriedade relatada ou o back-end de solução para uma propriedade desejada.

Versões também são úteis quando um agente observador (por exemplo, o aplicativo do dispositivo que observa as propriedades desejadas) deve reconciliar corridas entre o resultado de uma operação de recuperação e uma notificação de atualização. A seção Fluxo de reconexão do dispositivo fornece mais informações.

Fluxo de reconexão do dispositivo

O Hub IoT não preserva as notificações de atualização das propriedades desejadas para dispositivos desconectados. Acontece que um dispositivo que está se conectando deve recuperar o documento completo de propriedades desejadas, além de se inscrever para receber notificações de atualização. Considerando a possibilidade de corridas entre notificações de atualização e recuperação completa, o seguinte fluxo deve ser garantido:

  1. O aplicativo de dispositivo conecta-se a um Hub IoT.
  2. O aplicativo de dispositivo se inscreve para as notificações de atualização de propriedades desejadas .
  3. O aplicativo de dispositivo recupera o documento completo para as propriedades desejadas.

O aplicativo de dispositivo pode ignorar todas as notificações com $version menor ou igual à versão do documento recuperado completo. Essa abordagem é possível porque o Hub IoT garante que as versões sempre aumentam.

Próximas etapas

Para experimentar alguns dos conceitos descritos neste artigo, consulte os seguintes artigos do Hub IoT: