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.
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.
- Apri lo Sketch di esempio nell’IDE di Arduino
File -> Examples -> ArduinoECCX08 -> Tools -> ECCX08CSR
. - Fai clic sul pulsante “Carica” per creare e caricare lo sketch sulla tua bacheca;
- 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 .
- 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.
- 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.
- Nella console AWS IoT (IoT Core), scegli dal menù di sinistra Gestione e 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) - Quindi fai clic sul pulsante Crea in alto a destra, quindi Aggiungi il tuo dispositivo al registro degli oggetti.
- 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. - Scegli Crea con CSR e seleziona
ArduinoSAMD_CSR.txt
.
- Scegli Carica file.
- Quindi fare clic su Allega una policy.
- 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.
- Quindi fare clic su Registra oggetto.
- Ora torna a
Gestione -> Oggetti
. - Seleziona arduinoSAMD_relay .
- Ora a sinistra puoi selezionare Sicurezza.
- Fare clic sul certificato nella casella.
- Quindi nel menu Azioni in alto a destra, fai clic su Download .
- Metti il file XXXXXXXXXX-certificate.pem.crt nella cartella arduinoSAMD_relay_iot_core/certificates.
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
- Per modificare la policy devi andare su AWS IoT Console;
- 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); - Fare clic su
esp8266_relay_policy
; - Clicca in alto a destra nel testo della policy Modifica policy;
- 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.
- 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 partiTHINGNAME
è il nome dell’oggettoesp32_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
- Servizi AWS IoT core e MQTT: introduzione e prerequisiti
- Servizi AWS IoT core e MQTT: creazione di oggetti AWS con certificato e policy
- Servizi AWS IoT core e MQTT: connettere i dispositivi esp8266
- Servizi AWS IoT core e MQTT: connettere i dispositivi esp32
- Servizi AWS IoT core e MQTT: connettere i dispositivi Arduino SAMD (WiFiNINA).
- Servizi AWS IoT core e MQTT: test da console e MQTT.fx