Arbeiten mit dem Cayenne Dashboard - Gateway als Access-Point und Netzwerk-Client(Teil 5) - AZ-Delivery

In Parte 3 se abbiamo costruito una porta che lavora come un cliente su una rete WLAN. Dunque, doveva esser posato inevitabilmente i dati di accesso adatti in costanti nella memoria di programma. Perché vogliamo utilizzare la porta anche per ESP Adesso, sarebbe pratico se la porta anche come un punto di Accesso poteva lavorare.

Adesso dell'ESP32 questo è capace. Se noi WiFi moda su WIFI_AP_STA stzen lavori dell'ESP come un punto di Accesso così come come una stazione. Infatti, solo un canale può esser usato. La connessione sulla rete d'instradatore ha la priorità con la scelta di canale. Questo è il punto di Accesso sempre usa lo stesso canale come la connessione sulla rete d'instradatore.

Adesso vogliamo usare questa moda doppia per esso per configurare la nostra porta su un navigatore. I dati di accesso necessari come SSID e parola d'ordine, comunque, anche i dati di accesso a Caienna semplicemente su spago vuoto. Se la porta è assente cominciato quindi non può aumentare connessione sulla rete d'instradatore, là i dati di accesso. Dopo che il tentativo connettente è entrato in Time out, il punto di Accesso con lo SSID MQTTGateway è cominciato. L'indirizzo IP della porta è in questa rete sempre 192.168.4.1

Per configurare adesso la porta annunciamo un computer o uno smartphone in questa rete (nessuna parola d'ordine) e cominciamo un navigatore con l'indirizzo http://192.168.4.1 Noi allora deve vedere la parte di configurazione seguente.

Se i dati di accesso sono immagazzinati, la porta prova a produrre una connessione con la rete d'instradatore. Se il tentativo connettente è di successo, l'esposizione mostra all'indirizzo IP in con che la porta nella rete d'instradatore può esser raggiunta.

Dopo che una connessione con la rete d'instradatore esiste uno riceve nel navigatore sempre la lista dei dispositivi iscritti. Sul path/conf uno può accedere alla parte di configurazione e cambiare i dati di accesso.

Sketch:

 

/* La porta MQTT forma un'interfaccia tra LoRa a dispositivi o dispositivi SPECIALMENTE Nowe 
 * e Caienna Cruscotti di MQTT. Dirige su ESP32 con LoRa ed esposizione OLED
 * La configurazione succede dal navigatore
 */
#include <SPI.H>
#include <LoRa.H>
#include «SSD1306.h»
#include<Arduino.H>
#include <CayenneMQTTESP32.H>
#include <CayenneLPP.H>
#include <WiFi.H>
#include <Server Web.H>
#include <tempo.H>
#include «FS.h»
#include «SPIFFS.h»


//Server NTP alla sincronizzazione di tempo
#define NTP_SERVER «de.pool.ntp.org»
#define GMT_OFFSET_SEC 3600
#define DAYLIGHT_OFFSET_SEC 0

//Spilli per il chip di LoRa
#define SS      18
#define RST     14
#define DI0     26
//Frequenza per il chip di LoRa
#define NASTRO    433175000

//
#define MAXCHANNELS 256 //numero massimo dei canali amministrati
#define MAXDEVICE 32 //il numero massimo dei dispositivi amministrati MAXCHANNELS/MAXDEVICE = 8 dimostra il numero massimo di canali per dispositivo

//Il sistema di File di Lampo di formato se non avvengono già
#define FORMAT_SPIFFS_IF_FAILED vero

#define MESSA A PUNTO 1

//Pietre per il server Web
può PROGMEM lavoro a giornata HTML_HEADER[] =
«<!DOCTYPE HTML>»;
«<html>»;
«<head>»;
«<meta chiamano = \«viewport \» i contenuti = \«la larghezza = la larghezza del dispositivo, la scala iniziale = 1.0, la scala massima = 1.0, user-scalable=0> \«>»;
«<meta http-equiv = \«tipo contento \» contenuti = \«testo / html; charset=UTF-8 \«>»;
«<title>MQTT Gateway</title>»;
«<style>»;
«corpo {colore di sfondo: #d2f3eb; famiglia della serie completa di caratteri: Arial, Helvetica, Sans-grazia; Colore: #000000;font-size:12pt;}»
«Th {colore di sfondo: #b6c0db; colore: #050ed2;font-weight:lighter;font-size:10pt;}»
«tavolo, th, td {confine: 1px px nero affidabile;}»
«.titel {font-size:18pt;font-weight:bold;text-align:center;}»
«</style>»;;

può PROGMEM lavoro a giornata HTML_HEADER_END[] = 
«</head>»;
«<body><div disegna = 'il margine-left:30px; '>»;;

può PROGMEM lavoro a giornata HTML_SCRIPT[] =
«<script lingua = \«javascript \«>»;
«la funzione ricarica () {»
«document.location = \«http://%s \»;}»
«</script>»;;

può PROGMEM lavoro a giornata HTML_END_RELOAD[] =
«</div><script la lingua = \«javascript \«>setTimeout (ricaricano, 10000) ;</script></body>»;
«</html>»;;
può PROGMEM lavoro a giornata HTML_END[] =
«</body></html>»;;
può PROGMEM lavoro a giornata HTML_TAB_GERAETE[] =
«<table disegna = \«width:100 il % \«><tr><th gli stili = \«width:20 il % \«>ID</th><th gli stili = \«width:10 il % \«>Nr.</th>»;
«<th disegna = \«width:20 il % \«>Kanäle</th><th gli stili = \«width:20 il % \«>Name</th>»;
«<th disegna = \«width:20 il % \«>Letzte Daten</th><th gli stili = \«width:10 il % \«>Aktion</th></tr>»;;
può PROGMEM lavoro a giornata HTML_TAB_END[] =
«</table>»;;
può PROGMEM lavoro a giornata HTML_NEWDEVICE[] =
«<div disegna = \«il margine-top:20px; \«>%s nome: <input battono a macchina = \«il testo \»» il nome = \«devname \» maxlength = \«gli stili = \«width:200px \10 \» il valore = \» \» > <button il nome = \«il registro \» il valore = \» il % vede \«>Registrieren</button></div>»;;
può PROGMEM lavoro a giornata HTML_TAB_ZEILE[] =
«<tr><td>%s</td><td>%i</td><td>%i a %i</td><td>%s</td><td>%s</td><td><button il nome = \«cancellano \» il valore = \» il % i \«>Löschen</button></td></tr>»;;
può PROGMEM lavoro a giornata HTML_CONFIG[] = 
«<form il metodo = \«annunciano \«><h1>Zugangsdaten</h1><table>»;
«<tr><td>WLAN SSID</td><td><input il tipo = \«il testo \» il nome = \«ssid \» il valore = \«il % vede \» size=50 maxlen=30/></td></tr>»;
«<tr><td>WLAN Passwort</td><td><input il tipo = \«il testo \» il nome = \«pwd \» il valore = \«il % vede \» size=50 maxlen=30/></td></tr>»;
«<tr><td>Cayenne Benutzername</td><td><input il tipo = \«il testo \» il nome = \«mquser \» il valore = \«il % vede \» size=50 maxlen=40/></td></tr>»;
«<tr><td>Cayenne Passwort</td><td><input il tipo = \«il testo \» il nome = \«mqpwd \» il valore = \«il % vede \» size=50 maxlen=50/></td></tr>»;
«<tr><td>Cayenne il cliente Id</td><td><input il tipo = \«il testo \» il nome = \«mqid \» il valore = \«il % vede \» size=50 maxlen=40/></td></tr>»;
«<tr><td>&nbsp;</td><td><button il nome = \«fa economie \» value=>Speichern</button></td></tr>»;
«</table></form></body></html>»;;

//Strutture di dati
//Respingente di notizie
struct MESSAGE_BUF {   uint8_t battere a macchina;   uint8_t di nuovo;   uint8_t dati[10];
};

//Definizione di dispositivo
struct DISPOSITIVO {   uint8_t attivamente;   uint8_t servizi; //0=LoRa, 1=ESP-Now   uint8_t id[6];   Spago nome;   Spago leggere;
};

//Variabili globali
//I dati di accesso questo può esser dato sul server Web
Spago wlanssid = «Lechner LAN»;
Spago wlanpwd = «Guadalquivir2711»;
Spago mqttuser = "";
Spago mqttpwd = "";
Spago mqttid = "";

//Autorità di server Web
Server Web server(80);

//Esposizione OLED
SSD1306  esposizione(0x3c, 4, 15);

//Respingente al respingente del canale di notizie
MESSAGE_BUF messaggi[MAXCHANNELS];

//Lista dei dispositivi definiti
DISPOSITIVO dispositivi[MAXDEVICE];

//Id di non dispositivo registrato
uint8_t sconosciuto[6];
//Si affievolisca sempre allora vero quando un nuovo dispositivo fu scoperto
boolean nuovo dispositivo = falso;
//Tipo del nuovo dispositivo 0=LöRa 1 =ESPNow
uint8_t neuesGeraetTyp = 0;

//Counter e stato di Aktivitaets per l'esposizione
uint32_t loraCnt = 0; //Numero delle notizie di LoRa ricevute
Spago loraLast = ""; //Data e tempo delle ultime notizie di LoRa ricevute
uint32_t nowCnt = 0; //Numero delle notizie ricevute SPECIALMENTE Adesso
Spago nowLast = ""; //Data e tempo delle ultime notizie di LoRa ricevute
uint32_t cayCnt = 0; //Numero delle notizie mandate MQTT
Spago cayLast = ""; // Data e ora dell'ultimo messaggio MQTT inviato


// La funzione restituisce data e ora nel formato aaaa-mm-gg hh: mm: ss come stringa
stringa GetLocalTime()
{   carbonizzare stTime[20] = "";   struct tm informazioni tempo;   se (WiFi.stato() == WL_CONNECTED) {     se(!GetLocalTime(&informazioni tempo)){       serial.println("Impossibile ottenere il tempo");       ritorno stTime;     }     strftime(stTime, sizeof(stTime), "%Y-%m-%d %H:%M:%S", &informazioni tempo);   }   ritorno stTime;
}

// La funzione restituisce un ID dispositivo a 6 byte nel formato xx: xx: xx: xx: xx: xx come stringa
stringa getId(uint8_t id[6])
{   stringa STID;   carbonizzare tmp[4];   sprintf(tmp,"% 02x",id[0]);   STID=tmp;   per (uint8_t j = 1; j<6; j++) {     sprintf(tmp,":% 02x",id[j]);     STID = STID += tmp ;   }   ritorno STID;
}

// prepara il buffer dei messaggi
// imposta tutti i messaggi su done
vuoto buffer dei messaggi init() {   per (int io = 0;io<MaxChannels;io++) messaggi[io].nuovo = 0;
}

// Funzione per salvare la configurazione
vuoto scrivi configurazione(const carbonizzare *fn) {   file f = spiffs.aperto(fn, file_write);   se (!f) {     serial.println(F("ERRORE: SPIFFS Impossibile salvare la configurazione"));     ritorno;   }   per (uint8_t io = 0; io<MAXDEVICE; io++) {     f.stampare(dispositivi[io].attivamente);f.stampare(",");     f.stampare(dispositivi[io].servizio);f.stampare(",");     f.stampare(getId(dispositivi[io].id));f.stampare(",");     f.stampare(dispositivi[io].nome);f.stampare(",");     f.println(dispositivi[io].carico);   }
}

// Funzione per la memorizzazione dei dati di accesso
vuoto accesso in scrittura(const carbonizzare *fn) {   file f = spiffs.aperto(fn, file_write);   se (!f) {     serial.println(F("ERRORE: SPIFFS non può salvare i dati di accesso"));     ritorno;   }   f.stampare("WLANSSID =");f.stampare(wlanssid);f.stampare('\ n');   f.stampare("WLANPWD =");f.stampare(wlanpwd);f.stampare('\ n');   f.stampare("MQTTUSER =");f.stampare(mqttuser);f.stampare('\ n');   f.stampare("MQTTPWD =");f.stampare(mqttpwd);f.stampare('\ n');   f.stampare("MQTTID =");f.stampare(mqttid);f.stampare('\ n');    }

// Funzione per la registrazione di un nuovo dispositivo
vuoto geraetRegistrieren() {   uint8_t io = 0;   // cerca l'ingresso gratuito   mentre ((io<MAXDEVICE) && dispositivi[io].attivamente) io++;   // se non ci sono nuove voci, non facciamo nulla   se (io < MAXDEVICE) {     // altrimenti registra Nome dispositivo = nome inserito      // o sconosciuto se non ne è stato inserito nessuno     se (server.hasArg("Devname")) {       dispositivi[io].nome = server.cattivo("Devname");     } altro {       dispositivi[io].nome = "Sconosciuto";     }     per (uint8_t j = 0; j<6; j++) dispositivi[io].id[j]=sconosciuto[j];     dispositivi[io].attivamente = 1;     dispositivi[io].servizio= nuovo tipo di dispositivo;     dispositivi[io].carico = "";     scrivi configurazione("/Konfiguration.csv");     nuovo dispositivo = falso;   }
}

// La pagina di configurazione viene visualizzata dal server Web
vuoto handleConfig(){   carbonizzare htmlbuf[1024];   booleano nuovo inizio = falso;   int indice;   // è stato premuto il pulsante di memoria?   se (server.hasArg("Salva")) {     // Dati dalla richiesta POST     wlanssid = server.cattivo("SSID");     // se il SSID contiene uno spazio otteniamo un "+"     // questo deve essere riconvertito in uno spazio per la registrazione     wlanssid.sostituire("+"," ");     wlanpwd = server.cattivo("PWD");     mqttuser = server.cattivo("Mquser");     mqttpwd = server.cattivo("Mqpwd");     mqttid = server.cattivo("Mqid");     serial.println("Nuova configurazione:");     serial.stampare("SSID");serial.println(wlanssid);     serial.stampare("Password");serial.println(wlanpwd);     serial.stampare("Utente");serial.println(mqttuser);     serial.stampare("Password");serial.println(mqttpwd);     serial.stampare("ID");serial.println(mqttid);     // Salva la nuova configurazione in SPIFFS     accesso in scrittura("/Zugang.txt");     // ricordiamo che è necessario riavviare la connessione WiFi     //comunque, prima deve consegnare tessono il server la parte di HTML     genere di riposo = vero;   }   //Problema della parte di configurazione   //formiamo la lancetta sulla memoria interna dello spago di accesso   //usare la connessione intorno a questo per sprintf e per iniziare il WLAN e Caienna   lavoro a giornata* txtSSID = const_cast<lavoro a giornata*>(wlanssid.c_str());   lavoro a giornata* txtPassword = const_cast<lavoro a giornata*>(wlanpwd.c_str());      lavoro a giornata* txtUser = const_cast<lavoro a giornata*>(mqttuser.c_str());   lavoro a giornata* txtPwd = const_cast<lavoro a giornata*>(mqttpwd.c_str());   lavoro a giornata* txtId = const_cast<lavoro a giornata*>(mqttid.c_str());   //Mandi la parte di HTML di attualità a navigatore   server.setContentLength(CONTENT_LENGTH_UNKNOWN);   //Testata   server.mandare(200, «testo / html»,HTML_HEADER);   server.sendContent(HTML_HEADER_END);   //La forma con i campi d'impiego diventa con i valori di attualità befüllt   sprintf(htmlbuf,HTML_CONFIG,txtSSID,txtPassword,txtUser,txtPwd,txtId);   //e in Browsewr mandato   server.sendContent(htmlbuf);   server.sendContent(HTML_END);   se (genere di riposo) {     //Se il resto che la bandiera gentile è stata in modo posato deve fare la connessione di WiFi separatamente e di nuovo     //sono costruiti     Seriale.println(«Ripresa»);     uint8_t time out = 0;     Seriale.println(«Connessione separata»);     WiFi.sconnettere();     mentre ((WiFi.stato() == WL_CONNECTED) && (time out < 10))     {       ritardo(1000);       time out++;     }     Seriale.println(«Di nuovo si connetta»);     WiFi.cominciare(txtSSID,txtPassword);     mentre ((WiFi.stato() != WL_CONNECTED) && (time out < 10))     {       ritardo(1000);       time out++;     }     Seriale.stampa(«Indirizzo IP»:);     Seriale.println(WiFi.localIP());     se (WiFi.stato() == WL_CONNECTED) {       //è stato di Neustrart con successo la connessione con Caienna deve esser anche aumentata di nuovo.       Seriale.println(«Caienna si connette»);       Caienna.cominciare(txtUser, txtPwd, txtId);     //L'orologio sincronizza con server di tempo     configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER);     //Trascorra il tempo di attualità     Seriale.println(getLocalTime());     }   }
}

//La parte di azzerramento è stata interrogata dal server Web
vuoto handleReset() {   //mettiamo i dati di accesso da parte    wlanssid= "";    wlanpwd = "";    mqttuser = "";    mqttpwd="";    mqttid="";    //e indichi i dati di configurazione    //solo se sulla configurazione parteggiano il distintivo    //A memorie è fatto clic, diventi i dati di accesso     //anche nello SPIFFS estinto.    handleConfig();
}

//La parte con la lista di dispositivo è stata interrogata dal server Web
vuoto handleWLANRequest(){   lavoro a giornata htmlbuf[512];   lavoro a giornata tmp1[20];   lavoro a giornata tmp2[20];   lavoro a giornata tmp3[20];   intervallo indice;   //è stato fatto clic il pulsante di estinzione?   se (server.hasArg(«cancellare»)) {     indice = server.male(«cancellare»).toInt();
#ifdef DEGUG     Seriale.printf(«Dispositivo di Lösche %i =»,indice);     Seriale.println(dispositivi[indice].nome);
#endif     dispositivi[indice].attivamente=0;     schreibeKonfiguration(«/konfiguration.csv»);   }   //è stata fatta clic la registrazione di pulsante?   se (server.hasArg(«registro»)) {     geraetRegistrieren();   }   //Mandi la parte di HTML di attualità a navigatore   server.setContentLength(CONTENT_LENGTH_UNKNOWN);   //Testata   server.mandare(200, «testo / html»,HTML_HEADER);   //Si rivolga a IP per ricaricano il copione   WiFi.localIP().toString().toCharArray(tmp1,20);   sprintf(htmlbuf,HTML_SCRIPT,tmp1);   server.sendContent(htmlbuf);   server.sendContent(HTML_HEADER_END);   //Inizio di forma   server.sendContent(«<div la classe = \«il titolo \«>MQTT - Gateway</div><form il metodo = \«annunciano \«>»;);   //Tavolo dei dispositivi attivi   server.sendContent(HTML_TAB_GERAETE);   per (uint8_t io = 0; io<MAXDEVICE; io++) {      se (dispositivi[io].attivamente == 1) {        getId(dispositivi[io].id).toCharArray(tmp1,20);       dispositivi[io].nome.toCharArray(tmp2,20);       dispositivi[io].leggere.toCharArray(tmp3,20);       sprintf(htmlbuf,HTML_TAB_ZEILE,tmp1,io,io*8,io*8+7,tmp2,tmp3,io);       server.sendContent(htmlbuf);     }   }   server.sendContent(HTML_TAB_END);   // Se viene trovato un nuovo dispositivo, il suo ID e un campo di input per il nome   // e viene visualizzato un pulsante per la registrazione del nuovo dispositivo   se (nuovo dispositivo) {     getId(sconosciuto).ToCharArray(tmp1,20);     sprintf(htmlbuf,HTML_NEWDEVICE,tmp1,tmp1);     server.Invia contenuti(htmlbuf);   }   server.Invia contenuti(HTML_END_RELOAD);
}

// Funzioni di servizio del server Web per la directory principale
vuoto handleRoot() {   se (WiFi.stato() != WL_CONNECTED) {     // se non abbiamo alcuna connessione alla rete del router     // Viene visualizzata la pagina di configurazione in modo da poter inserire i dati di accesso     handleConfig();   } altro {     handleWLANRequest();   }
}


// Funzione per cercare un dispositivo nell'elenco dei dispositivi
// Restituisce l'indice del dispositivo o -1 se non è stato trovato
int dispositivo posto(uint8_t dev[6]) {   uint8_t j;   uint8_t io = 0;   booleano fondare = falso;   fare {     j = 0;     se (dispositivi[io].attivamente == 0) {       io++;     } altro {       mentre ((j < 6) && (dev[j] == dispositivi[io].id[j])) {j++;}       fondare = (j == 6);       se (!fondare) io++;      }    } mentre ((io<MAXDEVICE) && (!fondare));   se (fondare) {ritorno io;} altro {ritorno -1;}
}

// Funzione per visualizzare lo stato sul display OLED
vuoto display() {   display.chiaro();   display.drawString(0,0,"MQTT Gateway");   display.drawString(0,10,GetLocalTime());   display.drawString(0,20,WiFi.LocalIP().toString());   display.drawString(0,34,"MQTT");   display.drawString(60,34,stringa(cayCnt));   display.drawString(0,44,"LoRa");   display.drawString(60,44,stringa(loraCnt));   display.drawString(0,54,"NOW");   display.drawString(60,54,stringa(nowCnt));   display.display();
}


// Elabora un messaggio da un client LoRa
vuoto readLoRa() {   int devnr;   uint8_t devid[6];   uint8_t canale;   uint8_t tipo;   uint8_t len;   uint8_t dat;   booleano produzione;   // recupera i dati se disponibili   int dimensione del pacchetto = LoRa.parsePacket();   // abbiamo ricevuto dati?   se (dimensione del pacchetto > 5) {
#ifdef DEBUG         serial.println(GetLocalTime());     serial.stampare("RX");     serial.stampare(dimensione del pacchetto);     serial.println("Byte");     serial.stampare("ID dispositivo");
#endif      // legge prima l'ID del dispositivo     per (uint8_t io=0; io<6;io++){       devid[io]=LoRa.leggere();
#ifdef DEBUG       serial.printf("-% 02x",devid[io]);
#endif     }
#ifdef DEBUG     serial.println();
#endif     // calcola il pacchetto rimanente     dimensione del pacchetto -= 6;     // controlla se il dispositivo è registrato     devnr = dispositivo posto(devid);     se (devnr >= 0)  {       // se sì, impostiamo il timestamp per l'ultimo messaggio e       // leggi i dati       dispositivi[devnr].carico = GetLocalTime();       scrivi configurazione("/Konfiguration.csv");       mentre (dimensione del pacchetto > 0) {         // Numero canale = numero dispositivo * 16 + canale dispositivo         canale = LoRa.leggere() + devnr*16;
#ifdef DEBUG         serial.printf("Canale:% 02x",canale);
#endif         // tipo di canale         tipo = LoRa.leggere();
#ifdef DEBUG         serial.printf("Tipo:% 02x",tipo);
#endif         // determina la lunghezza del pacchetto di dati e se il canale è un attuatore         produzione = falso;         interruttore(tipo) {           caso LPP_DIGITAL_INPUT : len = LPP_DIGITAL_INPUT_SIZE - 2; pausa;           caso LPP_DIGITAL_OUTPUT : len = LPP_DIGITAL_OUTPUT_SIZE - 2; produzione = vero; pausa;           caso LPP_ANALOG_INPUT : len = LPP_ANALOG_INPUT_SIZE - 2; pausa;           caso LPP_ANALOG_OUTPUT : len = LPP_ANALOG_OUTPUT_SIZE - 2; produzione = vero; pausa;           caso LPP_LUMINOSITY : len = LPP_LUMINOSITY_SIZE - 2; pausa;           caso LPP_PRESENCE : len = LPP_PRESENCE_SIZE - 2; pausa;           caso LPP_TEMPERATURE : len = LPP_TEMPERATURE_SIZE - 2; pausa;           caso LPP_RELATIVE_HUMIDITY : len = LPP_RELATIVE_HUMIDITY_SIZE - 2; pausa;           caso LPP_ACCELEROMETER : len = LPP_ACCELEROMETER_SIZE - 2; pausa;           caso LPP_BAROMETRIC_PRESSURE : len = LPP_BAROMETRIC_PRESSURE_SIZE - 2; pausa;           caso LPP_GYROMETER : len = LPP_GYROMETER_SIZE - 2; pausa;           caso LPP_GPS : len = LPP_GPS_SIZE - 2; pausa;           difetto: len =  0;         }         //se il canale non è nessun attuatore, mettiamo nel respingente di notizie di nuovo su 1         //con esso i dati sono mandati con la prossima opportunità al server MQTT         se (!uscita) messaggi[canale].di nuovo =1;         messaggi[canale].battere a macchina = battere a macchina;         //Il pacco di riposo = 2 meno canali là e tipo è stato letto         packetSize -= 2;
#ifdef MESSA A PUNTO         Seriale.stampa(«Dati»:);
#endif         //adesso leggiamo i dati ricevuti con la lunghezza accertata         per (uint8_t io=0; io<len; io++) {           dat = LoRa.Leggere();           //per attuatori non ci notiamo nessun dato           se (! uscita) messaggi[canale].dati[io] = dat;
#ifdef MESSA A PUNTO           Seriale.printf(«-x»,dat);
#endif           //Pacco di riposo di diminuzione intorno a uno           packetSize --;         }
#ifdef MESSA A PUNTO         Seriale.println();
#endif       }       //Aggiornamenti di stato       loraCnt++;       loraLast = getLocalTime();       registri();     } altro {       //Il dispositivo non è registrato        //ci notiamo che il Geräte-Id intorno a loro per Registriuerung si iscrive       per (uint8_t io = 0; io<6; io++) sconosciuto[io] = devid[io];       nuovo dispositivo = vero;       neuesGeraetTyp = 0; //Dispositivo di LoRa     }     //La parte due risposte manda al dispositivo di LoRa     ritardo(100);     LoRa.beginPacket();     //all'inizio il Geräte-Id     LoRa.scrivere(devid,6);     //chiediamo se i dati di uscita per il dispositivo di LoRa di attualità abbiamo     intervallo devbase = devnr*16;     per (intervallo io = devbase; io<devbase+8; io++) {       //secondo tipo Digitalmente o dati analoghi       interruttore (messaggi[io].battere a macchina) {           caso LPP_DIGITAL_OUTPUT : LoRa.scrivere(io-devbase);             LoRa.scrivere(messaggi[io].battere a macchina);             LoRa.scrivere(messaggi[io].dati,1);
#ifdef MESSA A PUNTO             Seriale.println(«Digitalmente uscita»);
#endif             pausa;           caso LPP_ANALOG_OUTPUT :  LoRa.scrivere(io-devbase);             LoRa.scrivere(messaggi[io].battere a macchina);             LoRa.scrivere(messaggi[io].dati,2);
#ifdef MESSA A PUNTO             Seriale.println(«Analogamente uscita»);
#endif             pausa;       }     }          intervallo lstatus = LoRa.endPacket();
#ifdef MESSA A PUNTO     Seriale.stampa(«Stato trasmittente =»);     Seriale.println(lstatus);
#endif   }
}

//Funzione alla lettura della configurazione
vuoto lettura di configurazione(può lavoro a giornata *fn) {   uint8_t io = 0;   Spago tmp;   lavoro a giornata stregoneria di pratica[3];   se (!SPIFFS.esiste(fn)) {     //non esiste già allora generano     schreibeKonfiguration(fn);     ritornare;   }   File e il seguente = SPIFFS.aperto(fn, «r»);   se (!e il seguente) {     Seriale.println(E IL SEGUENTE(«ERRORE:: SPIFFS essere la configurazione capace non si aprono»));     ritornare;   }   mentre (e il seguente.disponibile() && (io<MAXDEVICE)) {     tmp = e il seguente.readStringUntil(',');     dispositivi[io].attivamente = (tmp == "1");     tmp = e il seguente.readStringUntil(',');     dispositivi[io].servizi = tmp.toInt();     tmp = e il seguente.readStringUntil(',');     per (uint8_t j=0; j<6; j++){       stregoneria di pratica[0]=tmp[j*3];       stregoneria di pratica[1]=tmp[j*3+1];       stregoneria di pratica[2]=0;       dispositivi[io].id[j]= (byte) strtol(stregoneria di pratica,ZERO,16);     }     tmp = e il seguente.readStringUntil(',');     dispositivi[io].nome = tmp;     tmp = e il seguente.readStringUntil(',');     dispositivi[io].leggere = tmp;     io++;   }    }
//Funzione alla lettura dei dati di accesso
vuoto lettura di accesso(può lavoro a giornata *fn) {   uint8_t io = 0;   Spago chiave;   Spago val;   lavoro a giornata stregoneria di pratica[3];   se (!SPIFFS.esiste(fn)) {     //non esiste già allora generano     schreibeZugang(fn);     ritornare;   }   File e il seguente = SPIFFS.aperto(fn, «r»);   se (!e il seguente) {     Seriale.println(E IL SEGUENTE(«ERRORE:: SPIFFS essere dati di accesso capaci non si aprono»));     ritornare;   }   mentre (e il seguente.disponibile() && (io<MAXDEVICE)) {     chiave = e il seguente.readStringUntil('=');     val = e il seguente.readStringUntil(di '\n');     se (chiave == «WLANSSID») wlanssid = val;     se (chiave == «WLANPWD») wlanpwd = val;      se (chiave == «MQTTUSER») mqttuser = val;      se (chiave == «MQTTPWD») mqttpwd = val;      se (chiave == «MQTTID») mqttid = val;    }    }

vuoto situazione() {   //le memorie di dispositivo inizializzano   per (uint8_t io =0; io<MAXDEVICE; io++) dispositivi[io].attivamente = 0;   //Inizializzi l'esposizione OLED   pinMode(16,USCITA);   digitalWrite(16, IN BASSO);   ritardo(50);    digitalWrite(16, IN ALTO);   esposizione.init();   esposizione.flipScreenVertically();   esposizione.setFont(ArialMT_Plain_10);   esposizione.setTextAlignment(TEXT_ALIGN_LEFT);   //Cominci l'interfaccia seriale   Seriale.cominciare(115200);   mentre (!Seriale);    Seriale.println(«Cominciare»);   //Sistema di file di lampo   se (SPIFFS.cominciare(FORMAT_SPIFFS_IF_FAILED)) Seriale.println(E IL SEGUENTE(«SPIFFS caricato»));   //Legga in dati di accesso e di configurazione   lettura di configurazione(«/konfiguration.csv»);   lettura di accesso(«/zugang.txt»);   initMessageBuffer();   //SPI e LoRa inizializzano   SPI.cominciare(5,19,27,18);   LoRa.setPins(SS,RST,DI0);   Seriale.println(«LoRa TRX»);   se (!LoRa.cominciare(NASTRO)) {     Seriale.println(«L'inizio di LoRa ha fallito!»);     mentre (1);   }   LoRa.enableCrc();   Seriale.println(«LoRa inizialmente va bene!»);   ritardo(2000);   //Problema dei dati di accesso letti al controllo   Seriale.stampa(«SSID»:);Seriale.println(wlanssid);   Seriale.stampa(«Parola d'ordine»:);Seriale.println(wlanpwd);   Seriale.stampa(«Utente»:);Seriale.println(mqttuser);   Seriale.stampa(«Parola d'ordine»:);Seriale.println(mqttpwd);   Seriale.stampa(«ID»:);Seriale.println(mqttid);   //Colleghi al WLAN e il server MQTT   Seriale.println(«WLAN si connettono»);   //usiamo l'ESP32 come un Accesso Poin, comunque, anche come un cliente nella rete d'instradatore   WiFi.moda(WIFI_AP_STA);   //abbiamo bisogno di lancetta sulla memoria di segno dentro lo spago   lavoro a giornata* txtSSID = const_cast<lavoro a giornata*>(wlanssid.c_str());   lavoro a giornata* txtPassword = const_cast<lavoro a giornata*>(wlanpwd.c_str());      lavoro a giornata* txtUser = const_cast<lavoro a giornata*>(mqttuser.c_str());   lavoro a giornata* txtPwd = const_cast<lavoro a giornata*>(mqttpwd.c_str());   lavoro a giornata* txtId = const_cast<lavoro a giornata*>(mqttid.c_str());   WiFi.cominciare(txtSSID, txtPassword);   //La connessione nella rete d'instradatore è prodotta   uint8_t time out = 0;   mentre ((WiFi.stato() != WL_CONNECTED) && (time out<10)) {     time out++;     ritardo(1000);   }   //aspettiamo 10 secondi massimi agli stand di connessione   //Senza badare alla connessione nella rete d'instradatore cominciamo AccessPoint   //questo permette la configurazione su un navigatore, se noi a questi    //in AccessPoint annunciano   WiFi.softAP(«MQTTGateway»);   se (WiFi.stato() == WL_CONNECTED) {     //Se la connessione è stata di successo nella rete d'instradatore, cominciamo MQTT a Caienna     //e sincronizzi l'orologio interno con il server di tempo     Seriale.stampa(«Indirizzo IP»:);     Seriale.println(WiFi.localIP());     Caienna.cominciare(txtUser, txtPwd, txtId);     Seriale.println(«Connessione di Caienna fatta»);     //L'orologio sincronizza con server di tempo     configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER);     //Trascorra il tempo di attualità     Seriale.println(getLocalTime());   }   //I server Web inizializzano   server.su("/", handleRoot);   server.su(«/conf»,handleConfig);   server.su(«/azzerramento»,handleReset);   server.cominciare();   Seriale.println("*********************************************");


}


vuoto cappio() {   registri();   se (WiFi.stato() == WL_CONNECTED) {     //Controlli l'interfaccia LoRa per dati     readLoRa();     //con Caienna i server di MQTT comunicano     Caienna.cappio(1);   }   //Servizio di server Web   server.handleClient();

}

//I dati dal respingente di notizie mandano al server MQTT
CAYENNE_OUT_DEFAULT()
{   boolean uscita = falso;   boolean sentData = falso;
#ifdef MESSA A PUNTO   Seriale.println(getLocalTime());   Seriale.println(«Caienna manda»);
#endif   per (intervallo io = 0; io<MAXCHANNELS; io++) {     //solo le notizie mandano     se (messaggi[io].di nuovo == 1) {
#ifdef MESSA A PUNTO       Seriale.printf(«Sende MQTT Typ %i\n»,messaggi[io].battere a macchina);
#endif       //secondo tipo i Dati mandano       interruttore (messaggi[io].battere a macchina) {           caso LPP_DIGITAL_INPUT : Caienna.digitalSensorWrite(io,messaggi[io].dati[0]); pausa;           caso LPP_DIGITAL_OUTPUT : uscita = vero; pausa;           //caso LPP_ANALOG_INPUT: Cayenne.virtualWrite (io, (messaggi [io] .daten [0] *256 messaggi [io] .daten [1])/100, «analog_sensor», UNIT_UNDEFINED); pausa; pausa;           caso LPP_ANALOG_OUTPUT : uscita = vero; pausa;           caso LPP_LUMINOSITY : Caienna.luxWrite(io,messaggi[io].dati[0]*256 + messaggi[io].dati[1]); pausa;           caso LPP_PRESENCE : Caienna.digitalSensorWrite(io,messaggi[io].dati[0]); pausa;           caso LPP_TEMPERATURE : Caienna.celsiusWrite(io,(messaggi[io].dati[0]*256 + messaggi[io].dati[1])/10); pausa;           caso LPP_RELATIVE_HUMIDITY : Caienna.virtualWrite(io,messaggi[io].dati[0]/2,TYPE_RELATIVE_HUMIDITY,UNIT_PERCENT); pausa;           caso LPP_ACCELEROMETER : Caienna.virtualWrite(io,(messaggi[io].dati[0]*256 + messaggi[io].dati[1])/1000,«gx»,«g»); pausa;           caso LPP_BAROMETRIC_PRESSURE : Caienna.hectoPascalWrite(io,(messaggi[io].dati[0]*256 + messaggi[io].dati[1])/10); pausa;           //caso LPP_GYROMETER: len = LPP_GYROMETER_SIZE - 2; pausa;           //caso LPP_GPS: len = LPP_GPS_SIZE - 2; pausa;       }       se (!uscita) {         messaggi[io].di nuovo = 0;         sentData = vero;       }            }   }   se (sentData) {     //Aggiornamenti di stato     cayCnt++;     cayLast = getLocalTime();     registri();   }

}

CAYENNE_IN_DEFAULT()
{   uint8_t * pData;   intervallo val;   intervallo ch = richiesta.canale;
#ifdef MESSA A PUNTO   Seriale.println(«Caienna riceve»);   Seriale.printf(«Dati MQTT per canale %i = %s\n»,ch,getValue.asString());
#endif   interruttore (messaggi[ch].battere a macchina) {       caso LPP_DIGITAL_OUTPUT : messaggi[ch].dati[0] = getValue.santo();         messaggi[ch].di nuovo = 1;         pausa;       caso LPP_ANALOG_OUTPUT :  val = intorno(getValue.asDouble()*100);         messaggi[ch].dati[0] = val / 256;         messaggi[ch].dati[1] = val % 256;         messaggi[ch].di nuovo = 1;         pausa;   }   CAYENNE_LOG(«Il canale %u, valuti %s», richiesta.canale, getValue.asString());   //Messaggio di processo qui. Se c'è in serie di errore in messaggio di errore usando getValue.setError (), ad esempio getValue.setError («L'errore di messaggio»);    }

 

Molto divertimento con la prova.

Esp-32Projekte für fortgeschrittene

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione