Uso de módulos gemelos en IoT Hub

En este artículo se da por supuesto que ha leído primero Dispositivos gemelos en IoT Hub. En IoT Hub, en cada identidad de dispositivo, puede crear hasta 50 identidades de módulos. Cada identidad de módulo genera implícitamente un módulo gemelo. De forma parecida a los dispositivos gemelos, los módulos gemelos son documentos JSON que almacenan información acerca del estado del módulo, incluidos metadatos, configuraciones y condiciones. Azure IoT Hub mantiene un módulo gemelo para cada módulo que se conecta a IoT Hub.

En el lado del dispositivo, los SDK de dispositivo de IoT Hub le permiten crear módulos, donde cada uno abre una conexión independiente a IoT Hub. Esta funcionalidad le permite usar espacios de nombres distintos para distintos componentes del dispositivo. Por ejemplo, tiene una máquina expendedora con tres sensores diferentes. Cada sensor se controla mediante diferentes departamentos de su empresa. Puede crear un módulo para cada sensor. De esta manera, cada departamento solo puede enviar trabajos o métodos directos al sensor que controlan, con lo que se evitan conflictos y errores de usuario.

La identidad del módulo y el módulo gemelo proporcionan las mismas funcionalidades que la identidad del dispositivo y el dispositivo gemelo, pero de manera mucho más pormenorizada. Esto permite a los dispositivos compatibles, como dispositivos basados en el sistema operativo o dispositivos de firmware que administran varios componentes, aislar la configuración y las condiciones de cada uno de esos componentes. La identidad del módulo y el módulo gemelo proporcionan la separación administrativa de problemas al trabajar con dispositivos IoT que tienen componentes de software modulares. Nuestro objetivo es respaldar toda la funcionalidad de dispositivo gemelo en el nivel de módulo gemelo mediante la disponibilidad general del este.

Nota

Las características descritas en este artículo solo están disponibles en el nivel estándar de IoT Hub. Para más información sobre los niveles Básico y Estándar o Gratis de IoT Hub, consulte el artículo sobre cómo elegir el nivel de IoT Hub correcto.

En este artículo se describe:

  • La estructura del módulo gemelo: etiquetas, propiedades deseadas y propiedades notificadas.
  • Las operaciones que pueden realizar los módulos y los servidores back-end en los módulos gemelos.

Para obtener instrucciones sobre el uso de propiedades notificadas, mensajes de dispositivo a nube o carga de archivos, consulte Guía de comunicación de dispositivo a nube.

Para obtener instrucciones sobre el uso de propiedades deseadas, los métodos directos o los mensajes de nube a dispositivo, consulte Guía de comunicación de nube a dispositivo.

Módulos gemelos

Los módulos gemelos almacenan información relacionada con el módulo que:

  • Los módulos del dispositivo e IoT Hub pueden usar para sincronizar la configuración y las condiciones del módulo.

  • El back-end de la solución se puede usar para consultar e identificar operaciones de larga duración.

El ciclo de vida de un módulo gemelo está vinculado a la identidad del módulo correspondiente. Los módulos gemelos se crean y se eliminan implícitamente cuando se crea o se elimina una identidad del módulo en IoT Hub.

Un módulo gemelo es un documento JSON que incluye:

  • Etiquetas. Una sección del documento JSON en la que el back-end de solución puede leer y escribir. Las etiquetas no son visibles para los módulos en el dispositivo. Las etiquetas se establecen con fines de consulta.

  • Propiedades deseadas. Se usan junto con las propiedades notificadas para sincronizar la configuración o las condiciones del módulo. El back-end de solución puede establecer propiedades deseadas, y la aplicación de módulo puede leerlas. La aplicación de módulo también puede recibir notificaciones de cambios en las propiedades deseadas.

  • Propiedades notificadas. Se usan junto con las propiedades deseadas para sincronizar la configuración o las condiciones del módulo. La aplicación de módulo puede establecer propiedades notificadas, y el back-end de solución puede leerlas y consultarlas.

  • Propiedades de identidad del módulo. La raíz del documento JSON del módulo gemelo contiene las propiedades de solo lectura de la identidad de módulo correspondiente, almacenadas en el registro de identidades.

Representación de arquitectura del dispositivo gemelo

En el ejemplo siguiente se muestra un documento JSON del módulo gemelo:

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

En el objeto raíz están las propiedades de identidad del módulo y los objetos de contenedor para tags y las propiedades reported y desired. El contenedor properties incluye algunos elementos de solo lectura ($metadata y $version) descritos en las secciones Metadatos de módulo gemelo y Simultaneidad optimista.

Ejemplo de propiedad notificada

En el ejemplo anterior, el módulo gemelo contiene una propiedad batteryLevel notificada por la aplicación de módulo. Esta propiedad permite consultar y operar en los módulos en función del último nivel de batería notificado. Otros ejemplos incluyen la aplicación de módulo que notifica las funcionalidades del módulo o las opciones de conectividad.

Nota

Las propiedades notificadas simplifican los escenarios donde el back-end de la solución está interesado en el último valor conocido de una propiedad. Use mensajes del dispositivo a la nube si el back-end de la solución debe procesar la telemetría del módulo en forma de secuencias de eventos con marca de tiempo, por ejemplo, series temporales.

Ejemplo de propiedad deseada

En el ejemplo anterior, el back-end de la solución y la aplicación de módulo usan las propiedades deseadas y notificadas del módulo gemelo telemetryConfig para sincronizar la configuración de telemetría de este módulo. Por ejemplo:

  1. El back-end de la solución establece la propiedad deseada con el valor de configuración deseado. Esta es la parte del documento con el conjunto de propiedad deseada:

    ...
    "desired": {
        "telemetryConfig": {
            "sendFrequency": "5m"
        },
        ...
    },
    ...
    
  2. La aplicación de módulo recibe la notificación del cambio de inmediato si el módulo está conectado. Si no está conectado, la aplicación de módulo sigue el flujo de reconexión del módulo cuando se conecta. Después, la aplicación de módulo notifica la configuración actualizada (o una condición de error mediante la propiedad status). Esta es la parte de las propiedades notificadas:

    "reported": {
        "telemetryConfig": {
            "sendFrequency": "5m",
            "status": "success"
        }
        ...
    }
    
  3. El back-end de la solución puede realizar un seguimiento de los resultados de la operación de configuración en varios módulos; para ello, consulta los módulos gemelos.

Nota

Los fragmentos de código anteriores son ejemplos, optimizados para mejorar su legibilidad, de una manera de codificar una configuración de módulo y su estado. IoT Hub no impone un esquema específico para las propiedades deseadas y notificadas en los módulos gemelos.

Importante

IoT Plug and Play define un esquema que usa varias propiedades adicionales para sincronizar los cambios con las propiedades deseadas y notificadas. Si la solución usa IoT Plug and Play, debe seguir las convenciones de esta tecnología al actualizar las propiedades gemelas. Para obtener más información y un ejemplo, vea Propiedades editables en IoT Plug and Play.

Operaciones de back-end

Para trabajar en el back-end de la solución, el módulo gemelo usa las siguientes operaciones atómicas expuestas mediante HTTPS:

  • Recuperación del módulo gemelo por identificador. Esta operación devuelve el documento del módulo gemelo, incluidas las etiquetas y las propiedades del sistema, deseadas y notificadas.

  • Actualización parcial del módulo gemelo. Esta operación permite que el back-end de la solución actualice parcialmente las etiquetas o las propiedades deseadas del módulo gemelo. La actualización parcial se expresa como un documento JSON que agrega o actualiza cualquier propiedad. Las propiedades establecidas en null se quitan. El ejemplo siguiente crea una nueva propiedad deseada con el valor {"newProperty": "newValue"}, sobrescribe el valor existente de existingProperty con "otherNewValue", y quita otherOldProperty. No se realiza ningún cambio en otras etiquetas o propiedades deseadas existentes:

    {
        "properties": {
            "desired": {
                "newProperty": {
                    "nestedProperty": "newValue"
                },
                "existingProperty": "otherNewValue",
                "otherOldProperty": null
            }
        }
    }
    
  • Reemplazar propiedades deseadas. Esta operación permite que el back-end de la solución sobrescriba completamente todas las propiedades deseadas y sustituya un nuevo documento JSON para properties/desired.

  • Reemplazar etiquetas. Esta operación permite que el back-end de la solución sobrescriba completamente todas las etiquetas y sustituya un nuevo documento JSON para tags.

  • Recibir notificaciones gemelas. Esta operación permite que el back-end de la solución reciba una notificación cuando se modifique la gemela. Para ello, la solución de IoT debe crear una ruta y establecer el origen de datos igual a twinChangeEvents. De manera predeterminada, no existe tal ruta, por tanto, no se envían notificaciones gemelas. Si la tasa de cambio es demasiado alta, o por otras razones, como errores internos, IoT Hub podría enviar una sola notificación que contiene todos los cambios. Por lo tanto, si la aplicación necesita registro y auditoría confiables de todos los estados intermedios, debe usar mensajes del dispositivo a la nube. Para más información sobre las propiedades y el cuerpo devueltos en el mensaje de las notificaciones gemelas, consulte Esquemas de eventos que no son de telemetría.

Todas las operaciones anteriores admiten la simultaneidad optimista y requieren el permiso ServiceConnect, tal y como se define en el artículo Controlar el acceso a IoT Hub.

Además de estas operaciones, el back-end de la solución puede consultar el módulo gemelo mediante un lenguaje de consulta de IoT Hub de tipo SQL.

Operaciones de módulo

La aplicación de módulo opera en el módulo gemelo mediante las siguientes operaciones atómicas:

  • Recuperación del módulo gemelo. Esta operación devuelve el documento del módulo gemelo (incluidas las propiedades del sistema, deseadas y notificadas) para el módulo conectado actualmente.

  • Actualizar parcialmente propiedades notificadas. Esta operación permite la actualización parcial de las propiedades notificadas del módulo conectado actualmente. Esta operación usa el mismo formato de actualización JSON que el back-end de la solución usa para una actualización parcial de propiedades deseadas.

  • Observar las propiedades deseadas. El módulo conectado actualmente puede elegir recibir notificaciones de las actualizaciones de las propiedades deseadas cuando se produzcan. El módulo recibe la misma forma de actualización (sustitución parcial o completa) ejecutada por el back-end de la solución.

Todas las operaciones anteriores requieren el permiso DeviceConnect, tal y como se define en el artículo Control del acceso a IoT Hub.

Los SDK de dispositivos IoT de Azure permiten usar fácilmente las operaciones anteriores desde numerosos lenguajes y plataformas.

Formato de etiquetas y propiedades

Las etiquetas y las propiedades deseadas y notificadas son objetos JSON con las siguientes restricciones:

  • Claves: Todas las claves en objetos JSON tienen codificación UTF-8, con distinción de mayúsculas y minúsculas, y una longitud de hasta 1 KB. Entre los caracteres permitidos no se incluyen los caracteres de control UNICODE (segmentos C0 y C1), ni ., $ y SP.

  • Valores: Todos los valores en un objeto JSON pueden ser de los siguientes tipos JSON: booleano, número, cadena, objeto. También se admiten las matrices.

    • Los enteros pueden tener un valor mínimo de -4503599627370496 y un máximo de 4503599627370495.

    • Los valores de la cadena son codificados UTF-8 y pueden tener una longitud máxima de 4 KB.

  • Profundidad: La profundidad máxima de los objetos JSON en etiquetas y propiedades deseadas y notificadas es 10. Por ejemplo, el objeto siguiente es válido:

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

Tamaño del módulo gemelo

IoT Hub aplica un límite de tamaño de 8 KB en el valor de tags y un límite de tamaño de 32 KB cada uno en el valor de properties/desired y properties/reported. Estos totales son exclusivos de los elementos de solo lectura, como $version y $metadata/$lastUpdated.

El tamaño gemelo se calcula como sigue:

  • Para cada propiedad del documento JSON, IoT Hub calcula y agrega de forma acumulativa la longitud del valor y la clave de la propiedad.

  • Las claves de la propiedad se consideran cadenas codificadas UTF-8.

  • Los valores de propiedad simples se consideran cadenas codificadas UTF-8, valores numéricos (8 bytes) o valores booleanos (4 bytes).

  • El tamaño de las cadenas codificadas UTF-8 se calcula contando todos los caracteres, excepto los caracteres de control UNICODE (segmentos C0 y C1).

  • Los valores de propiedad complejos (objetos anidados) se calculan en función del tamaño agregado de las claves de la propiedad y los valores de propiedad que contienen.

IoT Hub rechaza con un error todas las operaciones que podrían aumentar el tamaño de los documentos por encima del límite.

Metadatos del módulo gemelo

IoT Hub conserva la marca de tiempo de la última actualización para cada objeto JSON en las propiedades deseadas y notificadas del módulo gemelo. Las marcas de tiempo están en formato UTC y se codifican con el formato ISO8601YYYY-MM-DDTHH:MM:SS.mmmZ. Por ejemplo:

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

Esta información se conserva en todo los niveles (no solo en las hojas de la estructura JSON) para conservar las actualizaciones que quitan las claves de objeto.

Simultaneidad optimista

Tanto las etiquetas como las propiedades deseadas y notificadas admiten la simultaneidad optimista. Si tiene que garantizar el orden de las actualizaciones de propiedades gemelas, considere la posibilidad de implementar la sincronización a nivel de la aplicación esperando la devolución de llamada de las propiedades notificadas antes de enviar la siguiente actualización.

Los módulos gemelos tienen una ETag (propiedad etag), según la norma RFC7232, que es la representación JSON del gemelo. Puede usar la propiedad etag en operaciones de actualización condicional desde el back-end de la solución para garantizar la coherencia. Esta es la única opción para garantizar la coherencia en las operaciones que implican al contenedor tags.

Las propiedades deseadas y notificadas del módulo gemelo también tienen un valor $version que se garantiza será incremental. De forma similar a una ETag, la parte que realiza la actualización puede usar la versión para garantizar la coherencia de las actualizaciones. Por ejemplo, una aplicación de módulo para una propiedad notificada o la solución de back-end para una propiedad deseada.

Las versiones también son útiles cuando un agente de observación (por ejemplo, la aplicación de módulo que observa las propiedades deseadas) tiene que conciliar las carreras entre el resultado de una operación de recuperación y una notificación de actualización. En la sección Flujo de reconexión de módulos se proporciona más información.

Flujo de reconexión de módulos

IoT Hub no conserva las notificaciones de actualización de las propiedades deseadas para los módulos desconectados. Se supone que un módulo que se está conectando debe recuperar el documento con todas las propiedades deseadas, además de suscribirse a las notificaciones de actualización. Dada la posibilidad de carreras entre las notificaciones de actualización y la recuperación completa, se debe asegurar el flujo siguiente:

  1. La aplicación de módulo se conecta a un centro de IoT.
  2. La aplicación de módulo se suscribe a las notificaciones de actualización de las propiedades deseadas.
  3. La aplicación de módulo recupera el documento completo de las propiedades deseadas.

La aplicación de módulo puede pasar por alto todas las notificaciones cuyo valor de $version sea anterior o igual a la versión del documento completo recuperado. Este enfoque es posible porque IoT Hub garantiza que las versiones siempre se incrementan.

Pasos siguientes

Para probar algunos de los conceptos descritos en este artículo, vea los siguientes tutoriales de IoT Hub: