Připojení zařízení k akcelerátoru řešení pro vzdálené monitorování (Windows)

V tomto kurzu implementujete zařízení Chiller , které odesílá následující telemetrii do akcelerátoru řešení pro vzdálené monitorování:

  • Teplota
  • Tlak
  • Vlhkost

Pro zjednodušení kód vygeneruje ukázkové telemetrické hodnoty pro Chiller. Ukázku můžete rozšířit připojením skutečných senzorů k zařízení a odesláním skutečné telemetrie.

Ukázkové zařízení také:

  • Odešle do řešení metadata, která popisují jeho možnosti.
  • Reaguje na akce aktivované na stránce Zařízení v řešení.
  • Reaguje na změny konfigurace odeslané ze stránky Zařízení v řešení.

K dokončení tohoto kurzu potřebujete mít aktivní účet Azure. Pokud účet nemáte, můžete si během několika minut vytvořit bezplatný zkušební účet. Podrobnosti najdete v článku Bezplatná zkušební verze Azure.

Než začnete

Než napíšete kód pro vaše zařízení, nasaďte akcelerátor řešení pro vzdálené monitorování a přidejte do řešení nové skutečné zařízení.

Nasazení akcelerátoru řešení pro vzdálené monitorování

Zařízení Chiller, které vytvoříte v tomto kurzu, odesílá data do instance akcelerátoru řešení pro vzdálené monitorování. Pokud jste ještě ve svém účtu Azure nezřídili akcelerátor řešení pro vzdálené monitorování, přečtěte si téma Nasazení akcelerátoru řešení pro vzdálené monitorování.

Po dokončení procesu nasazení řešení pro vzdálené monitorování kliknutím na spustit otevřete řídicí panel řešení v prohlížeči.

Řídicí panel řešení

Přidání zařízení do řešení pro vzdálené monitorování

Poznámka

Pokud jste už v řešení přidali zařízení, můžete tento krok přeskočit. Další krok však vyžaduje připojovací řetězec vašeho zařízení. Připojovací řetězec zařízení můžete načíst z Azure Portal nebo pomocí nástroje az iot CLI.

Aby se zařízení mohlo připojit k akcelerátoru řešení, musí se identifikovat, aby IoT Hub pomocí platných přihlašovacích údajů. Máte příležitost uložit připojovací řetězec zařízení, který obsahuje tyto přihlašovací údaje, když zařízení přidáte do řešení. Připojovací řetězec zařízení zahrnete do klientské aplikace později v tomto kurzu.

Pokud chcete přidat zařízení do řešení pro vzdálené monitorování, proveďte následující kroky na stránce Průzkumníka zařízení v řešení:

  1. Zvolte + Nové zařízení a pak jako typ zařízení zvolte Skutečné:

    Přidání skutečného zařízení

  2. Jako ID zařízení zadejte fyzický chladič . Zvolte možnosti symetrického klíče a automatického generování klíčů :

    Volba možností zařízení

  3. Zvolte Použít. Pak si poznamenejte hodnoty primárního klíče zařízení, primárního klíče a připojovacího řetězce :

    Načtení přihlašovacích údajů

Teď jste do akcelerátoru řešení pro vzdálené monitorování přidali skutečné zařízení a poznamenali jste si jeho připojovací řetězec zařízení. V následujících částech implementujete klientskou aplikaci, která používá připojovací řetězec zařízení pro připojení k vašemu řešení.

Klientská aplikace implementuje integrovaný model zařízení Chiller . Model zařízení akcelerátoru řešení určuje následující informace o zařízení:

  • Vlastnosti zařízení hlásí řešení. Například zařízení Chiller hlásí informace o jeho firmwaru a umístění.
  • Typy telemetrie, které zařízení odesílá do řešení. Například chladič odesílá hodnoty teploty, vlhkosti a tlaku.
  • Metody, které můžete naplánovat z řešení tak, aby běžely na zařízení. Například zařízení Chiller musí implementovat metody Reboot, FirmwareUpdate, EmergencyValveRelease a IncreasePressure .

V tomto kurzu se dozvíte, jak připojit skutečné zařízení k akcelerátoru řešení pro vzdálené monitorování.

Stejně jako u většiny vložených aplikací, které běží na omezených zařízeních, je klientský kód aplikace zařízení napsaný v jazyce C. V tomto kurzu sestavíte klientskou aplikaci zařízení na počítači s Windows.

Pokud dáváte přednost simulaci zařízení, přečtěte si téma Vytvoření a otestování nového simulovaného zařízení.

Požadavky

Pokud chcete dokončit kroky v tomto návodu, postupujte podle kroků v nastavení vývojového prostředí pro Windows a přidejte do počítače s Windows požadované vývojové nástroje a knihovny.

Zobrazení kódu

Ukázkový kód použitý v této příručce je k dispozici v úložišti GitHub sad SDK Azure IoT C.

Stažení zdrojového kódu a příprava projektu

Pokud chcete projekt připravit, naklonujte úložiště sad SDK Azure IoT C z GitHubu.

Ukázka se nachází ve složce samples, solutions/remote_monitoring_client .

Otevřete soubor remote_monitoring.c ve složce samples/solutions/remote_monitoring_client v textovém editoru.

Průvodce kódem

Tato část popisuje některé z klíčových částí vzorového kódu a vysvětluje, jak souvisí s akcelerátorem řešení pro vzdálené monitorování.

Následující fragment kódu ukazuje, jak jsou definované ohlášené vlastnosti, které popisují možnosti zařízení. Mezi tyto vlastnosti patří:

  • Umístění zařízení, které umožní akcelerátoru řešení přidat zařízení do mapy.
  • Aktuální verze firmwaru.
  • Seznam metod, které zařízení podporuje.
  • Schéma zpráv telemetrie odesílaných zařízením
typedef struct MESSAGESCHEMA_TAG
{
    char* name;
    char* format;
    char* fields;
} MessageSchema;

typedef struct TELEMETRYSCHEMA_TAG
{
    MessageSchema messageSchema;
} TelemetrySchema;

typedef struct TELEMETRYPROPERTIES_TAG
{
    TelemetrySchema temperatureSchema;
    TelemetrySchema humiditySchema;
    TelemetrySchema pressureSchema;
} TelemetryProperties;

typedef struct CHILLER_TAG
{
    // Reported properties
    char* protocol;
    char* supportedMethods;
    char* type;
    char* firmware;
    FIRMWARE_UPDATE_STATUS firmwareUpdateStatus;
    char* location;
    double latitude;
    double longitude;
    TelemetryProperties telemetry;

    // Manage firmware update process
    char* new_firmware_version;
    char* new_firmware_URI;
} Chiller;

Ukázka obsahuje serializaciToJson funkce, která serializuje tuto datovou strukturu pomocí knihovny Parson.

Ukázka obsahuje několik funkcí zpětného volání, které při interakci klienta s akcelerátorem řešení vytisknou informace do konzoly:

  • connection_status_callback
  • send_confirm_callback
  • reported_state_callback
  • device_method_callback

Následující fragment kódu ukazuje funkci device_method_callback . Tato funkce určuje akci, která se má provést při přijetí volání metody z akcelerátoru řešení. Funkce obdrží odkaz na datovou strukturu Chiller v parametru userContextCallback . Hodnota userContextCallback je nastavena, když je funkce zpětného volání nakonfigurována v hlavní funkci:

static int device_method_callback(const char* method_name, const unsigned char* payload, size_t size, unsigned char** response, size_t* response_size, void* userContextCallback)
{
    Chiller *chiller = (Chiller *)userContextCallback;

    int result;

    (void)printf("Direct method name:    %s\r\n", method_name);

    (void)printf("Direct method payload: %.*s\r\n", (int)size, (const char*)payload);

    if (strcmp("Reboot", method_name) == 0)
    {
        MESSAGERESPONSE(201, "{ \"Response\": \"Rebooting\" }")
    }
    else if (strcmp("EmergencyValveRelease", method_name) == 0)
    {
        MESSAGERESPONSE(201, "{ \"Response\": \"Releasing emergency valve\" }")
    }
    else if (strcmp("IncreasePressure", method_name) == 0)
    {
        MESSAGERESPONSE(201, "{ \"Response\": \"Increasing pressure\" }")
    }
    else if (strcmp("FirmwareUpdate", method_name) == 0)
    {
        if (chiller->firmwareUpdateStatus != IDLE)
        {
            (void)printf("Attempt to invoke firmware update out of order\r\n");
            MESSAGERESPONSE(400, "{ \"Response\": \"Attempting to initiate a firmware update out of order\" }")
        }
        else
        {
            getFirmwareUpdateValues(chiller, payload);

            if (chiller->new_firmware_version != NULL && chiller->new_firmware_URI != NULL)
            {
                // Create a thread for the long-running firmware update process.
                THREAD_HANDLE thread_apply;
                THREADAPI_RESULT t_result = ThreadAPI_Create(&thread_apply, do_firmware_update, chiller);
                if (t_result == THREADAPI_OK)
                {
                    (void)printf("Starting firmware update thread\r\n");
                    MESSAGERESPONSE(201, "{ \"Response\": \"Starting firmware update thread\" }")
                }
                else
                {
                    (void)printf("Failed to start firmware update thread\r\n");
                    MESSAGERESPONSE(500, "{ \"Response\": \"Failed to start firmware update thread\" }")
                }
            }
            else
            {
                (void)printf("Invalid method payload\r\n");
                MESSAGERESPONSE(400, "{ \"Response\": \"Invalid payload\" }")
            }
        }
    }
    else
    {
        // All other entries are ignored.
        (void)printf("Method not recognized\r\n");
        MESSAGERESPONSE(400, "{ \"Response\": \"Method not recognized\" }")
    }

    return result;
}

Když akcelerátor řešení volá metodu aktualizace firmwaru, ukázka deserializuje datovou část JSON a spustí vlákno na pozadí pro dokončení procesu aktualizace. Následující fragment kódu ukazuje do_firmware_update , která běží ve vlákně:

/*
 This is a thread allocated to process a long-running device method call.
 It uses device twin reported properties to communicate status values
 to the Remote Monitoring solution accelerator.
*/
static int do_firmware_update(void *param)
{
    Chiller *chiller = (Chiller *)param;
    printf("Running simulated firmware update: URI: %s, Version: %s\r\n", chiller->new_firmware_URI, chiller->new_firmware_version);

    printf("Simulating download phase...\r\n");
    chiller->firmwareUpdateStatus = DOWNLOADING;
    sendChillerReportedProperties(chiller);

    ThreadAPI_Sleep(5000);

    printf("Simulating apply phase...\r\n");
    chiller->firmwareUpdateStatus = APPLYING;
    sendChillerReportedProperties(chiller);

    ThreadAPI_Sleep(5000);

    printf("Simulating reboot phase...\r\n");
    chiller->firmwareUpdateStatus = REBOOTING;
    sendChillerReportedProperties(chiller);

    ThreadAPI_Sleep(5000);

    size_t size = strlen(chiller->new_firmware_version) + 1;
    (void)memcpy(chiller->firmware, chiller->new_firmware_version, size);

    chiller->firmwareUpdateStatus = IDLE;
    sendChillerReportedProperties(chiller);

    return 0;
}

Následující fragment kódu ukazuje, jak klient odešle zprávu telemetrie do akcelerátoru řešení. Vlastnosti zprávy zahrnují schéma zprávy, které akcelerátoru řešení pomáhá zobrazit telemetrii na řídicím panelu:

static void send_message(IOTHUB_DEVICE_CLIENT_HANDLE handle, char* message, char* schema)
{
    IOTHUB_MESSAGE_HANDLE message_handle = IoTHubMessage_CreateFromString(message);
    if (message_handle != NULL)
    {
        // Set system properties
        (void)IoTHubMessage_SetMessageId(message_handle, "MSG_ID");
        (void)IoTHubMessage_SetCorrelationId(message_handle, "CORE_ID");
        (void)IoTHubMessage_SetContentTypeSystemProperty(message_handle, "application%2fjson");
        (void)IoTHubMessage_SetContentEncodingSystemProperty(message_handle, "utf-8");

        // Set application properties
        MAP_HANDLE propMap = IoTHubMessage_Properties(message_handle);
        (void)Map_AddOrUpdate(propMap, "$$MessageSchema", schema);
        (void)Map_AddOrUpdate(propMap, "$$ContentType", "JSON");

        time_t now = time(0);
        struct tm* timeinfo;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4996) /* Suppress warning about possible unsafe function in Visual Studio */
#endif
        timeinfo = gmtime(&now);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
        char timebuff[50];
        strftime(timebuff, 50, "%Y-%m-%dT%H:%M:%SZ", timeinfo);
        (void)Map_AddOrUpdate(propMap, "$$CreationTimeUtc", timebuff);

        IoTHubDeviceClient_SendEventAsync(handle, message_handle, send_confirm_callback, NULL);

        IoTHubMessage_Destroy(message_handle);
    }
}

Hlavní funkce v ukázce:

  • Inicializuje a vypne subsystém sady SDK.
  • Inicializuje datovou strukturu Chiller .
  • Odešle ohlášené vlastnosti do akcelerátoru řešení.
  • Nakonfiguruje funkci zpětného volání metody zařízení.
  • Odesílá simulované telemetrické hodnoty do akcelerátoru řešení.
int main(void)
{
    srand((unsigned int)time(NULL));
    double minTemperature = 50.0;
    double minPressure = 55.0;
    double minHumidity = 30.0;
    double temperature = 0;
    double pressure = 0;
    double humidity = 0;

    (void)printf("This sample simulates a Chiller device connected to the Remote Monitoring solution accelerator\r\n\r\n");

    // Used to initialize sdk subsystem
    (void)IoTHub_Init();

    (void)printf("Creating IoTHub handle\r\n");
    // Create the iothub handle here
    device_handle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, MQTT_Protocol);
    if (device_handle == NULL)
    {
        (void)printf("Failure creating IotHub device. Hint: Check your connection string.\r\n");
    }
    else
    {
        // Setting connection status callback to get indication of connection to iothub
        (void)IoTHubDeviceClient_SetConnectionStatusCallback(device_handle, connection_status_callback, NULL);

        Chiller chiller;
        memset(&chiller, 0, sizeof(Chiller));
        chiller.protocol = "MQTT";
        chiller.supportedMethods = "Reboot,FirmwareUpdate,EmergencyValveRelease,IncreasePressure";
        chiller.type = "Chiller";
        size_t size = strlen(initialFirmwareVersion) + 1;
        chiller.firmware = malloc(size);
        if (chiller.firmware == NULL)
        {
            (void)printf("Chiller Firmware failed to allocate memory.\r\n");
        }
        else
        {
            memcpy(chiller.firmware, initialFirmwareVersion, size);
            chiller.firmwareUpdateStatus = IDLE;
            chiller.location = "Building 44";
            chiller.latitude = 47.638928;
            chiller.longitude = -122.13476;
            chiller.telemetry.temperatureSchema.messageSchema.name = "chiller-temperature;v1";
            chiller.telemetry.temperatureSchema.messageSchema.format = "JSON";
            chiller.telemetry.temperatureSchema.messageSchema.fields = "{\"temperature\":\"Double\",\"temperature_unit\":\"Text\"}";
            chiller.telemetry.humiditySchema.messageSchema.name = "chiller-humidity;v1";
            chiller.telemetry.humiditySchema.messageSchema.format = "JSON";
            chiller.telemetry.humiditySchema.messageSchema.fields = "{\"humidity\":\"Double\",\"humidity_unit\":\"Text\"}";
            chiller.telemetry.pressureSchema.messageSchema.name = "chiller-pressure;v1";
            chiller.telemetry.pressureSchema.messageSchema.format = "JSON";
            chiller.telemetry.pressureSchema.messageSchema.fields = "{\"pressure\":\"Double\",\"pressure_unit\":\"Text\"}";

            sendChillerReportedProperties(&chiller);

            (void)IoTHubDeviceClient_SetDeviceMethodCallback(device_handle, device_method_callback, &chiller);

            while (1)
            {
                temperature = minTemperature + ((double)(rand() % 10) + 5);
                pressure = minPressure + ((double)(rand() % 10) + 5);
                humidity = minHumidity + ((double)(rand() % 20) + 5);

                if (chiller.firmwareUpdateStatus == IDLE)
                {
                    (void)printf("Sending sensor value Temperature = %f %s,\r\n", temperature, "F");
                    (void)sprintf_s(msgText, sizeof(msgText), "{\"temperature\":%.2f,\"temperature_unit\":\"F\"}", temperature);
                    send_message(device_handle, msgText, chiller.telemetry.temperatureSchema.messageSchema.name);


                    (void)printf("Sending sensor value Pressure = %f %s,\r\n", pressure, "psig");
                    (void)sprintf_s(msgText, sizeof(msgText), "{\"pressure\":%.2f,\"pressure_unit\":\"psig\"}", pressure);
                    send_message(device_handle, msgText, chiller.telemetry.pressureSchema.messageSchema.name);


                    (void)printf("Sending sensor value Humidity = %f %s,\r\n", humidity, "%");
                    (void)sprintf_s(msgText, sizeof(msgText), "{\"humidity\":%.2f,\"humidity_unit\":\"%%\"}", humidity);
                    send_message(device_handle, msgText, chiller.telemetry.humiditySchema.messageSchema.name);
                }

                ThreadAPI_Sleep(5000);
            }

            (void)printf("\r\nShutting down\r\n");

            // Clean up the iothub sdk handle and free resources
            IoTHubDeviceClient_Destroy(device_handle);
            free(chiller.firmware);
            free(chiller.new_firmware_URI);
            free(chiller.new_firmware_version);
        }
    }
    // Shutdown the sdk subsystem
    IoTHub_Deinit();

    return 0;
}

Sestavení a spuštění ukázky

  1. Upravte soubor remote_monitoring.c tak, aby se nahradil <connectionstring> připojovacím řetězcem zařízení, který jste si poznamenali na začátku tohoto návodu při přidání zařízení do akcelerátoru řešení.

  2. Postupujte podle kroků v části Sestavení sady C SDK ve Windows a sestavte sadu SDK a klientskou aplikaci pro vzdálené monitorování.

  3. Na příkazovém řádku, který jste použili k sestavení řešení, spusťte:

    samples\solutions\remote_monitoring_client\Release\remote_monitoring_client.exe
    

    Konzola zobrazí zprávy takto:

    • Aplikace odesílá ukázkovou telemetrii do akcelerátoru řešení.
    • Reaguje na metody vyvolané z řídicího panelu řešení.

Zobrazení telemetrie zařízení

Telemetrii odeslanou ze zařízení můžete zobrazit na stránce Průzkumníka zařízení v řešení.

  1. Vyberte zařízení, které jste zřídili v seznamu zařízení na stránce Průzkumník zařízení . Na panelu se zobrazí informace o vašem zařízení, včetně vykreslení telemetrie zařízení:

    Zobrazit podrobnosti o zařízení

  2. Pokud chcete změnit zobrazení telemetrie, zvolte Tlak :

    Zobrazení telemetrie tlaku

  3. Pokud chcete zobrazit diagnostické informace o zařízení, posuňte se dolů k diagnostice:

    Zobrazení diagnostiky zařízení

Act on your device

K vyvolání metod na vašich zařízeních použijte stránku Průzkumníka zařízení v řešení pro vzdálené monitorování. Například v zařízeních Chladič řešení pro vzdálené monitorování implementují metodu restartování .

  1. Zvolte Zařízení a přejděte na stránku Průzkumníka zařízení v řešení.

  2. Vyberte zařízení, které jste zřídili v seznamu zařízení na stránce Průzkumník zařízení :

    Výběr skutečného zařízení

  3. Pokud chcete zobrazit seznam metod, které můžete volat na svém zařízení, zvolte Úlohy a pak Metody. Pokud chcete naplánovat spuštění úlohy na více zařízeních, můžete v seznamu vybrat několik zařízení. Panel Úlohy zobrazuje typy metod společné pro všechna vybraná zařízení.

  4. Zvolte Restartovat, nastavte název úlohy na RebootPhysicalChiller a pak zvolte Použít:

    Naplánování aktualizace firmwaru

  5. Posloupnost zpráv se zobrazí v konzole s kódem zařízení, zatímco simulované zařízení zpracovává metodu.

Poznámka

Pokud chcete sledovat stav úlohy v řešení, zvolte Zobrazit stav úlohy.

Další kroky

Článek Přizpůsobení akcelerátoru řešení pro vzdálené monitorování popisuje některé způsoby přizpůsobení akcelerátoru řešení.