Servizi AWS IoT core e MQTT: connettere i dispositivi Arduino SAMD (WiFiNINA) – 5

Spread the love

Questo articolo continuerà l’integrazione tramite AWS IoT con un altro tipo di dispositivo, la favolosa famiglia Arduino SAMD, che è molto potente e ben costruita.

Amazon AWS IoT Core MQTT connect Arduino SAMD devices
Amazon AWS IoT Core MQTT connects Arduino SAMD devices.

Come per l’esp8266 ed esp32, bisogna creare un nuovo oggetto con il relativo certificato (oppure riutilizzare l’oggetto esp8266 ma va fermato l’altro dispositivo).

Genera CSR per Arduino MRK WiFi 1010

Come accennato in precedenza, l’AWS IoT Core richiede che i dispositivi che si connettono utilizzando il protocollo MQTT utilizzino i certificati X.509 per l’autenticazione. Utilizzeremo uno sketch per generare una richiesta di firma del certificato (CSR) sulla scheda e quindi caricare questo CSR nella console AWS per creare un certificato X.509.

Il CSR può essere generato utilizzando uno sketch di esempio dalla libreria Arduino ECCX08.

  1. Apri lo Sketch di esempio nell’IDE di Arduino  
    File -> Examples -> ArduinoECCX08 -> Tools -> ECCX08CSR.
  2. Fai clic sul pulsante “Carica” ​​per creare e caricare lo sketch sulla tua bacheca;
  3. Apri il monitor seriale. Assicurati che la configurazione di fine riga sia impostata su “Entrambi NL e CR”.

Questo sketch ti chiederà di configurare in modo permanente il tuo elemento crittografico da ATECC508A a ECC608A se non è configurato e bloccato. NOTA: questo processo di blocco è permanente e irreversibile, ma è necessario per utilizzare l’elemento crittografico: la configurazione impostata nello sketch consente di utilizzare cinque slot di chiavi private con qualsiasi provider cloud  (o  server) e un CSR può essere rigenerato in qualsiasi momento per ciascuno dei gli altri quattro slot. Quando la scheda viene spedita dalla fabbrica, l’elemento crittografico non è configurato e sbloccato .

  1. Successivamente, ti verranno richieste le informazioni da includere nella CSR, la maggior parte delle voci può essere lasciata vuota e ad eccezione del “Common Name”, nello screenshot sotto “arduinoSAMD_relay” utilizzeremo lo slot 0 per generare e archiviare la chiave privata utilizzato per firmare la CSR (gli slot da 1 a 4 possono essere utilizzati per generare e archiviare chiavi private aggiuntive, se necessario). Nota:  poiché la chiave privata viene generata all’interno dell’elemento crittografico, non lascia mai il dispositivo, viene archiviata in modo sicuro e non può essere letta.
Arduino SAMD MKR 1010 generate Certificate Signing Request
Arduino SAMD MKR 1010 generates Certificate Signing Request.
  1. Copiare il testo CSR generato includendo “—–BEGIN CERTIFICATE REQUEST—–” e “—–END CERTIFICATE REQUEST—–” e salvalo in un file ArduinoSAMD_CSR.txt all’interno della cartella.

Ora che abbiamo una CSR per identificare la scheda, dobbiamo accedere alla console AWS e creare un certificato per essa.

Crea nuovi oggetti

Nel progetto che avevi già scaricato, verifica che la cartella arduinoSAMD_relay_iot_core/certificates esista, in caso contrario creala.

  1. Nella console AWS IoT (IoT Core), scegli dal menù di sinistra Gestione Oggetti.
    Oppure direttamente:
    https://us-east-1.console.aws.amazon.com/iot/home?region=us-east-1#/thinghub (Nord America)
    https://eu-west-1.console .aws.amazon.com/iot/home?region=eu-west-1#/thinghub (Europa)
  2. Quindi fai clic sul pulsante Crea in alto a destra, quindi Aggiungi il tuo dispositivo al registro degli oggetti.
  3. Assegna un nome al nuovo oggetto  arduinoSAMD_relay e copialo anche nel file setup.txt nella sezione [Device name]. Lascia i campi rimanenti impostati sui valori predefiniti. Scegli Avanti.
  4.  Scegli  Crea con CSR e seleziona ArduinoSAMD_CSR.txt.
Amazon AWS IoT Core MQTT upload del CSR per la creazione del certificato
Amazon AWS IoT Core MQTT upload del CSR per la creazione del certificato
  1. Scegli Carica file.
  2. Quindi fare clic su Allega una policy.
  3. Seleziona la policy già creata, se non la crei clicca per ora su Fatto e controlla l’articolo 2 “Servizi AWS IoT core e MQTT: creazione di oggetti AWS con certificato e policy” dove spiego che creazione della policy.
  4. Quindi fare clic su Registra oggetto.
  5. Ora torna a Gestione -> Oggetti.
  6. Seleziona arduinoSAMD_relay .
  7. Ora a sinistra puoi selezionare Sicurezza.
  8. Fare clic sul certificato nella casella.
Amazon AWS IoT Core MQTT download del certificato creato dal CSR Arduino MKR
Amazon AWS IoT Core MQTT download del certificato creato dal CSR Arduino MKR
  1. Quindi nel menu Azioni in alto a destra, fai clic su Download .
  2. Metti il ​​file XXXXXXXXXX-certificate.pem.crt nella cartella arduinoSAMD_relay_iot_core/certificates.
Amazon AWS IoT Core MQTT download del certificato dalla pagina principale
Amazon AWS IoT Core MQTT download del certificato dalla pagina principale

Puoi usare la stessa policy esp8266_relay_policy che abbiamo creato nell’ultimo articolo, ma devi cambiarla.

Modifica il criterio per aggiungere un nuovo dispositivo

  1. Per modificare la policy devi andare su AWS IoT Console;
  2. Nel menu a sinistra devi fare clic su Sicurezza e nel sottomenu selezionare Policy
    https://eu-west-1.console.aws.amazon.com/iot/home?region=eu-west-1#/policy/esp8266_relay_policy ( Europa)
    https://us-east-1.console.aws.amazon.com/iot/home?region=us-east-1#/policy/esp8266_relay_policy (Nord America);
  3. Fare clic su esp8266_relay_policy;
  4. Clicca in alto a destra nel testo della policy Modifica policy;
  5. Tutti i permessi di iscrizione all’argomento sono pronti, devi solo aggiungere queste righe
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:[Region]:[Account ID]:client/arduinoSAMD_relay"
    },

arduinoSAMD_relay è il nome dell’oggetto creato ora.

  1. E ora fai clic su Salva come nuova versione .

Configurare l’IDE

Ora è necessario il dispositivo, quindi è necessario configurare il dispositivo per creare e caricare il codice. Per fare ciò, puoi fare riferimento a questo articolo “Arduino SAMD NINA: piedinatura, specifiche e configurazione dell’Arduino IDE“.

Codice sorgente

Puoi trovare il codice sorgente nella cartella

alexa-skill-manage-relay/arduinoSAMD_relay_iot_core/sketch/aws_iot_core_arduino_SAMD

all’interno trovi quattro file

aws_certificate.h
aws_parameter.h
wifi_credential.h
aws_iot_core_arduinoSAMD.ino

Configurazione

E devi riempire con queste informazioni

  • wifi_credential.h: inserisci il tuo SSID WiFi e password .
char WIFI_SSID[] = "<YOUR-SSID>";
char WIFI_PASSWORD[] = "<YOUR-PASSWD>";
  • aws_parameter.h: hai questo file precompilato in alcune parti
    • THINGNAME è il nome dell’oggetto esp32_relay;
    • AWS_IOT_ENDPOINT: è il valore che avevi messo su [IoT MQTT EndPoint], lo trovi nella sezione Impostazioni della Console AWS IoT;
    • AWS_IOT_PUBLISH_TOPIC: è l’argomento di pubblicazione [IoT MQTT publish topic], per la nostra policy è relay/pub;
    • AWS_IOT_SUBSCRIBE_TOPIC: è l’argomento di pubblicazione [IoT MQTT subscribe topic], per la nostra policy è relay/sub;
#define THINGNAME "esp32_relay"
char AWS_IOT_ENDPOINT[] = "XXXXXXXXXXXXXX-ats.iot.eu-west-1.amazonaws.com";

#define AWS_IOT_PUBLISH_TOPIC   "relay/pub"
#define AWS_IOT_SUBSCRIBE_TOPIC "relay/sub"
  • aws_certificate.h:
    Questo file di configurazione deve essere compilato con XXXXXXXXXX-certificate.pem.crt scaricato in arduinoSAMD_relay_iot_core/certificates.
#include <avr/pgmspace.h>

// Device Certificate (XXXXXXXXXX-certificate.pem.crt)
// Fill in the boards public certificate
const char AWS_CERT_CRT[] = R"(
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
)";

Per l’altro file di configurazione, fare riferimento all’articolo “Servizi AWS, IoT core e MQTT: connettere i dispositivi esp8266“.

Sketch

Ecco lo sketch completo; come puoi vedere, devi importare tre librerie per gestire WiFi e sicurezza.

#include <WiFiNINA.h> // change to #include <WiFi101.h> for MKR1000
#include <ArduinoECCX08.h>
#include <ArduinoBearSSL.h>
  • WiFiNINA (or WiFi101 for the MKR1000)
  • ArduinoBearSSL
  • ArduinoECCX08

È necessario utilizzare ArduinoECCX08.h per gestire l’elemento crittografico interno; prestare attenzione a utilizzare lo slot corretto.

Quindi qui utilizziamo la libreria MQTT dal gestore delle librerie Arduino.

/*
 *   Amazon AWS IoT core connection from Arduino SAMD boards
 *
 *   This sketch securely connects to an AWS IoT using MQTT over WiFi.
 *   It uses a private key stored in the ATECC508A and a public
 *   certificate for SSL/TLS authetication.
 *
 *   It publishes a message every 5 seconds to arduino/pub
 *   topic and subscribes to messages on the arduino/sub
 *   topic.
 *
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org
 *
 */
#include "Arduino.h"
#include "aws_certificate.h"
#include "aws_parameter.h"
#include "wifi_credential.h"

#include <WiFiNINA.h> // change to #include <WiFi101.h> for MKR1000
#include <ArduinoECCX08.h>
#include <ArduinoBearSSL.h>

#include <MQTTClient.h>
#include <ArduinoJson.h>

// Secure connection
WiFiClient    wifiClient;            // Used for the TCP socket connection
BearSSLClient client(wifiClient); // Used for SSL/TLS connection, integrates with ECC508
// Client MQTT
MQTTClient clientMQTT = MQTTClient(256);

// Callback for every message on the topic subscribed
void messageCallback(String &topic, String &payload);
// Establish connection to MQTT
bool manageAWSConnection();
// Subscribe topic
bool manageAWSSubscription();
// Publish message to topic
bool publishMessage();

unsigned long getTime() {
  // get the current time from the WiFi module
  return WiFi.getTime();
}

void setup()
{
	Serial.begin(115200);
	while(!Serial){}
	Serial.flush();
	Serial.println();

	  if (!ECCX08.begin()) {
		Serial.println("No ECCX08 present!");
		while (1);
	  }

	  // Set a callback to get the current time
	  // used to validate the servers certificate
	  ArduinoBearSSL.onGetTime(getTime);

	  // Set the ECCX08 slot to use for the private key
	  // and the accompanying public certificate for it
	  client.setEccSlot(0, (const char*)AWS_CERT_CRT);

	// WIFI_SSID, WIFI_PASSWORD Stored on wifi_credential.h file
	WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

	Serial.print("Connecting to ");
	Serial.print(WIFI_SSID); Serial.println("");

	int i = 0;
	while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
		delay(1000);
		Serial.print(++i); Serial.print('.');
	}

	Serial.println('\n');
	Serial.println("Connection established!");
	Serial.print("IP address:\t");
	Serial.println(WiFi.localIP());         // Send the IP address of the ESP8266 to the computer

	if (manageAWSConnection()){
		manageAWSSubscription();
	}
}

unsigned long lastSendingTime = millis();
unsigned long sendMessageEveryMillis = 5000;

void loop()
{
	clientMQTT.loop();
	if (lastSendingTime+sendMessageEveryMillis<millis()){
		publishMessage();
		lastSendingTime = millis();
	}
}

bool manageAWSConnection(){
	// Connect to the MQTT broker on the AWS endpoint
	clientMQTT.begin(AWS_IOT_ENDPOINT, 8883, client);

	// Create a message handler
	clientMQTT.onMessage(messageCallback);

	Serial.print("Connecting to AWS IOT");

	while (!clientMQTT.connect(THINGNAME)) {
		Serial.print(".");
		delay(100);
	}

	if(!clientMQTT.connected()){
		Serial.println("AWS IoT Timeout!");
		return false;
	}
	return true;
}

bool manageAWSSubscription(){
	  // Subscribe to a topic
	  if (clientMQTT.subscribe(AWS_IOT_SUBSCRIBE_TOPIC)){
		  Serial.println("AWS IoT Connected!");
		  return true;
	  }else{
		  Serial.print("AWS IoT ERROR: ");
		  Serial.println(clientMQTT.lastError());
		  return false;
	  }
}

void messageCallback(String &topic, String &payload) {
	Serial.println("incoming: [" + topic + "]" );
	Serial.println("---------------------------" );

	StaticJsonDocument<200> doc;
	deserializeJson(doc, payload);
	serializeJsonPretty(doc, Serial);
	Serial.println();
	Serial.println("---------------------------" );
}

bool publishMessage()
{
	// Create simple message
	DynamicJsonDocument doc(512);

	doc["time"] = millis();
	doc["deviceName"] = "Arduino SAMD";
	doc["status"] = "OK";

	char jsonBuffer[512];
	serializeJson(doc, jsonBuffer); // print to client

	Serial.print("Message on ");
	Serial.print(AWS_IOT_PUBLISH_TOPIC);
	Serial.print(" topic... ");
	// Publish message to AWS_IOT_PUBLISH_TOPIC
	if (clientMQTT.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer)){
		Serial.println("Published!");
		return true;
	}else{
		Serial.println("Error!");
		return false;
	}
}

Puoi anche usare la libreria standard ArduinoMqttClient per ottenere lo stesso risultato.

/*
 *   Amazon AWS IoT core connection from Arduino SAMD boards
 *
 *   This sketch securely connects to an AWS IoT using MQTT over WiFi.
 *   It uses a private key stored in the ATECC508A and a public
 *   certificate for SSL/TLS authetication.
 *   With ArduinoMqttClient library.
 *
 *   It publishes a message every 5 seconds to arduino/pub
 *   topic and subscribes to messages on the arduino/sub
 *   topic.
 *
 *  by Mischianti Renzo <https://mischianti.org>
 *
 *  https://mischianti.org
 *
 */

#include "aws_certificate.h"
#include "aws_parameter.h"
#include "wifi_credential.h"

#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <ArduinoMqttClient.h>
#include <WiFiNINA.h> // change to #include <WiFi101.h> for MKR1000
#include <ArduinoJson.h>

/////// Enter your sensitive data in arduino_secrets.h

WiFiClient    wifiClient;            // Used for the TCP socket connection
BearSSLClient sslClient(wifiClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

unsigned long getTime();
void onMessageReceived(int messageSize);
void connectWiFi();
void connectMQTT();
bool publishMessage();

void setup() {
  Serial.begin(115200);
  while (!Serial);

  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, AWS_CERT_CRT);

  // Optional, set the client id used for MQTT,
  // each device that is connected to the broker
  // must have a unique client id. The MQTTClient will generate
  // a client id for you based on the millis() value if not set
  //
  mqttClient.setId(THINGNAME);

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  if (!mqttClient.connected()) {
    // MQTT client is disconnected, connect
    connectMQTT();
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

unsigned long getTime() {
  // get the current time from the WiFi module  
  return WiFi.getTime();
}

void connectWiFi() {
  Serial.print("Attempting to connect to SSID: ");
  Serial.print(WIFI_SSID);
  Serial.print(" ");

  while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the network");
  Serial.println();
}

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(AWS_IOT_ENDPOINT);
  Serial.println(" ");

  while (!mqttClient.connect(AWS_IOT_ENDPOINT, 8883)) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);
}

bool publishMessage()
{
	// Create simple message
	DynamicJsonDocument doc(512);

	doc["time"] = millis();
	doc["deviceName"] = "Arduino SAMD";
	doc["status"] = "OK";

	char jsonBuffer[512];
	size_t buffSize = serializeJson(doc, jsonBuffer); // print to client

	Serial.print("Message on ");
	Serial.print(AWS_IOT_PUBLISH_TOPIC);
	Serial.print(" topic... ");
	// Publish message to AWS_IOT_PUBLISH_TOPIC
	mqttClient.beginMessage(AWS_IOT_PUBLISH_TOPIC,(unsigned long)buffSize);
	mqttClient.print(jsonBuffer);
	if(mqttClient.endMessage() == 1){
		Serial.println("Published!");
		return true;
	}else{
		Serial.println("Error!");
		return false;
	}
}


void onMessageReceived(int messageSize) {
	Serial.println("incoming: [" + mqttClient.messageTopic() + "]" );
	Serial.println("---------------------------" );

	StaticJsonDocument<200> doc;
	deserializeJson(doc, mqttClient);
	serializeJsonPretty(doc, Serial);
	Serial.println();
	Serial.println("---------------------------" );
}

Grazie

  1. Servizi AWS IoT core e MQTT: introduzione e prerequisiti
  2. Servizi AWS IoT core e MQTT: creazione di oggetti AWS con certificato e policy
  3. Servizi AWS IoT core e MQTT: connettere i dispositivi esp8266
  4. Servizi AWS IoT core e MQTT: connettere i dispositivi esp32
  5. Servizi AWS IoT core e MQTT: connettere i dispositivi Arduino SAMD (WiFiNINA).
  6. Servizi AWS IoT core e MQTT: test da console e MQTT.fx

Spread the love

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *