Usare le proprietà desiderate per configurare i dispositivi

Introduzione

In Introduzione ai dispositivi gemelli dell'hub IoT è stato illustrato come impostare i metadati dei dispositivi dal back-end della soluzione usando tag, come segnalare le condizioni dei dispositivi da un'app per dispositivo con le proprietà segnalate e come eseguire query su tali informazioni con un linguaggio simile a SQL.

In questa esercitazione verrà illustrato come usare le proprietà desiderate del dispositivo gemello con le proprietà segnalate per configurare in remoto le app per dispositivi. In particolare, questa esercitazione descrive come le proprietà segnalate e desiderate di un dispositivo gemello supportano la configurazione in più passaggi di un'applicazione per dispositivi e come ottenere nel back-end della soluzione la visibilità dello stato di tale operazione in tutti i dispositivi. Per altre informazioni sul ruolo delle configurazioni del dispositivo, vedere Panoramica della gestione dei dispositivi con l'hub IoT.

In genere, l'uso di dispositivi gemelli abilita il back-end della soluzione per specificare la configurazione voluta per i dispositivi gestiti, invece di inviare comandi specifici. Il dispositivo ha quindi la responsabilità di configurare il modo migliore per aggiornare la propria configurazione (importante negli scenari IoT in cui le condizioni specifiche del dispositivo influiscono sulla possibilità di eseguire immediatamente determinati comandi) segnalando continuamente al back-end della soluzione lo stato corrente e le potenziali condizioni di errore del processo di aggiornamento. Questo modello è determinante per gestire grandi set di dispositivi, perché offre al back-end della soluzione la visibilità completa dello stato del processo di configurazione in tutti i dispositivi.

Nota

Negli scenari in cui i dispositivi sono controllati in modo più interattivo (come nel caso dell'attivazione di una ventola da un'app controllata dall'utente), può essere opportuno usare metodi diretti.

In questa esercitazione, il back-end della soluzione modifica la configurazione della telemetria di un dispositivo di destinazione e di conseguenza l'app per dispositivi segue un processo in più passaggi per applicare un aggiornamento della configurazione (che richiede ad esempio un riavvio del modulo software che nell'esercitazione viene simulato con un semplice ritardo).

Il back-end della soluzione archivia la configurazione nelle proprietà desiderate del dispositivo gemello nel modo seguente:

    {
        ...
        "properties": {
            ...
            "desired": {
                "telemetryConfig": {
                    "configId": "{id of the configuration}",
                    "sendFrequency": "{config}"
                }
            }
            ...
        }
        ...
    }

Nota

Dato che le configurazioni possono essere oggetti complessi, per semplificarne il confronto vengono assegnati ID univoci (hash o GUID).

L'app per dispositivi segnala la propria configurazione corrente eseguendo il mirroring della proprietà desiderata telemetryConfig nelle proprietà segnalate:

    {
        "properties": {
            ...
            "reported": {
                "telemetryConfig": {
                    "changeId": "{id of the current configuration}",
                    "sendFrequency": "{current configuration}",
                    "status": "Success",
                }
            }
            ...
        }
    }

Si noti che la proprietà segnalata telemetryConfig ha una proprietà status aggiuntiva usata per segnalare lo stato del processo di aggiornamento della configurazione.

Quando viene ricevuta una nuova configurazione desiderata, l'app per dispositivi segnala una configurazione in sospeso modificando le informazioni:

    {
        "properties": {
            ...
            "reported": {
                "telemetryConfig": {
                    "changeId": "{id of the current configuration}",
                    "sendFrequency": "{current configuration}",
                    "status": "Pending",
                    "pendingConfig": {
                        "changeId": "{id of the pending configuration}",
                        "sendFrequency": "{pending configuration}"
                    }
                }
            }
            ...
        }
    }

In un secondo momento l'app per dispositivi segnala l'esito positivo o negativo dell'operazione aggiornando la proprietà sopra indicata. Si noti che il back-end della soluzione può eseguire in qualsiasi momento query sullo stato del processo di configurazione in tutti i dispositivi.

Questa esercitazione illustra come:

  • Creare un'app per dispositivo simulato che riceve aggiornamenti di configurazione dal back-end della soluzione e segnala più aggiornamenti come proprietà segnalate nel processo di aggiornamento della configurazione.
  • Creare un'app back-end che aggiorna la configurazione desiderata di un dispositivo e quindi esegue query sul processo di aggiornamento della configurazione.

Al termine di questa esercitazione si avranno due app console .NET:

  • SimulateDeviceConfiguration, un'app per dispositivo simulata che attende un aggiornamento della configurazione desiderata e segnala lo stato di un processo di aggiornamento della configurazione simulata.
  • SetDesiredConfigurationAndQuery.js, un'app back-end che imposta la configurazione desiderata in un dispositivo ed esegue query sul processo di aggiornamento della configurazione.

Nota

L'articolo Azure IoT SDK contiene informazioni sui componenti Azure IoT SDK che consentono di compilare le app back-end e per dispositivi.

Per completare l'esercitazione, sono necessari gli elementi seguenti:

  • Visual Studio 2015 o Visual Studio 2017.
  • Un account Azure attivo. Se non si ha un account, è possibile crearne uno gratuito in pochi minuti.

Se è stata seguita l'esercitazione Introduzione ai dispositivi gemelli sono già disponibili un hub IoT e un'identità del dispositivo denominata myDeviceId. È quindi possibile ignorare la sezione Creare l'app per dispositivo simulata.

Creare un hub IoT

Creare un hub IoT per connettere l'app per dispositivo simulato. La procedura seguente illustra come completare questa attività usando il portale di Azure.

  1. Accedere al portale di Azure.
  2. Nell'indice fare clic su Nuovo > Internet delle cose > Hub IoT.

    Indice del portale di Azure

  3. Nella finestra Hub IoT scegliere la configurazione per l'hub IoT.

    Finestra Hub IoT

    1. Nella casella Nome immettere un nome per l'hub IoT. Se il Nome è valido e disponibile, appare un segno di spunta verde nella casella Nome.

      Importante

      L'hub IoT sarà individuabile pubblicamente come endpoint DNS, quindi evitare di indicare informazioni riservate nell'assegnazione del nome.

    2. Selezionare un piano tariffario e un livello di scalabilità. Per questa esercitazione non è necessario un livello specifico. Per questa esercitazione, usare il livello F1 gratuito.

    3. In Gruppo di risorse creare un gruppo di risorse o selezionarne uno esistente. Per altre informazioni, vedere Using resource groups to manage your Azure resources (Uso di Gruppi di risorse per gestire le risorse di Azure).
    4. In Percorsoselezionare il percorso per ospitare l'hub IoT. Per questa esercitazione, scegliere la località più vicina.
  4. Dopo aver scelto le opzioni di configurazione dell'hub IoT, fare clic su Crea. La creazione dell'hub IoT da parte di Azure può richiedere alcuni minuti. Per verificare lo stato, è possibile monitorare l'avanzamento nella Schermata iniziale o nel pannello Notifiche.

  5. Dopo avere creato l'hub IoT, fare clic sul nuovo riquadro dell'hub IoT nel portale di Azure per aprire la finestra delle proprietà. Annotare il Nome host, quindi fare clic su Criteri di accesso condiviso.

    Finestra del nuovo hub IoT

  6. In Criteri di accesso condivisi fare clic sul criterio iothubowner, quindi copiare e annotare la stringa di connessione dell'hub IoT nella finestra iothubowner. Per altre informazioni, vedere Controllo di accesso nella "Guida per gli sviluppatori dell'hub IoT".

    Criteri di accesso condivisi

Creare un'identità del dispositivo

In questa sezione si usa il portale di Azure per creare un'identità del dispositivo nel registro delle identità dell'hub IoT. Un dispositivo non può connettersi all'hub IoT a meno che non abbia una voce nel registro di identità. Per altre informazioni, vedere la sezione "Registro di identità" della Guida per gli sviluppatori dell'hub IoT. Nel portale, Device Explorer consente di generare una chiave e un ID dispositivo univoci con cui il dispositivo può identificarsi quando si connette all'hub IoT. Gli ID dispositivo fanno distinzione tra maiuscole e minuscole.

  1. Assicurarsi di aver eseguito l'accesso al portale di Azure.

  2. Nell'indice fare clic su Tutte le risorse e trovare la risorsa hub IoT.

    Passare all'hub IoT

  3. Dopo aver aperto la risorsa hub IoT, fare clic sullo strumento Device Explorer e quindi su Aggiungi nella parte superiore. Specificare un nome per il nuovo dispositivo, ad esempio myDeviceId e fare clic su Salva.

    Creare l'identità del dispositivo nel portale

    In questo modo viene creata una nuova identità del dispositivo per l'hub IoT.

    Importante

    L'ID dispositivo può essere visibile nei log raccolti per il supporto tecnico e la risoluzione dei problemi, quindi evitare di indicare informazioni riservate nell'assegnazione del nome.

  4. Nell'elenco dei dispositivi in Device Explorer fare clic sul dispositivo appena creato e prendere nota della Stringa di connessione - chiave primaria.

    Stringa di connessione del dispositivo

Nota

Il registro di identità dell'hub IoT archivia solo le identità del dispositivo per abilitare l'accesso sicuro all'hub. Archivia gli ID dispositivo e le chiavi da usare come credenziali di sicurezza e un flag di attivazione/disattivazione che consente di disabilitare l'accesso per un singolo dispositivo. Se l'applicazione deve archiviare altri metadati specifici del dispositivo, dovrà usare un archivio specifico dell'applicazione. Per altre informazioni, vedere la Guida per gli sviluppatori dell'hub IoT.

Creare l'app per dispositivo simulata

In questa sezione si crea un'app console .NET che si connette all'hub come myDeviceId, attende un aggiornamento della configurazione desiderata e quindi segnala gli aggiornamenti nel processo di aggiornamento della configurazione simulata.

  1. In Visual Studio creare un nuovo progetto desktop classico di Windows Visual C# usando il modello di progetto Applicazione console. Chiamare il progetto SimulateDeviceConfiguration.

    Nuova app per il dispositivo di Windows classico in Visual C#

  2. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto SimulateDeviceConfiguration e quindi scegliere Gestisci pacchetti NuGet....

  3. Nella finestra Gestione pacchetti NuGet selezionare Sfoglia e cercare microsoft.azure.devices.client. Selezionare Installa per installare il pacchetto microsoft.azure.devices.client e accettare le condizioni d'uso. Questa procedura scarica, installa e aggiunge un riferimento al pacchetto NuGet Azure IoT SDK per dispositivi e alle relative dipendenze.

    App client della finestra Gestione pacchetti NuGet

  4. Aggiungere le istruzione using seguenti all'inizio del file Program.cs :

     using Microsoft.Azure.Devices.Client;
     using Microsoft.Azure.Devices.Shared;
     using Newtonsoft.Json;
    
  5. Aggiungere i campi seguenti alla classe Program . Sostituire il valore del segnaposto con la stringa di connessione del dispositivo annotato nella sezione precedente.

     static string DeviceConnectionString = "HostName=<yourIotHubName>.azure-devices.net;DeviceId=<yourIotDeviceName>;SharedAccessKey=<yourIotDeviceAccessKey>";
     static DeviceClient Client = null;
     static TwinCollection reportedProperties = new TwinCollection();
    
  6. Aggiungere il metodo seguente alla classe Program :

     public static void InitClient()
     {
         try
         {
             Console.WriteLine("Connecting to hub");
             Client = DeviceClient.CreateFromConnectionString(DeviceConnectionString, TransportType.Mqtt);
         }
         catch (Exception ex)
         {
             Console.WriteLine();
             Console.WriteLine("Error in sample: {0}", ex.Message);
         }
     }
    

    L'oggetto Client espone tutti i metodi necessari per interagire con i dispositivi gemelli dal dispositivo. Il codice riportato sopra inizializza l'oggetto Client e quindi recupera il dispositivo gemello per myDeviceId.

  7. Aggiungere il metodo seguente alla classe Program. Questo metodo imposta i valori iniziali di telemetria nel dispositivo locale e quindi aggiorna il dispositivo gemello.

     public static async void InitTelemetry()
     {
         try
         {
             Console.WriteLine("Report initial telemetry config:");
             TwinCollection telemetryConfig = new TwinCollection();
    
             telemetryConfig["configId"] = "0";
             telemetryConfig["sendFrequency"] = "24h";
             reportedProperties["telemetryConfig"] = telemetryConfig;
             Console.WriteLine(JsonConvert.SerializeObject(reportedProperties));
    
             await Client.UpdateReportedPropertiesAsync(reportedProperties);
         }
         catch (AggregateException ex)
         {
             foreach (Exception exception in ex.InnerExceptions)
             {
                 Console.WriteLine();
                 Console.WriteLine("Error in sample: {0}", exception);
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine();
             Console.WriteLine("Error in sample: {0}", ex.Message);
         }
     }
    
  8. Aggiungere il metodo seguente alla classe Program. Si tratta di un callback che rileva una modifica nelle proprietà desiderate del dispositivo gemello.

     private static async Task OnDesiredPropertyChanged(TwinCollection desiredProperties, object userContext)
     {
         try
         {
             Console.WriteLine("Desired property change:");
             Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
    
             var currentTelemetryConfig = reportedProperties["telemetryConfig"];
             var desiredTelemetryConfig = desiredProperties["telemetryConfig"];
    
             if ((desiredTelemetryConfig != null) && (desiredTelemetryConfig["configId"] != currentTelemetryConfig["configId"]))
             {
                 Console.WriteLine("\nInitiating config change");
                 currentTelemetryConfig["status"] = "Pending";
                 currentTelemetryConfig["pendingConfig"] = desiredTelemetryConfig;
    
                 await Client.UpdateReportedPropertiesAsync(reportedProperties);
    
                 CompleteConfigChange();
             }
         }
         catch (AggregateException ex)
         {
             foreach (Exception exception in ex.InnerExceptions)
             {
                 Console.WriteLine();
                 Console.WriteLine("Error in sample: {0}", exception);
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine();
             Console.WriteLine("Error in sample: {0}", ex.Message);
         }
     }
    

    Questo metodo aggiorna le proprietà segnalate nell'oggetto dispositivo gemello locale con la richiesta di aggiornamento della configurazione e imposta lo stato su Pending (Sospeso), quindi aggiorna il dispositivo gemello nel servizio. Dopo aver aggiornato correttamente il dispositivo gemello, quest'ultimo completerà la configurazione chiamando il metodo CompleteConfigChange descritto nel punto successivo.

  9. Aggiungere il metodo seguente alla classe Program. Questo metodo simula una reimpostazione del dispositivo, aggiorna le proprietà segnalate locali impostando lo stato su Success e rimuove l'elemento pendingConfig, quindi aggiorna il dispositivo gemello nel servizio.

     public static async void CompleteConfigChange()
     {
         try
         {
             var currentTelemetryConfig = reportedProperties["telemetryConfig"];
    
             Console.WriteLine("\nSimulating device reset");
             await Task.Delay(30000); 
    
             Console.WriteLine("\nCompleting config change");
             currentTelemetryConfig["configId"] = currentTelemetryConfig["pendingConfig"]["configId"];
             currentTelemetryConfig["sendFrequency"] = currentTelemetryConfig["pendingConfig"]["sendFrequency"];
             currentTelemetryConfig["status"] = "Success";
             currentTelemetryConfig["pendingConfig"] = null;
    
             await Client.UpdateReportedPropertiesAsync(reportedProperties);
             Console.WriteLine("Config change complete \nPress any key to exit.");
         }
         catch (AggregateException ex)
         {
             foreach (Exception exception in ex.InnerExceptions)
             {
                 Console.WriteLine();
                 Console.WriteLine("Error in sample: {0}", exception);
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine();
             Console.WriteLine("Error in sample: {0}", ex.Message);
         }
     }
    
  10. Aggiungere infine le righe seguenti al metodo Main:

     try
     {
         InitClient();
         InitTelemetry();
    
         Console.WriteLine("Wait for desired telemetry...");
         Client.SetDesiredPropertyUpdateCallback(OnDesiredPropertyChanged, null).Wait();
         Console.ReadKey();
     }
     catch (AggregateException ex)
     {
         foreach (Exception exception in ex.InnerExceptions)
         {
             Console.WriteLine();
             Console.WriteLine("Error in sample: {0}", exception);
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine();
         Console.WriteLine("Error in sample: {0}", ex.Message);
     }
    

    Nota

    Questa esercitazione non simula alcun comportamento per gli aggiornamenti della configurazione simultanei. Alcuni processi di aggiornamento della configurazione potrebbero consentire modifiche della configurazione di destinazione mentre l'aggiornamento è in esecuzione, altre potrebbero doverle accodare e altri ancora rifiutarle con una condizione di errore. È importante tenere in considerazione il comportamento desiderato per il processo di configurazione specifico e aggiungere la logica appropriata prima di iniziare la modifica della configurazione.

  11. Compilare la soluzione e quindi eseguire l'app del dispositivo da Visual Studio facendo clic su F5. Nella console di output vengono visualizzati i messaggi che indicano che il dispositivo simulato sta recuperando il dispositivo gemello e configurando la telemetria ed è in attesa della modifica della proprietà desiderata. Mantenere l'app in esecuzione.

Creare l'app di servizio

In questa sezione si creerà un'app console .NET che aggiorna le proprietà desiderate nel dispositivo gemello associato a myDeviceId con un nuovo oggetto di configurazione di telemetria. Viene quindi effettuata una query dei dispositivi gemelli archiviati nell'hub IoT e viene visualizzata la differenza tra la configurazione desiderata e quella segnalata del dispositivo.

  1. In Visual Studio aggiungere un progetto desktop di Windows classico in Visual C# usando il modello di progetto Applicazione console . Assegnare al progetto il nome SetDesiredConfigurationAndQuery.

    Nuovo progetto desktop di Windows classico in Visual C#

  2. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto SetDesiredConfigurationAndQuery e quindi fare clic su Gestisci pacchetti NuGet.
  3. Nella finestra Gestione pacchetti NuGet selezionare Esplora, cercare microsoft.azure.devices, selezionare Installa per installare il pacchetto Microsoft.Azure.Devices e accettare le condizioni per l'uso. Questa procedura scarica, installa e aggiunge un riferimento al pacchetto NuGet Azure IoT - SDK per dispositivi e alle relative dipendenze.

    Finestra Gestione pacchetti NuGet

  4. Aggiungere le istruzione using seguenti all'inizio del file Program.cs :

     using Microsoft.Azure.Devices;
     using System.Threading;
     using Newtonsoft.Json;
    
  5. Aggiungere i campi seguenti alla classe Program . Sostituire il valore del segnaposto con la stringa di connessione dell'hub IoT creato nella sezione precedente.

     static RegistryManager registryManager;
     static string connectionString = "{iot hub connection string}";
    
  6. Aggiungere il metodo seguente alla classe Program :

     static private async Task SetDesiredConfigurationAndQuery()
     {
         var twin = await registryManager.GetTwinAsync("myDeviceId");
         var patch = new {
                 properties = new {
                     desired = new {
                         telemetryConfig = new {
                             configId = Guid.NewGuid().ToString(),
                             sendFrequency = "5m"
                         }
                     }
                 }
             };
    
         await registryManager.UpdateTwinAsync(twin.DeviceId, JsonConvert.SerializeObject(patch), twin.ETag);
         Console.WriteLine("Updated desired configuration");
    
         while (true)
         {
             var query = registryManager.CreateQuery("SELECT * FROM devices WHERE deviceId = 'myDeviceId'");
             var results = await query.GetNextAsTwinAsync();
             foreach (var result in results)
             {
                 Console.WriteLine("Config report for: {0}", result.DeviceId);
                 Console.WriteLine("Desired telemetryConfig: {0}", JsonConvert.SerializeObject(result.Properties.Desired["telemetryConfig"], Formatting.Indented));
                 Console.WriteLine("Reported telemetryConfig: {0}", JsonConvert.SerializeObject(result.Properties.Reported["telemetryConfig"], Formatting.Indented));
                 Console.WriteLine();
             }
             Thread.Sleep(10000);
         }
     }
    

    L'oggetto Registry espone tutti i metodi necessari per interagire con i dispositivi gemelli dal servizio. Questo codice inizializza l'oggetto Registry, recupera il dispositivo gemello per myDeviceId e ne aggiorna le proprietà desiderate con un nuovo oggetto di configurazione dei dati di telemetria. Ogni 10 secondi esegue una query dei dispositivi gemelli archiviati nell'hub IoT e stampa le configurazioni dei dati di telemetria desiderate e segnalate. Vedere il linguaggio di query dell'hub IoT per informazioni su come generare report avanzati in tutti i dispositivi.

    Importante

    Questa applicazione effettua una query dell'hub IoT ogni 10 secondi a scopo illustrativo. Usare le query per generare i report destinati all'utente in più dispositivi e non per rilevare le modifiche. Se la soluzione richiede notifiche in tempo reale degli eventi del dispositivo, usare le notifiche relative al dispositivo gemello.

  7. Aggiungere infine le righe seguenti al metodo Main :

     registryManager = RegistryManager.CreateFromConnectionString(connectionString);
     SetDesiredConfigurationAndQuery();
     Console.WriteLine("Press any key to quit.");
     Console.ReadLine();
    
  8. In Esplora soluzioni aprire Imposta progetti di avvio e assicurarsi che Azione per il progetto SetDesiredConfigurationAndQuery sia impostata su Avvio. Compilare la soluzione.
  9. Con l'app di dispositivo SimulateDeviceConfiguration in esecuzione, eseguire l'app di servizio da Visual Studio tramite F5. Si potrà osservare la configurazione segnalata passare da Pending a Success con la nuova frequenza di invio attiva di cinque minuti e non più di 24 ore.

    Dispositivo configurato correttamente

    Importante

    Tra l'operazione relativa al report del dispositivo e il risultato della query si verifica un ritardo fino a un minuto, che consente all'infrastruttura della query di funzionare su una scala molto ampia. Per recuperare visualizzazioni coerenti di un solo dispositivo gemello, usare il metodo getDeviceTwin nella classe Registry.

Passaggi successivi

In questa esercitazione è stata impostata una configurazione desiderata come proprietà desiderate da un back-end della soluzione ed è stata scritta un'app per dispositivo per rilevare tale modifica e simulare un processo di aggiornamento in più fasi che segnala lo stato tramite le proprietà segnalate.

Per altre informazioni, vedere le risorse seguenti:

  • Per inviare dati di telemetria dai dispositivi, vedere l'esercitazione Introduzione all'hub IoT.
  • Per pianificare o eseguire operazioni su grandi set di dispositivi, vedere l'esercitazione Pianificare e trasmettere processi.
  • Per controllare i dispositivi in modo interattivo, ad esempio per attivare un ventilatore da un'app controllata dall'utente, vedere l'esercitazione Use direct methods (Usare metodi diretti).