Compreender e usar gêmeos de módulo no Hub IoT

Este artigo pressupõe que você tenha lido Entender e usar gêmeos de dispositivo no Hub IoT primeiro. No Hub IoT, sob cada identidade de dispositivo, você pode criar até 50 identidades de módulo. Cada identidade de módulo gera implicitamente um módulo gêmeo. Semelhante aos gêmeos de dispositivo, os gêmeos de módulo são documentos JSON que armazenam informações de estado do módulo, incluindo metadados, configurações e condições. O Hub IoT do Azure mantém um módulo gêmeo para cada módulo que você conecta ao Hub IoT.

No lado do dispositivo, os SDKs de dispositivo do Hub IoT permitem criar módulos em que cada um abre uma conexão independente com o Hub IoT. Essa funcionalidade permite que você use namespaces separados para componentes diferentes em seu dispositivo. Por exemplo, você tem uma máquina de venda automática que tem três sensores diferentes. Cada sensor é controlado por diferentes departamentos na sua empresa. Você pode criar um módulo para cada sensor. Desta forma, cada departamento só consegue enviar trabalhos ou direcionar métodos para o sensor que controla, evitando conflitos e erros do utilizador.

A identidade do módulo e o gêmeo do módulo fornecem os mesmos recursos que a identidade do dispositivo e o gêmeo do dispositivo, mas com uma granularidade mais fina. Essa granularidade mais fina permite que dispositivos capazes, como dispositivos baseados no sistema operacional ou dispositivos de firmware gerenciando vários componentes, isolem a configuração e as condições para cada um desses componentes. A identidade do módulo e os gêmeos de módulo fornecem uma separação de gerenciamento de preocupações ao trabalhar com dispositivos IoT que têm componentes de software modulares. Nosso objetivo é suportar todas as funcionalidades do dispositivo twin no nível do módulo twin por disponibilidade geral do módulo twin.

Nota

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

Este artigo descreve:

  • A estrutura do módulo gêmeo: tags, propriedades desejadas e relatadas.
  • As operações que os módulos e back-ends podem executar em módulos gêmeos.

Consulte as diretrizes de comunicação entre dispositivos para a nuvem para obter orientações sobre como usar propriedades relatadas, mensagens de dispositivo para nuvem ou upload de arquivos.

Consulte as diretrizes de comunicação da nuvem para o dispositivo para obter orientação sobre como usar as propriedades desejadas, os métodos diretos ou as mensagens da nuvem para o dispositivo.

Gêmeos de módulo

Os gêmeos de módulo armazenam informações relacionadas ao módulo que:

  • Os módulos no dispositivo e no Hub IoT podem ser usados para sincronizar as condições e a configuração do módulo.

  • O back-end da solução pode ser usado para consultar e direcionar operações de longa execução.

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

Um módulo twin é um documento JSON que inclui:

  • Etiquetas. Uma seção do documento JSON que o back-end da solução pode ler e gravar. As tags não são visíveis para os módulos no dispositivo. As tags são definidas para fins de consulta.

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

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

  • Propriedades de identidade do módulo. A raiz do documento JSON gêmeo do módulo contém as propriedades somente leitura da identidade do módulo correspondente armazenada no registro de identidade.

Architectural representation of device twin

O exemplo a seguir mostra um documento JSON gêmeo de módulo:

{
    "deviceId": "devA",
    "moduleId": "moduleA",
    "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
        }
    }
}

No objeto raiz estão as propriedades de identidade do módulo e os objetos de contêiner para tags e ambas reporteddesired as propriedades. O properties contêiner contém alguns elementos somente leitura ($metadata e ) descritos nas seções Metadados gêmeos do módulo e $versionSimultaneidade otimista.

Exemplo de propriedade relatada

No exemplo anterior, o gêmeo do módulo contém uma batteryLevel propriedade que é relatada pelo aplicativo do módulo. Esta propriedade torna possível consultar e operar em módulos com base no último nível de bateria relatado. Outros exemplos incluem o módulo, o aplicativo, os recursos do módulo de relatório ou as opções de conectividade.

Nota

As propriedades relatadas simplificam os cenários em que o back-end da solução está interessado no último valor conhecido de uma propriedade. Use mensagens de dispositivo para nuvem se o back-end da solução precisar processar a telemetria do módulo na forma de sequências de eventos com carimbo de data/hora, como séries temporais.

Exemplo de propriedade desejada

No exemplo anterior, as propriedades desejadas e relatadas telemetryConfig do gêmeo do módulo são usadas pelo back-end da solução e pelo aplicativo do módulo para sincronizar a configuração de telemetria para este módulo. 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 o conjunto de propriedades desejado:

    ...
    "desired": {
        "telemetryConfig": {
            "sendFrequency": "5m"
        },
        ...
    },
    ...
    
  2. O aplicativo do módulo é notificado da alteração imediatamente se o módulo estiver conectado. Se não estiver conectado, o aplicativo do módulo segue o fluxo de reconexão do módulo quando se conecta. Em seguida, o aplicativo do módulo relata a configuração atualizada (ou uma condição de erro usando a status propriedade). Aqui está a parte das propriedades relatadas:

    "reported": {
        "telemetryConfig": {
            "sendFrequency": "5m",
            "status": "success"
        }
        ...
    }
    
  3. O back-end da solução pode acompanhar os resultados da operação de configuração em muitos módulos, consultando gêmeos de módulos.

Nota

Os trechos anteriores são exemplos, otimizados para legibilidade, de uma maneira de codificar uma configuração de módulo e seu status. O Hub IoT não impõe um esquema específico para as propriedades desejadas e relatadas do gêmeo de módulo nos gêmeos de módulo.

Importante

O 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 IoT Plug and Play, você deve seguir as convenções Plug and Play ao atualizar as propriedades gêmeas. Para obter mais informações e um exemplo, consulte Propriedades graváveis no IoT Plug and Play.

Operações de back-end

O back-end da solução opera no módulo twin usando as seguintes operações atômicas, expostas através de HTTPS:

  • Recupere o módulo twin por ID. Esta operação retorna o documento gêmeo do módulo, incluindo tags e propriedades do sistema desejadas e relatadas.

  • Atualização parcial do módulo twin. Esta operação permite que o back-end da solução atualize parcialmente as tags ou propriedades desejadas em um módulo gêmeo. A atualização parcial é expressa como um documento JSON que adiciona ou atualiza qualquer propriedade. As propriedades definidas como null são removidas. O exemplo a seguir cria uma nova propriedade desejada com value {"newProperty": "newValue"}, substitui o valor existente de existingProperty with "otherNewValue"e remove otherOldProperty. Nenhuma outra alteração é feita nas propriedades ou tags desejadas existentes:

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

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

  • Receba notificações duplas. Esta operação permite que o back-end da solução seja notificado quando o gêmeo é modificado. Para fazer isso, sua solução de IoT precisa criar uma rota e definir a Fonte de Dados igual a twinChangeEvents. Por padrão, essa rota não existe, portanto, nenhuma notificação dupla é enviada. Se a taxa de alteração for muito alta, ou por outros motivos, como falhas internas, o Hub IoT poderá enviar apenas uma notificação que contenha todas as alterações. Portanto, se seu aplicativo precisa de auditoria confiável e registro em log de todos os estados intermediários, você deve 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 sem telemetria.

Todas as operações anteriores suportam 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 consultar os gêmeos de módulo usando a linguagem de consulta do Hub IoT semelhante ao SQL.

Operações do módulo

O aplicativo de módulo opera no módulo gêmeo usando as seguintes operações atômicas:

  • Recuperar módulo gêmeo. Esta operação retorna o documento gêmeo do módulo (incluindo as propriedades do sistema desejadas e relatadas) para o módulo conectado no momento.

  • Atualize parcialmente as propriedades relatadas. Esta operação permite a atualização parcial das propriedades relatadas do módulo conectado no momento. Esta operação usa o mesmo formato de atualização JSON que o back-end da solução usa para uma atualização parcial das propriedades desejadas.

  • Observe as propriedades desejadas. O módulo atualmente conectado pode optar por ser notificado sobre atualizações nas propriedades desejadas quando elas acontecerem. O módulo recebe a mesma forma de atualização (substituição parcial ou total) executada pelo back-end da solução.

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

Os SDKs de dispositivo IoT do Azure facilitam o uso das operações anteriores de muitos idiomas e plataformas.

Formato de tags e propriedades

Tags, propriedades desejadas e propriedades relatadas 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 de comprimento. Os caracteres permitidos excluem caracteres de controle UNICODE (segmentos C0 e C1) e , $e .SP.

  • Valores: Todos os valores em objetos JSON podem ser dos seguintes tipos JSON: booleano, número, cadeia de caracteres, objeto. Matrizes também são suportadas.

    • 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 tags, propriedades desejadas e propriedades relatadas é 10. Por exemplo, o seguinte objeto é válido:

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

Módulo tamanho duplo

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

O tamanho duplo é calculado da seguinte forma:

  • Para cada propriedade no documento JSON, o Hub IoT calcula cumulativamente e adiciona o comprimento da chave e do valor da propriedade.

  • As chaves de propriedade são consideradas como cadeias de caracteres codificadas em UTF8.

  • Os valores de propriedade simples são considerados como cadeias de caracteres codificadas em UTF8, valores numéricos (8 Bytes) ou valores booleanos (4 Bytes).

  • O tamanho das cadeias de caracteres codificadas em UTF8 é calculado contando todos os caracteres, excluindo caracteres de controle UNICODE (segmentos C0 e C1).

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

O Hub IoT rejeita com um erro todas as operações que aumentariam o tamanho desses documentos acima do limite.

Metadados gêmeos do módulo

O Hub IoT mantém o carimbo de data/hora da última atualização para cada objeto JSON nas propriedades desejadas e relatadas do módulo gêmeo. Os carimbos de data/hora estão em UTC e codificados no formato YYYY-MM-DDTHH:MM:SS.mmmZISO8601. 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": "5m",
                    "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 mantidas em todos os níveis (não apenas nas folhas da estrutura JSON) para preservar as atualizações que removem chaves de objeto.

Simultaneidade otimista

Tags, propriedades desejadas e propriedades relatadas suportam simultaneidade otimista. Se você precisar garantir a ordem das atualizações de propriedades gêmeas, considere implementar 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 gêmeos de módulo têm uma ETag (etag propriedade), conforme RFC7232, que representa a representação JSON do gêmeo. Você pode usar a propriedade em operações de atualização condicional do back-end da solução para garantir a etag consistência. Esta é a única opção para garantir a consistência nas operações que envolvem o tags contêiner.

As propriedades desejadas e relatadas do módulo twin também têm um $version valor que é garantido como incremental. Da mesma forma que um 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 módulo para uma propriedade relatada ou o back-end da solução para uma propriedade desejada.

As versões também são úteis quando um agente de observação (como o aplicativo do módulo observando 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 módulo fornece mais informações.

Fluxo de reconexão do módulo

O Hub IoT não preserva as notificações de atualização de propriedades desejadas para módulos desconectados. Segue-se que um módulo que está se conectando deve recuperar o documento completo de propriedades desejadas, além de se inscrever para notificações de atualização. Dada a possibilidade de corridas entre as notificações de atualização e a recuperação total, deve ser assegurado o seguinte fluxo:

  1. O aplicativo de módulo se conecta a um hub IoT.
  2. O aplicativo do módulo se inscreve para receber notificações de atualização de propriedades desejadas.
  3. O aplicativo Module recupera o documento completo para as propriedades desejadas.

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

Próximos passos

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