Connettere il dispositivo alla soluzione preconfigurata per il monitoraggio remoto (Linux)

Panoramica dello scenario

In questo scenario, viene creato un dispositivo che invia la seguente telemetria alla soluzione preconfigurata per il monitoraggio remoto:

  • Temperatura esterna
  • Temperatura interna
  • Umidità

Per semplicità, il codice nel dispositivo genera valori di esempio, ma si consiglia di estendere l'esempio connettendo i sensori reali al dispositivo e inviando i dati di telemetria reali.

Inoltre, il dispositivo è in grado di rispondere ai metodi richiamati dal dashboard di soluzione e ai valori di proprietà desiderati impostati nel dashboard di soluzione.

Per completare l'esercitazione, è necessario un account Azure attivo. Se non si dispone di un account, è possibile creare un account di valutazione gratuita in pochi minuti. Per informazioni dettagliate, vedere la pagina relativa alla versione di valutazione gratuita di Azure.

Prima di iniziare

Prima di scrivere un codice per il dispositivo, occorre eseguire la soluzione preconfigurata di monitoraggio remoto e poi effettuare il provisioning di un nuovo dispositivo personalizzato all'interno della soluzione in questione.

Eseguire il provisioning della soluzione preconfigurata per il monitoraggio remoto

Il dispositivo creato in questa esercitazione invia dati a un'istanza della soluzione preconfigurata per il monitoraggio remoto. Se nel proprio account Azure non è già stato eseguito il provisioning della soluzione preconfigurata per il monitoraggio remoto, attenersi alla procedura seguente:

  1. Nella pagina https://www.azureiotsuite.com/ fare clic su + per creare una soluzione.
  2. Fare clic su Seleziona nel pannello Remote monitoring (Monitoraggio remoto) per creare la soluzione.
  3. Nella pagina per la creazione della soluzione di monitoraggio remoto immettere il nome desiderato in Nome soluzione e selezionare l'area in cui eseguire la distribuzione e quindi la sottoscrizione di Azure da usare. Fare clic su Crea soluzione.
  4. Attendere finché non viene completato il processo di provisioning.
Avviso

Le soluzioni preconfigurate usano servizi di Azure fatturabili. Al termine, assicurarsi di rimuovere la soluzione preconfigurata dalla sottoscrizione per evitare eventuali addebiti non necessari. Per rimuovere completamente una soluzione preconfigurata dalla sottoscrizione, visitare la pagina https://www.azureiotsuite.com/.

Al termine del processo di provisioning della soluzione di monitoraggio remoto, fare clic su Avvia per aprire il dashboard della soluzione nel browser.

Dashboard della soluzione

Effettuare il provisioning del dispositivo nella soluzione di monitoraggio remoto

Nota

Se è già stato eseguito il provisioning di un dispositivo nella soluzione, è possibile saltare questo passaggio. È necessario conoscere le credenziali del dispositivo quando si crea l'applicazione client.

Per connettere un dispositivo alla soluzione preconfigurata, è necessario che identifichi se stesso nell'hub IoT mediante delle credenziali valide. È possibile recuperare le credenziali del dispositivo dal dashboard della soluzione. Le istruzioni per includere le credenziali del dispositivo nell'applicazione client sono illustrate più avanti in questa esercitazione.

Per aggiungere un dispositivo alla soluzione per il monitoraggio remoto, completare i passaggi seguenti nel dashboard della soluzione:

  1. Nell'angolo inferiore sinistro del dashboard fare clic su Aggiungi un dispositivo.

    Aggiungere un dispositivo

  2. Nel pannello Dispositivo personalizzato fare clic su Aggiungi nuovo.

    Aggiungere un dispositivo personalizzato

  3. Scegliere Let me define my own Device ID (Desidero definire il mio ID dispositivo). Immettere un ID dispositivo, ad esempio mydevice, fare clic su Controlla ID per verificare che tale nome non sia già in uso e quindi fare clic su Crea per effettuare il provisioning del dispositivo.

    Aggiungere un ID dispositivo

  4. Annotare le credenziali del dispositivo (ID dispositivo, nome host dell'hub IoT e chiave dispositivo). Questi valori sono necessari per consentire all'applicazione client di connettersi alla soluzione per il monitoraggio remoto. Fare quindi clic su Done.

    Vedere le credenziali del dispositivo

  5. Selezionare il dispositivo nell'elenco dei dispositivi nel dashboard della soluzione. Nel pannello Dettagli dispositivo fare clic su Attiva dispositivo. Lo stato del dispositivo è ora In esecuzione. La soluzione per il monitoraggio remoto può ora ricevere i dati di telemetria dal dispositivo e richiamare i metodi sul dispositivo.

Compilare ed eseguire un client C Linux di esempio

La procedura seguente illustra come creare un'applicazione client che comunica con la soluzione di monitoraggio remoto preconfigurata. Questa applicazione è scritta in C e compilata ed eseguita in Ubuntu Linux.

Per completare questa procedura, è necessario un dispositivo che esegue Ubuntu versione 15.04 o 15.10. Prima di continuare, installare i pacchetti dei prerequisiti nel dispositivo Ubuntu usando il comando seguente:

sudo apt-get install cmake gcc g++

Installare le librerie client sul dispositivo

Le librerie client dell'hub IoT di Azure sono disponibili in forma di pacchetto da installare sul dispositivo Ubuntu tramite il comando apt-get . Completare la procedura seguente per installare il pacchetto che contiene la libreria del client dell'hub IoT e i file d'intestazione nel computer Ubuntu:

  1. In una shell, aggiungere il repository AzureIoT al computer:

    sudo add-apt-repository ppa:aziotsdklinux/ppa-azureiot
    sudo apt-get update
    
  2. Installare il pacchetto azure-iot-sdk-c-dev

    sudo apt-get install -y azure-iot-sdk-c-dev
    

Installare il parser JSON Parson

Le librerie client di hub IoT usano il parser JSON per analizzare il payload dei messaggi. In una cartella appropriata nel computer, clonare il repository Parson GitHub usando il comando seguente:

git clone https://github.com/kgabis/parson.git

Preparare il progetto

Nel computer Ubuntu creare una cartella denominata remote_monitoring. Nella cartella remote_monitoring:

  • Creare i quattro file main.c, remote_monitoring.c, remote_monitoring.h e CMakeLists.txt.
  • Creare una cartella denominata parson.

Copiare i file parson.c e parson.h dalla copia locale del repository Parson nella cartella remote_monitoring/parson.

In un editor di testo aprire il file remote_monitoring.c. Aggiungere le istruzioni #include seguenti:

#include "iothubtransportmqtt.h"
#include "schemalib.h"
#include "iothub_client.h"
#include "serializer_devicetwin.h"
#include "schemaserializer.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"
#include "parson.h"

Specificare il comportamento del dispositivo IoT

La libreria client serializzatrice di hub IoT usa un modello per specificare il formato dei messaggi che il dispositivo scambia con hub IoT.

  1. Aggiungere le seguenti dichiarazioni di variabili dopo le istruzioni #include . Sostituire i valori segnaposto [ID dispositivo] e [Chiave dispositivo] con i valori annotati per il dispositivo nel dashboard della soluzione di monitoraggio remoto. Usare il nome host hub IoT del dashboard della soluzione per sostituire [Nome IoTHub]. Ad esempio, se il nome host dell'hub IoT è contoso.azure-devices.net, sostituire [Nome IoTHub] con contoso:

    static const char* deviceId = "[Device Id]";
    static const char* connectionString = "HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]";
    
  2. Aggiungere il codice seguente per definire il modello che consente al dispositivo di comunicare con l'hub IoT. Questo modello consente di specificare che il dispositivo:

    • Può inviare temperatura, temperatura esterna, umidità e un ID dispositivo come dati di telemetria.
    • Può inviare i metadati relativi al dispositivo all'hub IoT. Il dispositivo invia i metadati di base in un oggetto DeviceInfo all'avvio.
    • Può inviare proprietà segnalate al dispositivo gemello nell'hub IoT. Queste proprietà segnalate sono raggruppate in proprietà di configurazione, dispositivo e di sistema.
    • Può ricevere e agire sulle proprietà desiderate impostate nel dispositivo gemello nell'hub IoT.
    • È in grado di rispondere al riavvio e ai metodi diretti InitiateFirmwareUpdate richiamati tramite il portale della soluzione. Il dispositivo invia le informazioni sui metodi diretti che supporta usando le proprietà segnalate.

      // Define the Model
      BEGIN_NAMESPACE(Contoso);
      
      /* Reported properties */
      DECLARE_STRUCT(SystemProperties,
       ascii_char_ptr, Manufacturer,
       ascii_char_ptr, FirmwareVersion,
       ascii_char_ptr, InstalledRAM,
       ascii_char_ptr, ModelNumber,
       ascii_char_ptr, Platform,
       ascii_char_ptr, Processor,
       ascii_char_ptr, SerialNumber
      );
      
      DECLARE_STRUCT(LocationProperties,
       double, Latitude,
       double, Longitude
      );
      
      DECLARE_STRUCT(ReportedDeviceProperties,
       ascii_char_ptr, DeviceState,
       LocationProperties, Location
      );
      
      DECLARE_MODEL(ConfigProperties,
       WITH_REPORTED_PROPERTY(double, TemperatureMeanValue),
       WITH_REPORTED_PROPERTY(uint8_t, TelemetryInterval)
      );
      
      /* Part of DeviceInfo */
      DECLARE_STRUCT(DeviceProperties,
       ascii_char_ptr, DeviceID,
       _Bool, HubEnabledState
      );
      
      DECLARE_DEVICETWIN_MODEL(Thermostat,
       /* Telemetry (temperature, external temperature and humidity) */
       WITH_DATA(double, Temperature),
       WITH_DATA(double, ExternalTemperature),
       WITH_DATA(double, Humidity),
       WITH_DATA(ascii_char_ptr, DeviceId),
      
       /* DeviceInfo */
       WITH_DATA(ascii_char_ptr, ObjectType),
       WITH_DATA(_Bool, IsSimulatedDevice),
       WITH_DATA(ascii_char_ptr, Version),
       WITH_DATA(DeviceProperties, DeviceProperties),
      
       /* Device twin properties */
       WITH_REPORTED_PROPERTY(ReportedDeviceProperties, Device),
       WITH_REPORTED_PROPERTY(ConfigProperties, Config),
       WITH_REPORTED_PROPERTY(SystemProperties, System),
      
       WITH_DESIRED_PROPERTY(double, TemperatureMeanValue, onDesiredTemperatureMeanValue),
       WITH_DESIRED_PROPERTY(uint8_t, TelemetryInterval, onDesiredTelemetryInterval),
      
       /* Direct methods implemented by the device */
       WITH_METHOD(Reboot),
       WITH_METHOD(InitiateFirmwareUpdate, ascii_char_ptr, FwPackageURI),
      
       /* Register direct methods with solution portal */
       WITH_REPORTED_PROPERTY(ascii_char_ptr_no_quotes, SupportedMethods)
      );
      
      END_NAMESPACE(Contoso);
      

Implementare il comportamento del dispositivo

Aggiungere il codice che implementa il comportamento definito nel modello.

  1. Aggiungere le funzioni seguenti che gestiscono le proprietà desiderate impostate nel dashboard della soluzione. Tali proprietà desiderate sono definite nel modello:

    void onDesiredTemperatureMeanValue(void* argument)
    {
      /* By convention 'argument' is of the type of the MODEL */
      Thermostat* thermostat = argument;
      printf("Received a new desired_TemperatureMeanValue = %f\r\n", thermostat->TemperatureMeanValue);
    
    }
    
    void onDesiredTelemetryInterval(void* argument)
    {
      /* By convention 'argument' is of the type of the MODEL */
      Thermostat* thermostat = argument;
      printf("Received a new desired_TelemetryInterval = %d\r\n", thermostat->TelemetryInterval);
    }
    
  2. Aggiungere le funzioni seguenti che gestiscono i metodi diretti richiamati tramite l'hub IoT. Questi metodi diretti sono definiti nel modello:

    /* Handlers for direct methods */
    METHODRETURN_HANDLE Reboot(Thermostat* thermostat)
    {
      (void)(thermostat);
    
      METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Rebooting\"");
      printf("Received reboot request\r\n");
      return result;
    }
    
    METHODRETURN_HANDLE InitiateFirmwareUpdate(Thermostat* thermostat, ascii_char_ptr FwPackageURI)
    {
      (void)(thermostat);
    
      METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Initiating Firmware Update\"");
      printf("Recieved firmware update request. Use package at: %s\r\n", FwPackageURI);
      return result;
    }
    
  3. Aggiungere la funzione seguente che invia un messaggio alla soluzione preconfigurata:

    /* Send data to IoT Hub */
    static void sendMessage(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
    {
      IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
      if (messageHandle == NULL)
      {
        printf("unable to create a new IoTHubMessage\r\n");
      }
      else
      {
        if (IoTHubClient_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
        {
          printf("failed to hand over the message to IoTHubClient");
        }
        else
        {
          printf("IoTHubClient accepted the message for delivery\r\n");
        }
    
        IoTHubMessage_Destroy(messageHandle);
      }
      free((void*)buffer);
    }
    
  4. Aggiungere il gestore di callback seguente che viene eseguito quando il dispositivo ha inviato i nuovi valori di proprietà segnalati alla soluzione preconfigurata:

    /* Callback after sending reported properties */
    void deviceTwinCallback(int status_code, void* userContextCallback)
    {
      (void)(userContextCallback);
      printf("IoTHub: reported properties delivered with status_code = %u\n", status_code);
    }
    
  5. Aggiungere la funzione seguente per connettere il dispositivo alla soluzione preconfigurata nel cloud e scambiare dati. Questa funzione esegue questa procedura:

    • Inizializza la piattaforma.
    • Registra lo spazio dei nomi Contoso con la libreria di serializzazione.
    • Inizializza il client con la stringa di connessione del dispositivo.
    • Creare un'istanza del modello Thermostat.
    • Crea e invia i valori delle proprietà segnalate.
    • Invia un oggetto DeviceInfo.
    • Crea un ciclo per inviare dati di telemetria ogni secondo.
    • Deinizializza tutte le risorse.

      void remote_monitoring_run(void)
      {
        if (platform_init() != 0)
        {
          printf("Failed to initialize the platform.\n");
        }
        else
        {
          if (SERIALIZER_REGISTER_NAMESPACE(Contoso) == NULL)
          {
            printf("Unable to SERIALIZER_REGISTER_NAMESPACE\n");
          }
          else
          {
            IOTHUB_CLIENT_HANDLE iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, MQTT_Protocol);
            if (iotHubClientHandle == NULL)
            {
              printf("Failure in IoTHubClient_CreateFromConnectionString\n");
            }
            else
            {
      #ifdef MBED_BUILD_TIMESTAMP
              // For mbed add the certificate information
              if (IoTHubClient_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
              {
                  printf("Failed to set option \"TrustedCerts\"\n");
              }
      #endif // MBED_BUILD_TIMESTAMP
              Thermostat* thermostat = IoTHubDeviceTwin_CreateThermostat(iotHubClientHandle);
              if (thermostat == NULL)
              {
                printf("Failure in IoTHubDeviceTwin_CreateThermostat\n");
              }
              else
              {
                /* Set values for reported properties */
                thermostat->Config.TemperatureMeanValue = 55.5;
                thermostat->Config.TelemetryInterval = 3;
                thermostat->Device.DeviceState = "normal";
                thermostat->Device.Location.Latitude = 47.642877;
                thermostat->Device.Location.Longitude = -122.125497;
                thermostat->System.Manufacturer = "Contoso Inc.";
                thermostat->System.FirmwareVersion = "2.22";
                thermostat->System.InstalledRAM = "8 MB";
                thermostat->System.ModelNumber = "DB-14";
                thermostat->System.Platform = "Plat 9.75";
                thermostat->System.Processor = "i3-7";
                thermostat->System.SerialNumber = "SER21";
                /* Specify the signatures of the supported direct methods */
                thermostat->SupportedMethods = "{\"Reboot\": \"Reboot the device\", \"InitiateFirmwareUpdate--FwPackageURI-string\": \"Updates device Firmware. Use parameter FwPackageURI to specifiy the URI of the firmware file\"}";
      
                /* Send reported properties to IoT Hub */
                if (IoTHubDeviceTwin_SendReportedStateThermostat(thermostat, deviceTwinCallback, NULL) != IOTHUB_CLIENT_OK)
                {
                  printf("Failed sending serialized reported state\n");
                }
                else
                {
                  printf("Send DeviceInfo object to IoT Hub at startup\n");
      
                  thermostat->ObjectType = "DeviceInfo";
                  thermostat->IsSimulatedDevice = 0;
                  thermostat->Version = "1.0";
                  thermostat->DeviceProperties.HubEnabledState = 1;
                  thermostat->DeviceProperties.DeviceID = (char*)deviceId;
      
                  unsigned char* buffer;
                  size_t bufferSize;
      
                  if (SERIALIZE(&buffer, &bufferSize, thermostat->ObjectType, thermostat->Version, thermostat->IsSimulatedDevice, thermostat->DeviceProperties) != CODEFIRST_OK)
                  {
                    (void)printf("Failed serializing DeviceInfo\n");
                  }
                  else
                  {
                    sendMessage(iotHubClientHandle, buffer, bufferSize);
                  }
      
                  /* Send telemetry */
                  thermostat->Temperature = 50;
                  thermostat->ExternalTemperature = 55;
                  thermostat->Humidity = 50;
                  thermostat->DeviceId = (char*)deviceId;
      
                  while (1)
                  {
                    unsigned char*buffer;
                    size_t bufferSize;
      
                    (void)printf("Sending sensor value Temperature = %f, Humidity = %f\n", thermostat->Temperature, thermostat->Humidity);
      
                    if (SERIALIZE(&buffer, &bufferSize, thermostat->DeviceId, thermostat->Temperature, thermostat->Humidity, thermostat->ExternalTemperature) != CODEFIRST_OK)
                    {
                      (void)printf("Failed sending sensor value\r\n");
                    }
                    else
                    {
                      sendMessage(iotHubClientHandle, buffer, bufferSize);
                    }
      
                    ThreadAPI_Sleep(1000);
                  }
      
                  IoTHubDeviceTwin_DestroyThermostat(thermostat);
                }
              }
              IoTHubClient_Destroy(iotHubClientHandle);
            }
            serializer_deinit();
          }
        }
        platform_deinit();
      }
      

      Per riferimento, ecco un esempio di messaggio di Telemetria inviato alla soluzione preconfigurata:

      {"DeviceId":"mydevice01", "Temperature":50, "Humidity":50, "ExternalTemperature":55}
      

Chiamare la funzione remote_monitoring_run

In un editor di testo aprire il file remote_monitoring.h. Aggiungere il codice seguente:

void remote_monitoring_run(void);

In un editor di testo aprire il file main. c . Aggiungere il codice seguente:

#include "remote_monitoring.h"

int main(void)
{
    remote_monitoring_run();

    return 0;
}

Compilare ed eseguire l'applicazione

La procedura seguente descrive i metodi d'uso di CMake per compilare l'applicazione client.

  1. In un editor di testo aprire il file CMakeLists.txt nella cartella remote_monitoring.

  2. Aggiungere le istruzioni seguenti per definire la modalità di compilazione dell'applicazione client:

    macro(compileAsC99)
      if (CMAKE_VERSION VERSION_LESS "3.1")
        if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
          set (CMAKE_C_FLAGS "--std=c99 ${CMAKE_C_FLAGS}")
          set (CMAKE_CXX_FLAGS "--std=c++11 ${CMAKE_CXX_FLAGS}")
        endif()
      else()
        set (CMAKE_C_STANDARD 99)
        set (CMAKE_CXX_STANDARD 11)
      endif()
    endmacro(compileAsC99)
    
    cmake_minimum_required(VERSION 2.8.11)
    compileAsC99()
    
    set(AZUREIOT_INC_FOLDER "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/parson" "/usr/include/azureiot" "/usr/include/azureiot/inc")
    
    include_directories(${AZUREIOT_INC_FOLDER})
    
    set(sample_application_c_files
        ./parson/parson.c
        ./remote_monitoring.c
        ./main.c
    )
    
    set(sample_application_h_files
        ./parson/parson.h
        ./remote_monitoring.h
    )
    
    add_executable(sample_app ${sample_application_c_files} ${sample_application_h_files})
    
    target_link_libraries(sample_app
        serializer
        iothub_client
        iothub_client_mqtt_transport
        aziotsharedutil
        umqtt
        pthread
        curl
        ssl
        crypto
        m
    )
    
  3. Nella cartella remote_monitoring creare una cartella per archiviare i file make generati da CMake e quindi eseguire i comandi cmake e make come segue:

    mkdir cmake
    cd cmake
    cmake ../
    make
    
  4. Eseguire l'applicazione client e inviare dati di telemetria all'hub IoT:

    ./sample_app
    

Visualizzare la telemetria del dispositivo nel dashboard

Il dashboard nella soluzione di monitoraggio remoto consente di visualizzare la telemetria che i dispositivi inviano all'hub IoT.

  1. Nel browser tornare al dashboard della soluzione di monitoraggio remoto e fare clic su Dispositivi nel pannello di sinistra per passare a Elenco dispositivi.
  2. In Devices list (Elenco dispositivi) si noterà che lo stato del dispositivo è ora In esecuzione. Se non lo è, nel pannello Dettagli dispositivo fare clic su Attiva dispositivo.

    Visualizzare lo stato dei dispositivi

  3. Fare clic su Dashboard per tornare al dashboard e selezionare il dispositivo nell'elenco a discesa Dispositivo da visualizzare per visualizzarne i dati di telemetria. La telemetria dall'applicazione di esempio è di 50 unità per la temperatura interna, 55 unità per la temperatura esterna e 50 unità per l’umidità.

    Visualizzare la telemetria dei dispositivi

Richiamare un metodo sul dispositivo

Il dashboard nella soluzione di monitoraggio remoto consente di richiamare metodi sui dispositivi tramite l'hub IoT. Nella soluzione di monitoraggio remota, ad esempio, è possibile richiamare un metodo per simulare il riavvio di un dispositivo.

  1. Nel dashboard della soluzione di monitoraggio remoto fare clic su Dispositivi nel pannello di sinistra per passare a Elenco dispositivi.
  2. In Elenco dispositivi fare clic sull'ID del proprio dispositivo.
  3. Nel pannello Dettagli dispositivo fare clic su Metodi.

    Metodi per il dispositivo

  4. Nel menu a discesa Metodi, selezionare InitiateFirmwareUpdate, quindi in FWPACKAGEURI immettere un URL fittizio. Fare clic su Richiama metodo per chiamare il metodo sul dispositivo.

    Richiamare un metodo per il dispositivo

  5. Viene visualizzato un messaggio nella console che esegue il codice del dispositivo quando il dispositivo gestisce il metodo. I risultati del metodo vengono aggiunti alla cronologia nel portale delle soluzioni:

    Visualizzare la cronologia del metodo

Passaggi successivi

L'articolo Personalizzazione delle soluzioni preconfigurate descrive alcuni modi per estendere questo esempio. Le estensioni possibili comprendono l'utilizzo di sensori reali e implementazione di comandi aggiuntivi.

Per altre informazioni sulle autorizzazioni visitare il sito azureiotsuite.com.