Impariamo ad usare il WiFi del NodeMCU Parte 1 - mai più schiavi del cavo
di Vincenzo Caputo
17 Giugno 2018
Coding
In questo nuovo articolo della serie dedicata al coding impariamo ad utilizzare il WiFi integrato nel NodeMCU.
Apriremo una connessione server all'interno di una LAN interagendo con questo tramite una app per Android che vi metto gratuitamente a disposizione qui.
L'app a vostra disposizione è una sorta di terminale "moderno" sottoforma di chat che vi permetterà di interagire con il NodeMCU inviando comandi e ricevendo risposte ai comandi inviati.
Vincenzo vi spiegherà nel video il funzionamento dell'app.
Comanderemo ancora una volta un led e riceveremo una risposta sullo stato del led.
Nel corso di questa serie dedicata al coding, oltre a mostrarvi nuove features del NodeMCU, aggiungerò anche nuove funzioni all'app.
Ingredienti necessari:
Preparazione.
Prendete dell'hardware e collegatelo così:
Prendete del software, ancora una volta l'IDE di Arduino, e scrivete così:
#include <ESP8266WiFi.h>
const char *SSID = "tim-12345678";
const char *PASSWORD = "12341234";
const int PORT = 8080;
//inizializzo un nuovo oggetto server della classe WiFiServer
//passando come argomento la porta su cui si mettera' in ascolto
WiFiServer server(PORT);
const int ledPinRed = D0;
const int ledPinGreen = D1;
void startWiFi() {
Serial.print("Connecting to ");
Serial.println(SSID);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
}
void setup() {
Serial.begin(115200);
delay(25);
pinMode(ledPinRed, OUTPUT);
pinMode(ledPinGreen, OUTPUT);
//mi collego all'hotspot
startWiFi();
//avvio il server
server.begin();
Serial.println("Server started");
Serial.println(WiFi.localIP());
}
void loop() {
//inizializzo un nuovo oggetto client della classe WiFiClient
WiFiClient client = server.available(); //NON bloccante
//entra se un nuovo client si e' connesso
if(client) {
String reply = "comando non trovato";
String request = client.readStringUntil('\r'); //la richiesta da parte del client deve contenere "\r\n", timeout di defaul di 1000ms altrimenti setTimeout()
Serial.println(request);
if(request.equals("accendi led rosso")) {
digitalWrite(ledPinRed, HIGH);
reply = "led rosso acceso";
}
else if(request.equals("spegni led rosso")) {
digitalWrite(ledPinRed, LOW);
reply = "led rosso spento";
}
else if(request.equals("accendi led verde")) {
digitalWrite(ledPinGreen, HIGH);
reply = "led verde acceso";
}
else if(request.equals("spegni led verde")) {
digitalWrite(ledPinGreen, LOW);
reply = "led verde spento";
}
client.println(reply);
client.stop();
}
else {
delay(500);
}
}
Carichiamo lo sketch.
Descrizione dello sketch:
La prima riga di codice dice al compilatore che utilizzeremo la libreria ESP8266WiFi includendo il file header ESP8266WiFi.h
Le stringhe SSID e PASSWORD sono ovviamente il nome e la password della rete a cui il NodeMCU si collegherà.
La variabile PORT di tipo intero è la porta su cui il server si metterà in ascolto in attesa che i client si colleghino.
WiFiServer è una classe inclusa nella libreria ESP8266WiFi che ci permetterà di utilizzare il NodeMCU come server. Istanziamo uno oggetto server della classe WiFiServer passando al costruttore la porta su cui il server si metterà in ascolto in attesa che un nuovo client si colleghi.
Avviamo lo sketch e come al solito sarà chiamata la funzione setup().
Nella funzione setup() troviamo la funzione startWiFi() scritta da noi.
Nella funzione startWiFi() troviamo la funzione statica begin() della classe WiFi che ci permetterà di connetterci alla rete. Il prototipo della funzione begin() è:
wl_status_t WiFi::begin(const char* ssid, const char* password);
wl_status_t è un tipo di dato definito tramite enum che può assumere i seguenti valori:
typedef enum { WL_NO_SHIELD = 255, WL_IDLE_STATUS = 0, WL_NO_SSID_AVAIL, WL_SCAN_COMPLETED, WL_CONNECTED, WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED} wl_status_t;
Subito dopo troviamo un ciclo while che itera finchè lo stato della connessione non diventi WL_CONNECTED cioè finche la funzione statica status() della classe WiFi non restituisca WL_CONNECTED. Il prototipo di questa funzione è:
wl_status_t WiFi::status();
Dopo che la connessione alla rete del NodeMCU sarà effettuata possiamo avviare il server chiamando la funzione begin della classe WiFiServer tramite l'oggetto server.
Terminata la funzione setup() il NodeMCU invocherà la funzione loop().
Nella funzione loop() troviamo per prima cosa l'oggetto client della classe WiFiClient. Questo oggetto sarà inizializzato con il primo client in ordine di tempo che si collega al server tramite la funzione available() dell'oggetto server.
WiFiClient WiFiServer::available();
La funzione available() è di tipo NON bloccante cioè nel momento in cui viene invocata, se non ci sono client in attesa, allora la funzione ritorna NULL.
La funzione readStringUntil() della classe WiFiClient ci permetterà di leggere una sequenza di caratteri dallo stream fino al teminatore di stringa, che siamo liberi di scegliere, e di inserirla in un oggetto della classe String. Il prototipo della funzione readStringUntil() è:
String WiFiClient::readStringUntil(const char terminatore);
Per terminare la connessione con il client utilizzeremo la funzione stop() della classe WiFiClient.
Risultato:
Carichiamo lo sketch e attendiamo che il NodeMCU si colleghi alla rete.
Avviamo l'app e diamo il permesso di leggere e scrivere file (si tratta della cache dei messaggi).
Nella Toolbar, in alto a destra, troviamo il bottone a forma di +. Premiamo il bottone per aggiungere un nuovo dispositivo fornendo un nome al dispositivo a vostra scelta, l'indirizzo ip e la porta.
L'indirizzo ip del NodeMCU lo trovate aprendo il Monitor Seriale nel momento in cui parte lo sketch. Infatti la riga Serial.println(WiFi.localIP()) nella funzione setup() assolve a questo compito. Notate bene che se aprite il Monitor Seriale durante il caricamento dello sketch allora il caricamento potrebbe non andare a buon fine quindi per ovviare potete eseguire prima il caricamento e al termine di questo avviare il Monitor Seriale infine premere il tasto di reset del NodeMCU.
La porta è il valore inserito nella variabile intera PORT che nel nostro caso è 8080 ma voi siete liberi di cambiarla a patto che siano uguali sia sull'app sia nello sketch.
Premendo sul bottone "Salva ed Esci" vi comparirà in lista il vostro dispositivo. Se vi siete accorti di aver fatto un errore potete premere a lungo sul dispositivo appena inserito per eliminarlo altrimenti premendo una sola volta entrate nella pagina della chat con il vostro dispositivo.
Nella pagina della chat potete inviare i comandi al vostro dispositivo.
Le stringhe "accendi led rosso", "spegni led rosso", etc..., presenti nella funzione loop() dello sketch, sono i comandi che voi potete fornire al NodeMCU tramite l'app mentre le stringhe "led rosso acceso", "led rosso spento", etc..., sono le risposte che il NodeMCU vi fornirà ai vostri comandi.
Potete divertirvi utilizzando questi comandi o creandone di vostri personalizzando la sequenza di istruzioni all'interno degli if().
Se tutto questo non avviene scrivetemi nei commenti e cercherò di aiutarvi il prima possibile.
Ho scritto l'app in pochissimo tempo quindi se avete problemi anche sull'app scrivetemi nei commenti. Ho intenzione di proseguire parallelamente nello sviluppo dell'app, aggiungendo sempre nuove funzionalità, e nella scrittura di nuovi tutorial in modo tale da fornirvi sempre qualcosa che sia gia pronto all'uso e su cui potete sperimentare.
Nota Bene:
Questo è solo un esempio in quanto non è stata utilizzata alcuna cifratura dei messaggi (quindi all'interno della vostra LAN chiunque potrebbe leggere i messaggi scambiati tra l'app e il NodeMCU) e non è stato validato l'input cioe non è stato controllato ne il case (upper e lower dei caratteri, ricodatevi che il C++ è case-sensitive) ne eventualmente i caratteri riservati (es. & #).
Nel prossimo tutorial...
Useremo ancora il WiFi NodeMCU per inviare comandi ad una elettrovalvola con un occhio di riguardo alla sicurezza.
Se avete suggerimenti su nuovi tutorial attinenti il NodeMCU non esitate a scrivere nei commenti.
Produrre e aggiornare contenuti su vincenzocaputo.com richiede molto tempo e lavoro. Se il contenuto che hai appena letto è di tuo gradimento e vuoi supportarmi, clicca uno dei link qui sotto per fare una donazione.