Accendere e spegnere LED mediante i dispositivi ombra di AWS IoT

Le applicazioni necessitano di una rete stabile per comunicare in tempo reale con i dispositivi IoT. In caso contrario, i dispositivi possono disconnettersi o essere sopraffatti dalle richieste provenienti da più applicazioni. Ciò può portare a problemi di sincronizzazione e stato che possono compromettere la raccolta e l'utilizzo dei dati. Il servizio Device Shadow di AWS IoT è progettato per affrontare queste sfide di connettività fungendo da tramite tra applicazioni e dispositivi IoT. In questo articolo utilizzeremo la piattaforma AWS IoT per controllare il LED integrato di una scheda basata su ESP32, grazie al servizio Device Shadow. Questo semplice esempio funge da trampolino di lancio per poter integrare qualsiasi dispositivo IoT per mezzo della piattaforma AWS, imparando così a creare soluzioni IoT automatizzate.

Introduzione

Per ogni dispositivo connesso alla piattaforma AWS IoT viene creato un dispositivo ombra. Il dispositivo ombra consente di ottenere informazioni sullo stato corrente del dispositivo fisico e, in base a tale stato, è possibile agire sul dispositivo fisico. Inoltre, il dispositivo fisico può essere monitorato e controllato in ​​base alle proprie esigenze tramite protocolli MQTT o HTTP, indipendentemente dal fatto che il dispositivo fisico sia connesso o meno a Internet. Il dispositivo ombra di ogni dispositivo fisico è identificato in modo univoco dal nome dell'oggetto corrispondente (oggetto è il termine che si usa sulla piattaforma AWS per identificare un dispositivo). Un dispositivo ombra è un documento Json utilizzato per archiviare e recuperare informazioni sullo stato corrente di un dispositivo. Un esempio di documento Json che rappresenta un dispositivo ombra è riportato in Figura 1.

Figura 1: Un dispositivo ombra è un file in formato Json dove vengono memorizzati lo "stato desiderato" e lo "stato riportato" del dispositivo fisico associato

Per poter implementare l'applicazione che andremo a descrivere nell'articolo, sono necessari:

  • L'IDE Arduino
  • Una scheda basata sull'ESP32. Nel nostro caso abbiamo utilizzato la ESP32-CAM di AI-Thinker
  • Un account di livello gratuito AWS (i servizi che utilizzeremo non supereranno il limite del livello gratuito)

Configurazione dell'IDE Arduino

Per prima cosa andiamo a configurare l'IDE Arduino installato sul nostro sistema locale:

  1. Dopo aver lanciato il software andiamo su "File" nella barra dei comandi e selezioniamo "Impostazioni".
  2. Quindi, inseriamo https://dl.espressif.com/dl/package_esp32_index.json nel campo "URL aggiuntive per il Gestore Schede".
  3. Ora selezioniamo "Gestione librerie" andando su "Strumenti" -> "Gestione librerie".
  4. Nella barra di ricerca scriviamo ESP32 e premiamo il pulsante di installazione per "ESP32 by Espressif System".

Installazione Hornbill Library per connettere ESP32 con AWS

Installiamo la libreria Hornbill AWS che permette una più facile integrazione tra il microcontrollore ESP32 con la piattaforma AWS, in modo sicuro. Fare clic QUI per scaricare la libreria AWS_IOT Hornbill. Aprire quindi il file scaricato, denominato Hornbill-Examples-master.zip, e dalla directory Hornbill-Examples-master\arduino-esp32, copiare AWS_IOT e incollarlo in C:\Users\{Your User Name}\Documents\Arduino\libraries.

Creazione Oggetto e policy

Se non si possiede un account AWS, bisognerà crearne uno. Durante la fase di creazione, vi verrà chiesto di inserire una carta di credito. Non c'è da preoccuparsi, poiché le operazioni che andremo a descrivere nell'articolo non eccederanno i limiti imposti dagli account gratuiti. Una volta registrati ed entrati nel proprio account possiamo passare alla creazione dell'oggetto, dei certificati e delle policy. Nella barra di ricerca in alto andiamo a scrivere "IoT core" e facciamo clic sul primo risultato. Nella nuova pagina che si aprirà ci sarà una barra laterale con diverse opzioni. Andiamo a fare clic su "Gestione" e quindi su "Oggetti". A questo punto nella nuova pagina andiamo a premere il tasto arancione "Crea oggetti". Gli oggetti sono la rappresentazione dei nostri dispositivi fisici, sulla piattaforma AWS IoT. Possiamo quindi premere "Successivo" per creare un singolo oggetto. Inseriamo il nome dell'oggetto nell'apposito spazio, ad esempio ESP32, e facciamo clic su "Successivo".

Nella pagina che si aprirà, denominata Configura il certificato dei dispositivi, andiamo a fare clic su "Successivo". A questo punto dobbiamo collegare una policy al nostro oggetto. Una policy definisce che cosa è permesso fare al nostro dispositivo quando si collega alla piattaforma. Premiamo su "Crea policy". Inseriamo nella nuova pagina il nome della policy, ad esempio ESP32Policy. Nella parte in basso denominata Documento della policy, andiamo a selezionare IoT:Connect nel menu a tendina sotto "Operazione della policy", mentre in "Risorsa della policy" inseriamo semplicemente un asterisco(*). Quindi facciamo clic su "Aggiungi nuova istruzione". Ripetiamo gli stessi passi finché non  avremo inserito altre tre "Operazioni della policy" che sono: iot:Subscribe, iot:Receive e iot:Publish. Una volta fatto, possiamo fare clic sul tasto "Crea". In sostanza, stiamo dando i permessi al nostro dispositivo (oggetto) di connettersi alla piattaforma AWS, pubblicare e sottoscriversi ai topic MQTT e di ricevere messaggi. A questo punto torniamo nella pagina di collegamento della policy all'oggetto. Spuntiamo la policy appena creata e premiamo su "Crea oggetto". Apparirà una finestra da cui dovremo scaricare i certificati. I certificati da scaricare sono: il certificato del dispositivo, i file della chiave pubblica e privata, e la certificazione root Amazon 1. La Figura 2 evidenzia i certificati da scaricare.

Figura 2: In rosso sono evidenziati i file da scaricare

Una volta scaricati, basterà fare clic su "Fatto" presente alla fine della finestra.

Registrazione dei certificati

Registreremo i certificati e la chiave privata nella libreria AWS_IOT. Andando nella directory:

C:\Users\Your User Name\Documents\Arduino\libraries\AWS_IOT\src

apriamo il file aws_iot_certficates.c in un editor (consigliato Notepad++). Qui andremo ad allegare il Certificato dell'Oggetto, la Chiave Privata e il Certificato CA che abbiamo scaricato nella sezione precedente. I certificati e la chiave privata vanno inseriti al posto delle x. Quindi:

  • in aws_root_ca_pem[] imposteremo il Certificato CA
  • in private_pem_key[] imposteremo la Chiave Privata e
  • in certificate_pem_crt[] imposteremo il Certificato dell'Oggetto

Fate attenzione ad inserire alla fine di ogni riga dei certificati i caratteri \n\.

Il codice

Occorre copiare il codice Arduino sottostante in un nuovo file nell'IDE Arduino, e fare poi alcune piccole modifiche.

/*********
  Gourav Das
  Complete project details at https://hackernoon.com/cloud-home-automation-series-part-2-use-aws-device-shadow-to-control-esp32-with-arduino-code-tq9a37aj
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/
#include <AWS_IOT.h>
#include <WiFi.h>
#include <ArduinoJson.h> //Download latest ArduinoJson 6 Version library only by Benoît Blanchon from Manage Libraries

AWS_IOT shadow;
#define ledPin 33 // LED Pin

char WIFI_SSID[]="Wifi-Name";
char WIFI_PASSWORD[]="Wifi_Password";
char HOST_ADDRESS[]="************-***.iot.us-east-1.amazonaws.com";  //AWS IoT Custom Endpoint Address
char CLIENT_ID[]= "ESP32";
char SHADOW_GET[]= "$aws/things/{Thingname}/shadow/get/accepted";
char SENT_GET[]= "$aws/things/{ThingName}/shadow/get";
char SHADOW_UPDATE[]= "$aws/things/{ThingName}/shadow/update";

int status = WL_IDLE_STATUS;
int msgReceived=0;
char payload[512];
char reportpayload[512];
char rcvdPayload[512];

void mySubCallBackHandler (char *topicName, int payloadLen, char *payLoad)
{
    strncpy(rcvdPayload,payLoad,payloadLen);
    rcvdPayload[payloadLen] = 0;
    msgReceived = 1;
}

void updateShadow (int power)
{ 
  sprintf(reportpayload,"{\"state\": {\"reported\": {\"power\": \"%d\"}}}",power);
  delay(3000);   
    if(shadow.publish(SHADOW_UPDATE,reportpayload) == 0)
      {       
        Serial.print("Publish Message:");
        Serial.println(reportpayload);
      }
    else
      {
        Serial.println("Publish failed");
        Serial.println(reportpayload);   
      }  
} 

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  delay(2000);  

    while (status != WL_CONNECTED)
    {
        Serial.print("Attempting to connect to SSID: ");
        Serial.println(WIFI_SSID);
        status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // Connect to WPA/WPA2 network. Change this line if using open or WEP network:        
        delay(5000);// wait 5 seconds for connection:
    }

    Serial.println("Connected to wifi");

    if(shadow.connect(HOST_ADDRESS,CLIENT_ID)== 0) //Connect to AWS IoT COre
    {
        Serial.println("Connected to AWS");
        delay(1000);

        if(0==shadow.subscribe(SHADOW_GET,mySubCallBackHandler)) //Subscribe to Accepted GET Shadow Service
        {
            Serial.println("Subscribe Successfull");
        }
        else
        {
            Serial.println("Subscribe Failed, Check the Thing Name and Certificates");
            while(1);
        }
    }
    else
    {
        Serial.println("AWS connection failed, Check the HOST Address");
        while(1);
    }
  
  
  delay(3000); /*Sent Empty string to fetch Shadow desired state*/ 
    if(shadow.publish(SENT_GET,"{}") == 0)
      {       
        Serial.print("Empty String Published\n");
      }
    else
      {
        Serial.println("Empty String Publish failed\n");
      }  /*Sent Empty string to fetch Shadow desired state*/   
}    

void loop() {
  
 if(msgReceived == 1)
    
  {
        msgReceived = 0;
        Serial.print("Received Message:");
        Serial.println(rcvdPayload);
        StaticJsonDocument<256> doc;
        deserializeJson(doc, rcvdPayload);
        
    
        if (doc.isNull()) { /* Test if parsing succeeds. */
        Serial.println("parseObject() failed");
        return;
        } /* Test if parsing succeeds. */
    
        int power = doc["state"]["desired"]["power"];
        Serial.println(power);
        if(power == 1)
        digitalWrite(ledPin, HIGH);
        else if(power == 0)
        digitalWrite(ledPin, LOW);
    updateShadow(power);  
    }  
}

Dobbiamo aggiungere una libreria nell'IDE di Arduino, andando su "Strumenti" → "Gestione librerie". Cercare ArduinoJson (di Benoit Blanchon), selezionando solo l'ultima versione e facendo clic su installa. Il codice non funzionerà con versioni 5 o precedenti.

[...]

ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 2578 parole ed è riservato agli ABBONATI. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici che potrai leggere in formato PDF per un anno. ABBONATI ORA, è semplice e sicuro.

Scarica subito una copia gratis

2 Commenti

  1. Matteo.L 9 Settembre 2022

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend