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

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.

Creare una soluzione di esempio C in Windows

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 Windows.

Creare un progetto iniziale in Visual Studio 2015 o Visual Studio 2017 e aggiungere i pacchetti NuGet del client dispositivo hub IoT:

  1. In Visual Studio creare un'applicazione console C usando il modello Applicazione console Win32 di Visual C++ . Assegnare al progetto il nome RMDevice.
  2. Nella pagina Impostazioni applicazione della Creazione guidata applicazione Win32 verificare che l'opzione Applicazione console sia selezionata e deselezionare Intestazione precompilata e Controlli Security Development Lifecycle (SDL).
  3. In Esplora soluzionieliminare i file stdafx.h, targetver.h e stdafx.cpp.
  4. In Esplora soluzionirinominare il file RMDevice.cpp in RMDevice.c.
  5. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto RMDevice e quindi scegliere Gestisci pacchetti NuGet. Fare clic su Sfoglia, quindi cercare e installare i seguenti pacchetti NuGet:

    • Microsoft.Azure.IoTHub.Serializer
    • Microsoft.Azure.IoTHub.IoTHubClient
    • Microsoft.Azure.IoTHub.MqttTransport
  6. In Esplora soluzioni fare clic sul progetto RMDevice e quindi scegliere Proprietà per aprire la finestra di dialogo Pagine delle proprietà del progetto. Per informazioni dettagliate, vedere Setting Visual C++ Project Properties (Impostazione delle proprietà dei progetti Visual C++).
  7. Fare clic sulla cartella Linker, quindi fare clic sulla pagina delle proprietà Input.
  8. Aggiungere crypt32.lib alla proprietà Dipendenze aggiuntive. Fare clic su OK e quindi scegliere nuovamente OK per salvare i valori delle proprietà del progetto.

Aggiungere la libreria Parson JSON al progetto RMDevice e aggiungere le istruzioni #include richieste:

  1. In una cartella appropriata nel computer, clonare il repository Parson GitHub usando il comando seguente:

    git clone https://github.com/kgabis/parson.git
    
  2. Copiare i file parson.h e parson.c dalla copia locale del repository Parson alla cartella del progetto RMDevice.

  3. In Visual Studio fare clic con il pulsante destro del mouse sul progetto RMDevice, scegliere Aggiungi e quindi Elemento esistente.

  4. Nella finestra di dialogo Aggiungi elemento esistente, selezionare i file parson.h e parson.c file nella cartella di progetto RMDevice. Quindi fare clic su Aggiungi per aggiungere i due file al progetto.

  5. In Visual Studio aprire il file RMDevice.c. Sostituire le istruzioni #include esistenti con il codice seguente:

    #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"
    
    Nota

    Compilando il progetto è possibile verificare che siano state impostate le dipendenze corrette.

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}
      

Compilare ed eseguire l'esempio

Aggiungere codice per richiamare la funzione remote_monitoring_run e quindi creare ed eseguire l'applicazione del dispositivo.

  1. Sostituire la funzione main con il codice seguente per richiamare la funzione remote_monitoring_run:

    int main()
    {
      remote_monitoring_run();
      return 0;
    }
    
  2. Fare clic su Compila e quindi su Compila soluzione per compilare l'applicazione del dispositivo.

  3. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto RMDevice, scegliere Debug e quindi fare clic su Avvia nuova istanza per eseguire l'esempio. Nella console vengono visualizzati i messaggi mano a mano che l'applicazione invia i dati di telemetria di esempio alla soluzione preconfigurata, riceve i valori delle proprietà desiderate impostate nel dashboard della soluzione e risponde ai metodi richiamati dal dashboard della soluzione.

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.