Como reinicializar remotamente o dispositivo do Azure Sphere com o método direto do Hub IoT do Azure

Concluído

Nesta unidade, você aprenderá a reiniciar remotamente um Azure Sphere do Azure IoT Explorer.

Noções básicas sobre comandos de método direto do Hub IoT

O Hub IoT do Azure usa comandos de método direto para invocar uma ação em um dispositivo. Frequentemente, os comandos são usados para o controle interativo de dispositivos, como ligar um ventilador, acender uma luz ou, no caso desta unidade, reiniciar o Azure Sphere.

Os métodos diretos do Hub IoT representam uma interação de solicitação e resposta com um dispositivo semelhante a uma chamada HTTP, no sentido em que são bem-sucedidas ou falham imediatamente (após um tempo limite especificado pelo usuário). Essa abordagem é útil para cenários em que o curso de ação imediata é diferente dependendo se o dispositivo foi capaz de responder.

Observação

Há vários motivos pelos quais você pode precisar reiniciar remotamente um Azure Sphere. Certificados de dispositivo, atualizações do SO e atualizações de aplicativos são concluídos em um ciclo de 24 horas ou após a reinicialização do dispositivo. Você pode ter um motivo operacional pelo qual precisa reiniciar o dispositivo para forçar uma atualização.

Reinicialização remota de um Azure Sphere

No IoT Explorer, você pode invocar um comando de método direto para reiniciar o dispositivo. Você precisa definir o número de segundos que o dispositivo aguardará antes de reiniciar. O Hub IoT do Azure envia uma mensagem de método direto com uma carga opcional para o dispositivo. O dispositivo responde com um código de status e, opcionalmente, uma mensagem indicando se o comando foi bem-sucedido ou falhou.

The illustration shows a device twin configuration pattern.

Etapas para reiniciar um IoT Explorer do Azure Sphere

As etapas a seguir descrevem como o Azure IoT Explorer e os métodos diretos do Hub IoT do Azure são usados para o controle de transferências de nuvem para dispositivo.

  1. No Azure IoT Explorer, você pode invocar o comando de método direto Restart Device do Hub IoT.
  2. Em seguida, o Hub IoT do Azure envia a mensagem do comando do método direto para o dispositivo.
  3. No Azure Sphere, a função RestartDeviceHandler é chamada.
  4. Em seguida, o dispositivo envia uma mensagem ReportedRestartUTC de dispositivo gêmeo para o Azure IoT para registrar a hora em que o dispositivo foi reiniciado.
  5. O método direto responde com um código de status HTTP e uma mensagem de resposta.
  6. Em seguida, o Azure Sphere é reiniciado.
  7. O Azure IoT Explorer consulta e exibe a propriedade ReportedRestartUTC do dispositivo.

Introdução às associações de método direto

Uma associação de método direto mapeia um nome de comando do método direto do Hub IoT com uma função de manipulador que será chamada para implementar a ação.

O exemplo a seguir declara uma associação de método direto para reiniciar o Azure Sphere. Essa declaração mapeia o comando de do método direto RestartDevice do Hub IoT do Azure com uma função de manipulador chamada RestartDeviceHandler.

static LP_DIRECT_METHOD_BINDING dm_restartDevice = {
    .methodName = "RestartDevice",
    .handler = RestartDeviceHandler };

Reinicialização remota do Azure Sphere

A seguir está a implementação da função de manipulador RestartDeviceHandler. A função de manipulador é chamada quando o dispositivo recebe uma mensagem de método direto chamada RestartDevice do Hub IoT do Azure.

/// <summary>
/// Start Device Power Restart Direct Method 'ResetMethod' integer seconds eg 5
/// </summary>
static LP_DIRECT_METHOD_RESPONSE_CODE RestartDeviceHandler(JSON_Value* json, LP_DIRECT_METHOD_BINDING* directMethodBinding, char** responseMsg)
{
    const size_t responseLen = 60; // Allocate and initialize a response message buffer. The calling function is responsible for the freeing memory
    static struct timespec period;

    *responseMsg = (char*)malloc(responseLen);
    memset(*responseMsg, 0, responseLen);

    if (json_value_get_type(json) != JSONNumber) { return LP_METHOD_FAILED; }

    int seconds = (int)json_value_get_number(json);

    // leave enough time for the device twin dt_reportedRestartUtc to update before restarting the device
    if (seconds > 2 && seconds < 10)
    {
        // Report Device Restart UTC
        lp_deviceTwinReportState(&dt_reportedRestartUtc, lp_getCurrentUtc(msgBuffer, sizeof(msgBuffer))); // LP_TYPE_STRING

        // Create Direct Method Response
        snprintf(*responseMsg, responseLen, "%s called. Restart in %d seconds", directMethodBinding->methodName, seconds);

        // Set One Shot LP_TIMER
        period = (struct timespec){ .tv_sec = seconds, .tv_nsec = 0 };
        lp_timerOneShotSet(&restartDeviceOneShotTimer, &period);

        return LP_METHOD_SUCCEEDED;
    }
    else
    {
        snprintf(*responseMsg, responseLen, "%s called. Restart Failed. Seconds out of range: %d", directMethodBinding->methodName, seconds);
        return LP_METHOD_FAILED;
    }
}

Capacidade PowerControls do Azure Sphere

A função RestartDeviceHandler configura um temporizador de uso único que invoca a função DelayRestartDeviceTimerHandler após o período de reinicialização especificado, medido em segundos. Na função DelayRestartDeviceTimerHandler, é feita uma chamada à API PowerManagement_ForceSystemReboot. A API PowerManagement_ForceSystemReboot requer que a capacidade PowerControls seja declarada no arquivo app_manifest.json.

"PowerControls": [
    "ForceReboot"
]

Como os métodos diretos são mapeados para os manipuladores

Todas as associações de método direto declaradas precisam ser adicionadas por referência à matriz directMethodBindingSet. Quando uma mensagem de método direto é recebida pelo dispositivo do Hub IoT do Azure, é verificado um nome de methodName correspondente na matriz directMethodBindingSet. Quando uma correspondência é encontrada, a função de manipulador correspondente é chamada.

LP_DIRECT_METHOD_BINDING* directMethodBindingSet[] = { &dm_restartDevice };

Abrir o conjunto de associação de método direto

O conjunto de associação de método direto é inicializado na função InitPeripheralsAndHandlers em main.c.

lp_directMethodSetOpen(directMethodBindingSet, NELEMS(directMethodBindingSet));

Fechar o conjunto de associação de método direto

O conjuntos de associação é fechado na função ClosePeripheralsAndHandlers em main.c.

lp_directMethodSetClose();