Condividi tramite


Guida: Configurare i dispositivi da un servizio di back-end

Nell'ambito del ciclo di vita del dispositivo, potrebbe essere necessario configurare i dispositivi IoT dal servizio back-end. Quando si invia una configurazione desiderata ai dispositivi, si vogliono ricevere anche gli aggiornamenti di stato e conformità da tali dispositivi. Ad esempio, è possibile impostare un intervallo di temperatura operativa di destinazione per un dispositivo o raccogliere informazioni sulla versione del firmware dai dispositivi.

Per sincronizzare le informazioni sullo stato tra un dispositivo e un hub IoT, usare dispositivi gemelli. Un dispositivo gemello è un documento JSON, associato a un dispositivo specifico e archiviato dall'hub IoT nel cloud in cui è possibile eseguirne query . Un dispositivo gemello contiene le proprietà desiderate, le proprietà segnalate e i tag.

  • Una proprietà desiderata viene impostata da un'applicazione back-end e letta da un dispositivo.
  • Una proprietà segnalata viene impostata da un dispositivo e letta da un'applicazione back-end.
  • Un tag viene impostato da un'applicazione back-end e non viene mai inviato a un dispositivo. I tag vengono usati per organizzare i dispositivi.

Questa esercitazione illustra come usare le proprietà desiderate e segnalate per sincronizzare le informazioni sullo stato.

Diagramma dei dispositivi gemelli nel dispositivo e nel cloud.

In questa esercitazione vengono eseguite le attività seguenti:

  • Creare un hub IoT e aggiungere un dispositivo di test al registro delle identità.
  • Usare le proprietà desiderate per inviare informazioni sullo stato al dispositivo simulato.
  • Usare le proprietà segnalate per ricevere informazioni sullo stato dal dispositivo simulato.

Se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.

Prerequisiti

  • Questa esercitazione usa l'interfaccia della riga di comando di Azure per creare risorse cloud. Se è già disponibile un hub IoT con un dispositivo registrato, è possibile ignorare questi passaggi. Esistono due modi per eseguire i comandi dell'interfaccia della riga di comando:

  • Le due applicazioni di esempio eseguite in questa esercitazione vengono scritte usando Node.js. È necessario Node.js v10.x.x o versione successiva nel computer di sviluppo.

    • È possibile scaricare Node.js per più piattaforme da nodejs.org.

    • È possibile verificare la versione corrente di Node.js nel computer di sviluppo usando il comando seguente:

      node --version
      
  • Clonare o scaricare il progetto di esempio Node.js dagli esempi di Azure IoT per Node.js.

  • Assicurarsi che la porta 8883 sia aperta nel firewall. L'esempio di dispositivo in questa esercitazione usa il protocollo MQTT, che comunica sulla porta 8883. Questa porta può essere bloccata in alcuni ambienti di rete aziendali e didattici. Per altre informazioni e modi per risolvere questo problema, vedere Connessione all'hub IoT (MQTT).

Configurare le risorse di Azure

Per completare questa esercitazione, la sottoscrizione di Azure deve contenere un hub IoT con un dispositivo aggiunto al registro delle identità del dispositivo. La voce del registro delle identità del dispositivo consente al dispositivo simulato in esecuzione in questa esercitazione di connettersi all'hub.

Se non hai già un hub IoT configurato nel tuo abbonamento, puoi configurarne uno con il seguente script CLI. Questo script usa il nome tutorial-iot-hub con un numero casuale aggiunto per il nome dell'hub IoT. È possibile sostituire questo nome con un proprio nome univoco a livello globale durante l'esecuzione. Lo script crea il gruppo di risorse e l'hub nella regione Stati Uniti centrali, che è possibile modificare in una regione più vicina. Lo script recupera la stringa di connessione del servizio dell'hub IoT, usata nell'esempio back-end per connettersi all'hub IoT:

let "randomIdentifier=$RANDOM*$RANDOM"  
hubname="tutorial-iot-hub-$randomIdentifier"
location=centralus

# Install the IoT extension if it's not already installed:
az extension add --name azure-iot

# Create a resource group:
az group create --name tutorial-iot-hub-rg --location $location

# Create your free-tier IoT hub. You can only have one free IoT hub per subscription.
# Change the sku to S1 to create a standard-tier hub if necessary.
az iot hub create --name $hubname --location $location --resource-group tutorial-iot-hub-rg --partition-count 2 --sku F1

# Make a note of the service connection string, you need it later:
az iot hub connection-string show --hub-name $hubname --policy-name service -o table

Questa esercitazione usa un dispositivo simulato denominato MyTwinDevice. Lo script seguente aggiunge questo dispositivo al registro delle identità e recupera la stringa di connessione:

# Create the device in the identity registry:
az iot hub device-identity create --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg

# Retrieve the device connection string, you need this later:
az iot hub device-identity connection-string show --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg -o table

Inviare informazioni sullo stato a un dispositivo

Usare le proprietà desiderate per inviare informazioni sullo stato da un'applicazione back-end a un dispositivo. In questa sezione viene illustrato come:

  • Configurare un dispositivo per ricevere ed elaborare le proprietà desiderate.
  • Inviare le proprietà desiderate da un'applicazione back-end a un dispositivo.

Esempio di proprietà desiderate

È possibile strutturare le proprietà desiderate in qualsiasi modo conveniente per l'applicazione. Questo esempio usa una proprietà di primo livello denominata fanOn e raggruppa le proprietà rimanenti in componenti separati. Il frammento JSON seguente illustra la struttura delle proprietà desiderate usate in questa esercitazione. Il codice JSON si trova nel file desired.json.

{
  "fanOn": "true",
  "components": {
    "system": {
      "id": "17",
      "units": "farenheit",
      "firmwareVersion": "9.75"
    },
    "wifi" : { 
      "channel" : "6",
      "ssid": "my_network"
    },
    "climate" : {
      "minTemperature": "68",
      "maxTemperature": "76"
    }
  }
}

Ricevere le proprietà desiderate in un'applicazione del dispositivo

Per visualizzare il codice di esempio del dispositivo simulato che riceve le proprietà desiderate, passare alla cartella iot-hub/Tutorials/DeviceTwins nell'esempio Node.js progetto scaricato. Aprire quindi il file SimulatedDevice.js in un editor di testo.

Le sezioni seguenti descrivono il codice eseguito nel dispositivo simulato che risponde alle modifiche delle proprietà desiderate inviate dall'applicazione back-end.

Recuperare l'oggetto dispositivo gemello

Quando il dispositivo è stato registrato con l'hub IoT, si riceve una stringa di connessione del dispositivo come output. Una stringa di connessione del dispositivo viene usata dal dispositivo per l'autenticazione con la relativa identità registrata nel cloud. Il codice seguente si connette all'hub IoT usando una stringa di connessione del dispositivo:

// Get the device connection string from a command line argument
var connectionString = process.argv[2];

Il codice seguente ottiene un gemello dall'oggetto client:

// Get the device twin
client.getTwin(function(err, twin) {
  if (err) {
    console.error(chalk.red('Could not get device twin'));
  } else {
    console.log(chalk.green('Device twin created'));

Creare gestori

È possibile creare gestori per gli aggiornamenti delle proprietà desiderati che rispondono agli aggiornamenti a livelli diversi nella gerarchia JSON. Ad esempio, questo gestore visualizza tutte le modifiche alle proprietà desiderate inviate al dispositivo da un'applicazione back-end. La variabile delta contiene le proprietà desiderate inviate dal back-end della soluzione:

// Handle all desired property updates
twin.on('properties.desired', function(delta) {
    console.log(chalk.yellow('\nNew desired properties received in patch:'));

Il gestore seguente reagisce solo alle modifiche apportate alla proprietà desiderata fanOn :

// Handle changes to the fanOn desired property
twin.on('properties.desired.fanOn', function(fanOn) {
    console.log(chalk.green('\nSetting fan state to ' + fanOn));

    // Update the reported property after processing the desired property
    reportedPropertiesPatch.fanOn = fanOn ? fanOn : '{unknown}';
});

Gestori per più proprietà

Nel codice JSON delle proprietà desiderate di esempio per questa esercitazione, il nodo clima nei componenti contiene due proprietà, minTemperature e maxTemperature.

L'oggetto gemello locale di un dispositivo archivia un set completo di proprietà desiderate e segnalate. Il delta inviato dal back-end potrebbe aggiornare solo un subset di proprietà desiderate. Nel frammento di codice seguente, se il dispositivo simulato riceve un aggiornamento a uno solo di minTemperature e maxTemperature, usa il valore nel gemello locale per l'altro valore per configurare il dispositivo:

// Handle desired properties updates to the climate component
twin.on('properties.desired.components.climate', function(delta) {
    if (delta.minTemperature || delta.maxTemperature) {
      console.log(chalk.green('\nUpdating desired tempertures in climate component:'));
      console.log('Configuring minimum temperature: ' + twin.properties.desired.components.climate.minTemperature);
      console.log('Configuring maximum temperture: ' + twin.properties.desired.components.climate.maxTemperature);

      // Update the reported properties and send them to the hub
      reportedPropertiesPatch.minTemperature = twin.properties.desired.components.climate.minTemperature;
      reportedPropertiesPatch.maxTemperature = twin.properties.desired.components.climate.maxTemperature;
      sendReportedProperties();
    }
});

Gestire operazioni di inserimento, aggiornamento ed eliminazione

Le proprietà desiderate inviate dal back-end non indicano quale operazione viene eseguita su una determinata proprietà desiderata. Il codice deve dedurre l'operazione dal set corrente di proprietà desiderate archiviate in locale e le modifiche inviate dall'hub.

Il frammento di codice seguente mostra come il dispositivo simulato gestisce le operazioni di inserimento, aggiornamento ed eliminazione nell'elenco dei componenti nelle proprietà desiderate. È possibile vedere come usare valori Null per indicare che un componente deve essere eliminato:

// Keep track of all the components the device knows about
var componentList = {};

// Use this componentList list and compare it to the delta to infer
// if anything was added, deleted, or updated.
twin.on('properties.desired.components', function(delta) {
  if (delta === null) {
    componentList = {};
  }
  else {
    Object.keys(delta).forEach(function(key) {

      if (delta[key] === null && componentList[key]) {
        // The delta contains a null value, and the
        // device has a record of this component.
        // Must be a delete operation.
        console.log(chalk.green('\nDeleting component ' + key));
        delete componentList[key];

      } else if (delta[key]) {
        if (componentList[key]) {
          // The delta contains a component, and the
          // device has a record of it.
          // Must be an update operation.
          console.log(chalk.green('\nUpdating component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];

        } else {
          // The delta contains a component, and the
          // device has no record of it.
          // Must be an add operation.
          console.log(chalk.green('\nAdding component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];
        }
      }
    });
  }
});

Inviare le proprietà desiderate da un'applicazione back-end

Si è visto come un dispositivo implementa degli handler per ricevere gli aggiornamenti delle proprietà desiderate. Questa sezione illustra come inviare le modifiche alle proprietà desiderate a un dispositivo da un'applicazione back-end.

Per visualizzare il codice di esempio del dispositivo simulato che riceve le proprietà desiderate, passare alla cartella iot-hub/Tutorials/DeviceTwins nell'esempio Node.js progetto scaricato. Aprire quindi il file ServiceClient.js in un editor di testo.

Il frammento di codice seguente illustra come connettersi al registro delle identità del dispositivo e accedere al dispositivo gemello per un dispositivo specifico:

// Create a device identity registry object
var registry = Registry.fromConnectionString(connectionString);

// Get the device twin and send desired property update patches at intervals.
// Print the reported properties after some of the desired property updates.
registry.getTwin(deviceId, async (err, twin) => {
  if (err) {
    console.error(err.message);
  } else {
    console.log('Got device twin');

Il frammento di codice seguente mostra le diverse patch di proprietà desiderate inviate dall'applicazione back-end al dispositivo:

// Turn the fan on
var twinPatchFanOn = {
  properties: {
    desired: {
      patchId: "Switch fan on",
      fanOn: "false",
    }
  }
};

// Set the maximum temperature for the climate component
var twinPatchSetMaxTemperature = {
  properties: {
    desired: {
      patchId: "Set maximum temperature",
      components: {
        climate: {
          maxTemperature: "92"
        }
      }
    }
  }
};

// Add a new component
var twinPatchAddWifiComponent = {
  properties: {
    desired: {
      patchId: "Add WiFi component",
      components: {
        wifi: { 
          channel: "6",
          ssid: "my_network"
        }
      }
    }
  }
};

// Update the WiFi component
var twinPatchUpdateWifiComponent = {
  properties: {
    desired: {
      patchId: "Update WiFi component",
      components: {
        wifi: { 
          channel: "13",
          ssid: "my_other_network"
        }
      }
    }
  }
};

// Delete the WiFi component
var twinPatchDeleteWifiComponent = {
  properties: {
    desired: {
      patchId: "Delete WiFi component",
      components: {
        wifi: null
      }
    }
  }
};

Il frammento di codice seguente mostra come l'applicazione back-end invia un aggiornamento di proprietà desiderato a un dispositivo:

// Send a desired property update patch
async function sendDesiredProperties(twin, patch) {
  twin.update(patch, (err, twin) => {
    if (err) {
      console.error(err.message);
    } else {
      console.log(chalk.green(`\nSent ${twin.properties.desired.patchId} patch:`));
      console.log(JSON.stringify(patch, null, 2));
    }
  });
}

Ricevere informazioni sullo stato da un dispositivo

L'applicazione back-end riceve informazioni sullo stato da un dispositivo sotto forma di proprietà segnalate. Un dispositivo imposta le proprietà segnalate e le invia all'hub. Un'applicazione back-end è in grado di leggere i valori correnti delle proprietà segnalate da un dispositivo gemello archiviato nell'hub.

Invia le proprietà riportate da un dispositivo

È possibile inviare aggiornamenti ai valori delle proprietà segnalate sotto forma di patch. Il frammento di codice seguente mostra un modello per la patch inviata dal dispositivo simulato. Il dispositivo simulato aggiorna i campi nella patch prima di inviarli all'hub:

// Create a patch to send to the hub
var reportedPropertiesPatch = {
  firmwareVersion:'1.2.1',
  lastPatchReceivedId: '',
  fanOn:'',
  minTemperature:'',
  maxTemperature:''
};

Il dispositivo simulato usa la funzione seguente per inviare la patch contenente le proprietà segnalate all'hub:

// Send the reported properties patch to the hub
function sendReportedProperties() {
  twin.properties.reported.update(reportedPropertiesPatch, function(err) {
    if (err) throw err;
    console.log(chalk.blue('\nTwin state reported'));
    console.log(JSON.stringify(reportedPropertiesPatch, null, 2));
  });
}

Elaborare le proprietà segnalate

Un'applicazione back-end accede ai valori correnti delle proprietà segnalate per un dispositivo tramite il dispositivo gemello. Il frammento di codice seguente illustra come l'applicazione back-end legge i valori delle proprietà segnalate per il dispositivo simulato:

// Display the reported properties from the device
function printReportedProperties(twin) {
  console.log("Last received patch: " + twin.properties.reported.lastPatchReceivedId);
  console.log("Firmware version: " + twin.properties.reported.firmwareVersion);
  console.log("Fan status: " + twin.properties.reported.fanOn);
  console.log("Min temperature set: " + twin.properties.reported.minTemperature);
  console.log("Max temperature set: " + twin.properties.reported.maxTemperature);
}

Eseguire le applicazioni

In questa sezione vengono eseguite le due applicazioni di esempio da osservare come un'applicazione back-end invia gli aggiornamenti delle proprietà desiderati a un'applicazione del dispositivo simulato.

Per eseguire le applicazioni di dispositivo simulato e back-end, sono necessarie le stringhe di connessione del dispositivo e del servizio. Hai annotato le stringhe di connessione quando hai creato le risorse all'inizio di questa esercitazione.

Per eseguire l'applicazione del dispositivo simulato, aprire una shell o una finestra del prompt dei comandi e passare alla cartella iot-hub/Tutorials/DeviceTwins nel progetto Node.js scaricato. Eseguire quindi i comandi seguenti:

npm install
node SimulatedDevice.js "{your device connection string}"

Per eseguire l'applicazione back-end, aprire un'altra shell o un'altra finestra del prompt dei comandi. Passare quindi alla cartella iot-hub/Tutorials/DeviceTwins nel progetto Node.js scaricato. Eseguire quindi i comandi seguenti:

npm install
node ServiceClient.js "{your service connection string}"

Osservare gli aggiornamenti delle proprietà desiderate

Lo screenshot seguente mostra l'output dell'applicazione del dispositivo simulato ed evidenzia come gestisce un aggiornamento alla proprietà desiderata maxTemperature . È possibile vedere in che modo vengono eseguiti i gestori del componente relativo alle condizioni climatiche e del gestore di livello superiore:

Screenshot che mostra come vengono eseguiti i gestori del componente relativo alle condizioni climatiche e il gestore di livello superiore.

Lo screenshot seguente mostra l'output dell'applicazione back-end ed evidenzia come invia un aggiornamento alla proprietà desiderata maxTemperature :

Screenshot che mostra l'output dell'applicazione back-end e dimostra come essa invii un aggiornamento.

Osservare gli aggiornamenti delle proprietà segnalate

La schermata seguente mostra l'output dell'applicazione del dispositivo simulato ed evidenzia come viene inviato all'hub un aggiornamento delle proprietà segnalate:

Screenshot che mostra il dispositivo simulato che aggiorna lo stato del suo dispositivo gemello.

Lo screenshot seguente mostra l'output dell'applicazione back-end ed evidenzia come riceve ed elabora un aggiornamento delle proprietà segnalato da un dispositivo:

Screenshot che mostra l'applicazione back-end che riceve le proprietà segnalate del dispositivo.

Pulire le risorse

Se si prevede di completare l'esercitazione successiva, lasciare il gruppo di risorse e l'hub IoT per riutilizzarli in un secondo momento.

Se non è più necessario l'hub IoT, eliminarlo e il gruppo di risorse nel portale. A tale scopo, selezionare il gruppo di risorse tutorial-iot-hub-rg che contiene l'hub IoT e selezionare Elimina.

In alternativa, usare il CLI:

# Delete your resource group and its contents
az group delete --name tutorial-iot-hub-rg

Passaggi successivi

In questa esercitazione si è appreso come sincronizzare le informazioni sullo stato tra i dispositivi e l'hub IoT. Passare all'esercitazione successiva per apprendere come usare i dispositivi gemelli per implementare un processo di aggiornamento de dispositivo.