Envoi de données du capteur d’environnement de la pièce temps réel Azure RTOS à IoT Hub

Effectué

Le capteur de température, de pression et d’humidité du laboratoire de microbiologie mis à niveau s’exécute correctement sur le cœur temps réel Azure Sphere. Le client est satisfait et il peut effectuer ses expériences. Le client voudrait aussi surveiller à distance les conditions du laboratoire.

Dans cette unité, vous allez découvrir comment lire des données à partir du capteur du laboratoire mis à niveau et envoyer les données à IoT Hub à des fins de monitoring.

Architecture de solution

Ce qui suit décrit comment une application de haut niveau Azure Sphere peut lire des données à partir du capteur de laboratoire mis à niveau qui s’exécute sur un des cœurs temps réel Azure Sphere. L’application de haut niveau enverra alors ces données de manière sécurisée à IoT Hub.

Inter-core communications architecture.

Pour récapituler l’architecture de la solution introduite dans le laboratoire Azure RTOS.

  1. Le thread du capteur d’environnement temps réel Azure RTOS s’exécute toutes les 2 secondes. Le thread stocke en mémoire les dernières données de température, d’humidité et de pression de l’environnement.
  2. L’application de streaming de télémétrie de haut niveau demande au cœur temps réel les dernières données de l’environnement.
  3. Le thread du service de l’environnement temps réel Azure RTOS répond avec les données les plus récentes de l’environnement.
  4. L’application de haut niveau sérialise les données de l’environnement au format JSON et envoie le message de télémétrie à IoT Hub.
  5. Azure IoT Explorer s’abonne aux messages de télémétrie envoyés à IoT Hub par l’appareil et présente les données de télémétrie à l’utilisateur.
  6. Vous pouvez également régler la température souhaitée pour la pièce en définissant une propriété. La propriété est définie sur l’appareil via un message de jumeau d’appareil IoT Hub.
  7. L’appareil Azure Sphere définit ensuite le mode de fonctionnement de l’unité HVAC pour atteindre la température souhaitée.

Contrat de message inter-cœurs

Il doit exister un contrat qui décrit la forme des données passées entre les cœurs. La structure suivante déclare le contrat inter-cœurs utilisé dans cette unité. Vous pouvez trouver ce contrat dans le répertoire IntercoreContract.

typedef enum
{
    LP_IC_UNKNOWN,
    LP_IC_HEARTBEAT,
    LP_IC_ENVIRONMENT_SENSOR,
    LP_IC_SAMPLE_RATE
} LP_INTER_CORE_CMD;

typedef struct
{
    LP_INTER_CORE_CMD cmd;
    float temperature;
    float pressure;
    float humidity;
    int sample_rate;
} LP_INTER_CORE_BLOCK;

Sécurité inter-cœurs

Pour communiquer, les applications qui s’exécutent sur plusieurs cœurs doivent être configurées avec des ID de composant correspondants.

L’ID de composant pour l’application temps réel se trouve dans son fichier app_manifest.json.

{
  "SchemaVersion": 1,
  "Name": "AzureSphereIoTCentral",
  "ComponentId": "25025d2c-66da-4448-bae1-ac26fcdd3627",
  ...
}

Fonctionnalités inter-cœurs de haut niveau

La propriété AllowedApplicationConnections dans le fichier app_manifest.json de l’application de haut niveau est définie sur l’ID de composant de l’application temps réel Azure RTOS.

{
    ...
    "AllowedApplicationConnections": [ "6583cf17-d321-4d72-8283-0b7c5b56442b" ]
    ...
}

Initialisation des communications inter-cœurs

Dans InitPeripheralAndHandlers, un appel est fait à lp_interCoreCommunicationsEnable, en passant l’ID de composant du temps réel et la fonction de rappel inter-cœurs.

La fonction de rappel inter-cœurs sera appelée lors de la réception d’un message provenant du cœur temps réel.

lp_interCoreCommunicationsEnable(REAL_TIME_COMPONENT_ID, InterCoreHandler);  // Initialize Inter Core Communications

Envoi d’une demande à l’application du cœur temps réel

Pour demander les données de l’environnement au cœur temps réel, procédez comme suit :

  1. Définissez la commande du bloc de contrôle inter-cœurs sur LP_IC_ENVIRONMENT_SENSOR.
  2. Envoyez le message de demande en appelant lp_interCoreSendMessage et en passant le bloc de contrôle inter-cœurs.
/// <summary>
/// Read sensor and send to Azure IoT
/// </summary>
static void MeasureSensorHandler(EventLoopTimer* eventLoopTimer)
{
    if (ConsumeEventLoopTimerEvent(eventLoopTimer) != 0)
    {
        lp_terminate(ExitCode_ConsumeEventLoopTimeEvent);
    }
    else {
        // send request to Real-Time core app to read temperature, pressure, and humidity
        ic_control_block.cmd = LP_IC_ENVIRONMENT_SENSOR;
        lp_interCoreSendMessage(&ic_control_block, sizeof(ic_control_block));
    }
}

Réception de messages inter-cœurs

Quand l’application de haut niveau reçoit un message, la fonction de rappel inter-cœurs est appelée en passant une référence au bloc de contrôle inter-cœurs contenant les données de l’environnement. L’application sérialise les données au format JSON, et envoie le message de télémétrie à IoT Hub, puis la LED d’état de l’unité HVAC est mise à jour.

/// <summary>
/// Callback handler for Inter-Core Messaging - Does Device Twin Update, and Event Message
/// </summary>
static void InterCoreHandler(LP_INTER_CORE_BLOCK* ic_message_block)
{
    static int msgId = 0;

    switch (ic_message_block->cmd)
    {
    case LP_IC_ENVIRONMENT_SENSOR:
        if (snprintf(msgBuffer, JSON_MESSAGE_BYTES, msgTemplate, ic_message_block->temperature,
            ic_message_block->humidity, ic_message_block->pressure, msgId++) > 0) {

            Log_Debug("%s\n", msgBuffer);
            lp_azureMsgSendWithProperties(msgBuffer, telemetryMessageProperties, NELEMS(telemetryMessageProperties));

            SetHvacStatusColour((int)ic_message_block->temperature);

            // If the previous temperature not equal to the new temperature then update ReportedTemperature device twin
            if (previous_temperature != (int)ic_message_block->temperature) {
                lp_deviceTwinReportState(&dt_reportedTemperature, &ic_message_block->temperature);
                previous_temperature = (int)ic_message_block->temperature;
            }
        }
        break;
    default:
        break;
    }
}