Como enviar dados do sensor de ambiente em tempo real do Azure RTOS para o Hub IoT

Concluído

O sensor atualizado de temperatura, pressão e umidade do laboratório de microbiologia está funcionando bem no núcleo de tempo real do Azure Sphere. O cliente está feliz e pode executar seus experimentos. O cliente também gostaria de monitorar remotamente as condições do laboratório.

Nesta unidade, você aprenderá a ler dados do sensor de laboratório atualizado e a enviar os dados ao Hub IoT para monitoramento.

Arquitetura da solução

Veja a seguir uma descrição de como um aplicativo de alto nível do Azure Sphere pode ler dados do sensor de laboratório atualizado em execução em um dos núcleos de tempo real do Azure Sphere. O aplicativo de alto nível enviará esses dados com segurança para o Hub IoT.

Inter-core communications architecture.

Para recapitular a arquitetura da solução introduzida no laboratório do Azure RTOS.

  1. O thread do sensor de ambiente de tempo real do Azure RTOS é executado a cada 2 segundos. O thread armazena na memória os dados mais recentes de temperatura, umidade e pressão do ambiente.
  2. O aplicativo de streaming de telemetria de alto nível solicita do núcleo de tempo real os dados mais recentes do ambiente.
  3. O thread do serviço de ambiente de tempo real do Azure RTOS responde com os dados mais recentes do ambiente.
  4. O aplicativo de alto nível serializa os dados do ambiente como JSON e envia a mensagem de telemetria para o Hub IoT.
  5. O Azure IoT Explorer assina as mensagens de telemetria enviadas ao Hub IoT pelo dispositivo e exibe a telemetria.
  6. Você também pode definir a temperatura desejada para o local definindo uma propriedade. A propriedade é definida no dispositivo por meio de uma mensagem de dispositivo gêmeo do Hub IoT.
  7. Em seguida, o Azure Sphere define o modo de operação do HVAC para chegar à temperatura desejada.

Contrato de mensagem entre núcleos

Precisa haver um contrato que descreva a forma dos dados que estão sendo passados entre os núcleos. A estrutura a seguir declara o contrato entre núcleos usado nesta unidade. Encontre esse contato no diretório 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;

Segurança entre núcleos

Para se comunicar, os aplicativos em execução nos núcleos precisam ser configurados com as IDs de Componente correspondentes.

A ID do componente do aplicativo em tempo real pode ser encontrada no arquivo app_manifest.json dele.

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

Funcionalidades entre núcleos de alto nível

A propriedade AllowedApplicationConnections no arquivo app_manifest.json de alto nível é definida como a ID do componente do aplicativo de tempo real do Azure RTOS.

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

Inicializando comunicações entre núcleos

No InitPeripheralAndHandlers, é feita uma chamada para lp_interCoreCommunicationsEnable, passando a ID do componente de tempo real e da função de retorno de chamada entre núcleos.

A função de retorno de chamada entre núcleos será chamada quando for recebida uma mensagem do núcleo de tempo real.

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

Enviar uma solicitação ao aplicativo do núcleo de tempo real

Para solicitar dados de ambiente do núcleo de tempo real:

  1. Defina o comando de bloco de controle entre núcleos como LP_IC_ENVIRONMENT_SENSOR.
  2. Envie a mensagem de solicitação chamando lp_interCoreSendMessage e passando o bloco de controle entre núcleos.
/// <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));
    }
}

Recebendo mensagens entre núcleos

Quando o aplicativo de alto nível recebe uma mensagem, a função de retorno de chamada entre núcleos é chamada, passando uma referência para o bloco de controle entre núcleos que contém os dados do ambiente. O aplicativo serializa os dados como JSON, envia a mensagem de telemetria ao Hub IoT e o LED de status do HVAC é atualizado.

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