Na een paar mislukte pogingen om een universele LoRa-gateway met de ESP32 te bouwen, werd de volgende eigen gateway gemaakt, waarmee op LoRa gebaseerde IoT-apparaten via MQTT met het Cayenne Dashboard kunnen worden verbonden. In een uitgebreide versie beheert de gateway ook IoT-apparaten op basis van het ESP-Now-protocol.
We hebben er maar één nodig voor de gateway ESP32 met LoRa en OLED-displayverdere componenten zijn niet nodig. De voeding kan worden gedaan met elke USB-voeding.
Functie beschrijving:
De gateway kan 32 apparaten beheren met elk maximaal 8 kanalen. De gegevensoverdracht is asynchroon. Wanneer de gateway een LoRa-gegevenspakket ontvangt, worden de eerste zes bytes geïnterpreteerd als apparaat-ID (meestal het MAC-adres). De gateway controleert vervolgens in een apparatenlijst of dit apparaat al is geregistreerd. Als dit niet het geval is, wordt de apparaat-ID opgeslagen en weergegeven voor registratie via de webinterface.
Als het apparaat al is geregistreerd, worden de gegevens uitgelezen en opgeslagen in een berichtenbuffer voor elk kanaal. Het kanaalnummer wordt bepaald op basis van het apparaatnummer (index in de apparatenlijst) * 8 + kanaalnummer van de ontvangen gegevens. Apparaat 0 heeft dus kanalen 0 tot 7, apparaat 1 heeft kanalen 8 tot 15 etc.
Een gegevensrecord begint met een byte voor het kanaalnummer gevolgd door een byte met het type en vervolgens 1 tot 6 gegevensbytes, afhankelijk van het type. Nadat alle gegevens in de berichtenbuffer zijn opgeslagen en als nieuw zijn gemarkeerd, wordt het responspakket op het Lora-apparaat samengesteld. Het begint opnieuw met de zes bytes apparaat-ID. De kanalen voor dit apparaat worden vervolgens in de berichtenbuffer gecontroleerd om te bepalen of er een uitgaand gegevenspakket van Cayenne naar het apparaat is dat is gemarkeerd met Nieuw. Als een dergelijk datapakket wordt gevonden, wordt het toegevoegd aan het antwoordpakket, waarbij het relatieve kanaalnummer 0 tot 7 opnieuw wordt gebruikt. Als laatste stap wordt het responspakket overgedragen naar het LoRa-apparaat.
De functie Cayenne.loop (1) neemt de communicatie met de IoT-server over. In de callback-functie CAYENNE_OUT_DEFAULT () worden alle kanalen gezocht in de berichtenbuffer die zijn gemarkeerd met Nieuw en die een invoergegevenspakket voor het type Cayenne bevatten. Deze pakketten worden nu geconverteerd, afhankelijk van het type en verzonden naar de IoT-server. Na een succesvolle overdracht wordt de nieuwe vlag gereset.
Een tweede callback-functie CAYENNE_IN_DEFAULT () wordt aangeroepen wanneer er gegevens van Cayenne zijn voor een actiekanaal. De gegevens van de IoT-server worden afhankelijk van het type geconverteerd en opgeslagen in de berichtenbuffer. Ze zijn gemarkeerd met Nieuw zodat ze naar het apparaat worden verzonden de volgende keer dat LoRa communiceert met het antwoordpakket.
Weer te geven:
Naast de naam toont het display de huidige datum en tijd. Daaronder het IP-adres.
De regel MQTT: toont het aantal succesvolle overdrachten naar de IoT-server, LoRa de succesvolle overdrachten naar LoRa-apparaten en NU het aantal succesvolle overdrachten naar ESP-Now-apparaten. De laatste is momenteel altijd 0 omdat deze functie nog niet is geïmplementeerd.
Apparatenlijst en registratie:
De apparatenlijst wordt opgeslagen als een CSV-bestand in het flash-bestandssysteem (SPIFFS) zodat het wordt bewaard, zelfs als er geen voeding is. Deze lijst kan worden bijgehouden via de webserver die in de gateway is geïntegreerd. Apparaten kunnen worden verwijderd en nieuwe apparaten kunnen worden geregistreerd.
Datapakketten:
Voor het type zijn de codes volgens de IPSO Alliance Smart Objects-richtlijnen, maar 3200 wordt afgetrokken.
Type | IPSO | TypNr. | Bytes | Ontbinding |
Digitale ingang | 3200 | 0 | 1 | 1 |
Digitale uitgang | 3201 | 1 | 1 | 1 |
Analoge ingang | 3202 | 2 | 2 | 0,01 met teken |
Analoge uitgang | 3203 | 3 | 2 | 0,01 met teken |
Verlichting sensor | 3301 | 101 | 2 | 1 lux |
Aanwezigheidssensor | 3302 | 102 | 1 | 1 |
Temperatuur sensor | 3303 | 103 | 2 | 0.1°C met het teken van de |
luchtvochtigheid Sensor, | 3304 | 104 | 1 | 0.5% |
de acceleratie Sensor | 3313 | 113 | 6 | 0.001 G met het teken voor elk van de assen X, Y en Z |
druk Sensor | 3315 | 115 | 2 | 0.1 hPa |
Gyrometer | 3334 | 134 | 6 | 0.01%/s, met het teken , afhankelijk van de X-as, Y -, en Z - |
GPS-Positie | 3336 | 136 | 9 | breedtegraad in graden 0.0001° met het teken lengtegraad 0.0001° , met het teken van de hoogte van 0,01 m met het teken |
Schets:
De registratie van de gateway in het geval van de Cayenne is op dezelfde manier gedaan als in deel 1 van deze Blog-serie beschreven. De toegang tot de gegevens dienen te worden in de Schets is ingevoerd (gele markering), en de toegang tot gegevens om in te Loggen op het lokale Wi-Fi. De Cayenne Dashboard geeft de Widgets, nog geen apparaat is aangesloten op de Gateway.
Raad voor de Arduino IDE = TTGO LoRa32-OLED-V1
/* * De MQTT Gateway is een Interface tussen de LoRa apparaten of ESP Nowe apparaten * en Cayenne MQTT Dashboards. Het draait op ESP32 met LoRa en OLED-Display * De configuratie van de Browser */ #include <SPI.h> #include <LoRa.h> #include "SSD1306.h" #include<Arduino.h> #include <CayenneMQTTESP32.h> #include <CayenneLPP.h> #include <WiFi.h> #include <de webserver.h> #include <tijd.h> #include "FS.h" #include "SPIFFS.h" //De gegevens voor deze instelling krijgen we van de Cayenne Dashboard #define MQTT_USER "" #define MQTT_PASSWORD "" #define MQTT_CLIENTID "" // toegang tot de gegevens voor de lokale Wi-Fi - #define WIFI_SSID "" #define WIFI_PASSWORD "" //NTP-Server voor tijdsynchronisatie .#definiëren NTP_SERVER "de.pool.ntp.org" #define GMT_OFFSET_SEC 3600 #define DAYLIGHT_OFFSET_SEC 0 //Pennen voor de LoRa Chip #define SS 18 #define EERSTE 14 #define DI0 26 //- Frequentie voor de LoRa Chip #define BAND - 433175000 // #define MAXCHANNELS 256 //maximum aantal beheerde kanalen #define MAXDEVICE 32 //maximum aantal van beheerde apparaten MAXCHANNELS/MAXDEVICE = 8 het maximum aantal kanalen //Formatteren van het Flash-Bestandssysteem als het nog niet klaar #define FORMAT_SPIFFS_IF_FAILED true #define DEBUG 1 //bouwstenen voor de Web-Server, const char HTML_HEADER[] = "<!DOCTYPE HTML>" "<html>" "<head>" "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-schaalbare=0>\">" "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" "<title>MQTT Gateway</title>" "<script language=\"javascript\">" "function laden() {" "document.locatie=\"http://%s\";}" "</script>" "<style>" "body { background-color: #d2f3eb; font-family: Arial, Helvetica, Sans-Serif; Color: #000000;font-size:12pt; }" "th { background-color: #b6c0db; color: #050ed2;font-weight:lichter;font-size:10pt;}" "table, th, td {border: 1px solid black;}" ".title {font-size:18pt;font-weight:bold;text-align:center;}" "</style>" "</head>" "<body><div style='margin-left:30 met een afwijkende;'>"; const char HTML_END[] = "</div><script language=\"javascript\">setTimeout(reload, 10000);</script></body>" "</html>"; const char HTML_TAB_GERAETE[] = "<table style=\"width:100%\"><tr><th style=\"width:20%\">ID</th><th style=\"width:10%\">nr.</th>" "<th style=\"width:20% off\">Kanalen</th><th style=\"width:20%\">Naam</th>" "<th style=\"width:20%\">laatste</th><th style=\"width:10%\">Action</th></tr>"; const char HTML_TAB_END[] = "</table>"; const char HTML_NEWDEVICE[] = "<div style=\"margin-top:20px;\">%s Naam: <input type=\"text\" style=\"width:200px\" name=\"apparaatnaam\" maxlength=\"10\" value=\"\"> <button name=\"aanmelden\" value=\"%s\">Register</button></div>"; const char HTML_TAB_ZEILE[] = "<tr><td>%s</td><td>%h</td><td>%i %i</td><td>%s</td><td>%s</td><td><button name=\"verwijderen\" value=\"%i\">Verwijderen</button></td></tr>"; //data structuren, //bericht Buffer struct MSG_BUF { uint8_t type,; uint8_t nieuwe; uint8_t gegevens[10]; }; //eenheid definitie van struct APPARAAT, { uint8_t actieve; uint8_t service; //0=LoRa, 1=ESP-Nu uint8_t id[6]; String naam,; String laden; }; //Globale Variabele //de web server web server server(80); //OLED Display SSD1306 display(0x3c, 4, 15); //Buffer voor het opslaan van de berichten voor elk kanaal MSG_BUF berichten[MAXCHANNELS]; //lijst van gedefinieerde apparaten, APPARAAT, apparaten[MAXDEVICE]; //Id van een niet-geregistreerd apparaat, uint8_t onbekend[6]; //Vlag is altijd het geval wanneer een nieuw apparaat werd ontdekt boolean nieuwe eenheid = false; //het type van het nieuwe apparaat, 0=LöRa 1 =ESPNow uint8_t neuesGeraetTyp = 0; //tellers en Activiteit de Status van het Display uint32_t loraCnt = 0; //aantal ontvangen LoRa bericht String loraLast = ""; //datum en tijd van de laatste ontvangen LoRa bericht uint32_t nowCnt = 0; //aantal ontvangen ESP Nu bericht String nowLast = ""; //datum en tijd van de laatste ontvangen LoRa bericht uint32_t cayCnt = 0; //aantal verzonden MQTT berichten String cayLast = ""; //datum en tijd van de laatste verzonden MQTT bericht //Functie geeft de datum en de tijd in de Notatie jjjj-mm-dd hh:mm:ss-als een Tekenreeks Tekenreeks getLocalTime() { char sttime[20] = ""; struct tm tijd info; als(!getLocalTime(&tijd info)){ Seriële.println("Failed to verkrijgen tijd"); terug sttime; } strftime(sttime, sizeof(sttime), "%Y-%m-%d %H:%M:%S", &tijd info); terug sttime; } //functie geeft als resultaat een 6-Byte apparaat-Id in de notatie xx:xx:xx:xx:xx:xx als String String getId(uint8_t id[6]) { String stid; char tmp[4]; sprintf(tmp,,"%02x",id[0]); stid=tmp; voor (uint8_t j = 1; j<6; j++) { sprintf(tmp,":%02x",, id[j]); stid = stid += tmp ; } terug stid; } //stelt het bericht buffer vóór //zet alle berichten voltooid void init bericht buffer() { voor (int i = 0;i<MAXCHANNELS;ik++) berichten die[ik].her - = 0; } //functie om de configuratie op te Slaan void schrijf configuratie(const char *fn -) { Bestand f = SPIFFS.open(fn,, FILE_WRITE); als (!f) { Seriële.println(F("FOUT: SPIFFS Kan de configuratie niet opslaan")); return; } voor (uint8_t ik, = 0; ik<MAXDEVICE; i++) { f.afdrukken(apparaten[ik].actief);f.print(","); f.afdrukken(apparaten[ik].de service);f -.print(","); f.print(getId(apparaten[i].id));f.print(","); f.afdrukken(apparaten[ik].de naam);f.print(","); f.println(apparaten[ik].laad); } } //Functie voor het Registreren van een nieuw apparaat ongeldig apparaat registreren() { uint8_t ik = 0; //het vinden van een gratis vermelding terwijl ((ik<MAXDEVICE) && apparaten[ik].actief) i++; //er is geen nieuwe inschrijving doen we niets als (ik < MAXDEVICE) { //anders wordt de eenheid registreren Naam = Naam ingevoerd //of onbekend of er niemand was ingevoerd als (de server.hasArg("apparaatnaam")) { apparaten[i].- naam van de = server -.arg("apparaatnaam"); } anders { apparaten die[ik].de naam = "onbekend"; } voor (uint8_t j = 0; j<6; j++) apparaten[i].- id[j]=onbekende[j]; - apparaten[ik].actief = 1; apparaten[ik].service= neuesGeraetTyp; apparaten[ik].belasting = ""; schrijven configuratie("/de configuratie.csv"); nieuwe eenheid = false; } } //Dienst functie van de Web server void handvat wortel,() { char htmlbuf[1024]; char tmp1[20]; char tmp2[20]; char tmp3[20]; int index,; //is de delete-knop is geklikt ? als (de server.hasArg("verwijderen")) { index = server -.arg("verwijderen").toInt(); #ifdef DEGUG Seriële.printf("apparaat Wissen %i = ",index van); Seriële.println(apparaten[index].naam); #endif apparaten[index].actieve=0; schrijven configuratie("/de configuratie.csv"); } //de 'Register' knop wordt geklikt ? als (de server.hasArg("registreren")) { eenheid registreren(); } //Huidige HTML-pagina naar de Browser verzenden naar de server.setContent lengte(CONTENT_LENGTH_UNKNOWN); //Header WiFi.localIP().toString().toCharArray(tmp1,20); sprintf(htmlbuf,HTML_HEADER,tmp1); server te.sturen(200, "text/html",htmlbuf); //vorm van het begin van de server.sendContent("<div class=\"titel\">MQTT - Gateway</div><form>"); //Tabel van actieve apparaten server.sendContent(HTML_TAB_GERAETE); voor (uint8_t ik, = 0; ik<MAXDEVICE; ik++) { als (apparaten[ik].actief == 1) { getId(apparaten[i].- id).toCharArray(tmp1,20); apparaten[ik].de naam.toCharArray(tmp2,20); apparaten[ik].belasting.toCharArray(tmp3,20); sprintf(htmlbuf,HTML_TAB_ZEILE,tmp1,ik,ik*8,ik*8+7,tmp2,tmp3,ik); server.sendContent(htmlbuf); } } server.sendContent(HTML_TAB_END); //Als er een nieuw apparaat is gevonden zijn ID en een invoerveld voor de naam // en een knop voor het Registreren van de nieuwe eenheid als (een nieuwe eenheid) { getId(onbekend).toCharArray(tmp1,20); sprintf(htmlbuf,HTML_NEWDEVICE,tmp1,tmp1); server.sendContent(htmlbuf); } server.sendContent(HTML_END); } //functie om te Zoeken naar een apparaat in de lijst //de Terugkeer van de Index van het apparaat of -1 als deze niet gevonden int vinden apparaat(uint8_t dev,[6]) { uint8_t j,; uint8_t ik, = 0; boolean gevonden = op false; doen { j = 0; als (apparaten[ik].actief == 0) { ik++; } anders { terwijl ((j < 6) && (dev[j] == apparaten[i].- id[j])) {j++;} gevonden = (j == 6); als (!vond) ik++; } } terwijl ((ik<MAXDEVICE) && (!gevonden)); als (gevonden) {terug ik;} anders {terug -1;} } //Functie om de Status op het OLED-Display void display() { display.duidelijk(); display.koord(0,0,"MQTT Gateway"); display.koord(0,10,getLocalTime()); display.koord(0,20,WiFi.localIP().toString()); display.koord(0,34,"MQTT: "); display.koord(60,34,String(cayCnt)); display.koord(0,44,"LoRa: "); display.koord(60,44,String(loraCnt)); display.koord(0,54,"NU: "); display.koord(60,54,String(nowCnt)); display.display(); } //een bericht afkomstig is van Een LoRa Client proces nietig readLoRa() { int typen devnr; uint8_t devid,[6]; uint8_t kanaal,; uint8_t type,; uint8_t len,; uint8_t dat; boolean - uitgang; //ophalen van gegevens als het bestaat int packetSize = LoRa.parsePacket(); //we hebben ontvangen van gegevens ? als (packet-grootte > 5) { #ifdef DEBUG Serial.. println(getLocalTime()); Serieel.afdrukken(" RX "); Serieel.afdrukken(packet grootte); van de Seriële.println(" Bytes"); Serieel.afdrukken("Device ID"); #endif //stel eerst de apparaat-Id om te lezen voor (uint8_t ik,=0; ik,<6;ik,++){ devid[ik]=LoRa.read(); #ifdef DEBUG Seriële.printf("-%02x",devid[ik,]); #endif } #ifdef DEBUG Serial.. println(); #endif //rest van het pakket voor het berekenen van de pakket grootte -= 6; //controleer of het apparaat is geregistreerd, wordt het typen van devnr = vinden apparaat(devid); als (typen devnr >= 0) { //indien Ja, we instellen van de tijd-stempel voor het laatste bericht en /lees/de gegevens apparaten[typen devnr].laden = getLocalTime(); schrijven configuratie("/de configuratie.csv"); terwijl (pakket grootte > 0) { //kanaal nummer = nummer van het apparaat * 16 + apparaat, kanaal kanaal, = LoRa.lees() + typen devnr*16; #ifdef DEBUG Seriële.printf("kanaal: %02x ",, kanaal); #endif //type van het kanaal type = LoRa.read(); #ifdef DEBUG Seriële.printf("typt u: %02x ",type); #endif //bepalen van de lengte van het data pakket en als het kanaal is een actuator output = false,; switch(type) { case LPP_DIGITAL_INPUT : len = LPP_DIGITAL_INPUT_SIZE - 2; breken; geval LPP_DIGITAL_OUTPUT : len = LPP_DIGITAL_OUTPUT_SIZE - 2; uitgang = waar; breken; geval LPP_ANALOG_INPUT : len = LPP_ANALOG_INPUT_SIZE - 2; breken; geval LPP_ANALOG_OUTPUT : len = LPP_ANALOG_OUTPUT_SIZE - 2; uitgang = waar; breken; geval LPP_LUMINOSITY : len = LPP_LUMINOSITY_SIZE - 2; breken; geval LPP_PRESENCE : len = LPP_PRESENCE_SIZE - 2; breken; geval LPP_TEMPERATURE : len = LPP_TEMPERATURE_SIZE - 2; breken; geval LPP_RELATIVE_HUMIDITY : len = LPP_RELATIVE_HUMIDITY_SIZE - 2; breken; geval LPP_ACCELEROMETER : len = LPP_ACCELEROMETER_SIZE - 2; breken; geval LPP_BAROMETRIC_PRESSURE : len = LPP_BAROMETRIC_PRESSURE_SIZE - 2; breken; geval LPP_GYROMETER : len = LPP_GYROMETER_SIZE - 2; breken; geval LPP_GPS : len = LPP_GPS_SIZE - 2; breken; standaard: len = 0; } // ist der Kanal kein Aktuator, setzen wir im Nachrichtenbuffer neu auf 1 // damit die Daten bei nächster Gelegenheit an den MQTT Server gesendet werden als (!uitgang) berichten[kanaal].neu =1; berichten[kanaal].typ = typ; // Restpaket = 2 weniger da Kanal und Typ gelesen wurden pakketgrootte -= 2; #ifdef DEBUG Serie.afdrukken("Daten:"); #stop als // non lesen wir die empfangenen Daten mit der ermittelten Länge voor (uint8_t ik=0; ik<len; ik++) { dat = LoRa.lezen(); // für Aktuatoren merken wir uns keine Daten als (! uitgang) berichten[kanaal].daten[ik] = dat; #ifdef DEBUG Serie.printf("-% 02x",dat); #stop als // Restpaket um eins vermeldn pakketgrootte --; } #ifdef DEBUG Serie.println(); #stop als } // Status aktualisieren loraCnt++; loraLast = getLocalTime(); anzeige(); } anders { // Das Gerät ist nicht registriert // wir merken uns die Geräte-Id um sie für die Registriuerung anzuzeigen voor (uint8_t ik = 0; ik<6; ik++) onbetekenend[ik] = devid[ik]; neuesGeraet = waar; neuesGeraetTyp = 0; // LoRa Gerät } // Teil zwei Antwort an das LoRa Gerät senden vertraging(100); LoRa.beginPakket(); // ben Anfang die Geräte-Id LoRa.schrijven(devid,6); // wir prüfen ob wir Output Daten für das aktuelle LoRa-Gerät haben int devbase = devnr*16; voor (int ik = devbase; ik<devbase+8; ik++) { // je nach typ Digital oder Analogdaten schakelaar (berichten[ik].typ) { geval LPP_DIGITAL_OUTPUT : LoRa.schrijven(ik-devbase); LoRa.schrijven(berichten[ik].typ); LoRa.schrijven(berichten[ik].daten,1); #ifdef DEBUG Serie.println("Digital Ausgang"); #stop als breken; geval LPP_ANALOG_OUTPUT : LoRa.schrijven(ik-devbase); LoRa.schrijven(berichten[ik].typ); LoRa.schrijven(berichten[ik].daten,2); #ifdef DEBUG Serie.println("Analoge Ausgang"); #stop als breken; } } int lstatus = LoRa.endPacket(); #ifdef DEBUG Serie.afdrukken("Sendestatus ="); Serie.println(lstatus); #stop als } } // Funktion zum lesen der Konfiguration nietig configuratie configuratie(const char *fn) { uint8_t ik = 0; Draad tmp; char hex[3]; als (!SPIFFS.bestaat(fn)) { // existiert noch nicht dann erzeugen schreibe Configuratie(fn); terug; } het dossier f = SPIFFS.Open(fn, "r"); als (!f) { Serie.println(F("FOUT :: SPIFFS Kann Konfiguration nicht öffnen")); terug; } terwijl (f.beschikbaar() && (ik<MAXDEVICE)) { tmp = f.readStringUntil(','); apparaten[ik].aktiv = (tmp == "1"); tmp = f.readStringUntil(','); apparaten[ik].dienst = tmp.toInt(); tmp = f.readStringUntil(','); voor (uint8_t j=0; j<6; j++){ hex[0]=tmp[j*3]; hex[1]=tmp[j*3+1]; hex[2]=0; apparaten[ik].ID kaart[j]= (byte) strtol(hex,NUL,16); } tmp = f.readStringUntil(','); apparaten[ik].naam = tmp; tmp = f.readStringUntil(','); apparaten[ik].laatste = tmp; ik++; } } nietig opstelling() { // gerätespeicher initialisieren voor (uint8_t ik =0; ik<MAXDEVICE; ik++) apparaten[ik].aktiv = 0; // OLED Display initialisieren pinMode(16,UITGANG); digitalWrite(16, LAAG); vertraging(50); digitalWrite(16, HIGH); Scherm.in het(); Scherm.flipScreenVertically(); Scherm.setFont(ArialMT_Plain_10); Scherm.setText lijn ment(TEXT_ALIGN_LEFT); //Seriële interface start Seriële.beginnen(115200); terwijl (!Seriële); Seriële.println("Start",); //Flash-Bestand syastem als (SPIFFS.beginnen(FORMAT_SPIFFS_IF_FAILED)) Seriële.println(F("SPIFFS loaded")); //Lees configuratie lees configuratie("/de configuratie.csv"); init bericht buffer(); //SPI en LoRa initialiseren SPI.beginnen(5,19,27,18); LoRa.setPins(SS,EERSTE,DI0); Seriële.println("LoRa TRX"); als (!LoRa.beginnen(BAND)) { Seriële.println("Starten van LoRa is mislukt!"); terwijl (1); } LoRa.enableCrc(); Seriële.println("LoRa Eerste OK!"); vertraging(2000); //Met de Wi-Fi-en MQTT connect to Server Serial.. println("Wi-Fi"); Cayenne.beginnen(MQTT_USER, MQTT_PASSWORD, MQTT_CLIENTID, WIFI_SSID, WIFI_PASSWORD); Serieel.afdrukken("IP-adres: "); Seriële.println(WiFi.localIP()); //Web-Server initialiseren server.op("/", handvat root); server.starten(); //klok met tijd-server synchroniseren config tijd(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER); //de Stroom van de tijd-uitgang Seriële.println(getLocalTime()); } void loop() { display(); //LoRa Interface te controleren gegevens readLoRa(); //met Cayenne MQTT Server, en communiceren Cayenne.lus(1); //de Web Server, gebruik de server.het afhandelen van de client(); } //Gegevens van het bericht buffer om de MQTT Server te sturen CAYENNE_OUT_DEFAULT() { boolean - uitgang = op false; boolean sentData = , false; #ifdef DEBUG Serial.. println(getLocalTime()); Seriële.println("Cayenne verzenden"); #endif voor (int i = 0; i<MAXCHANNELS; ik++) { //alleen nieuwe berichten meer verzenden als (berichten die[ik].her - == 1) { #ifdef DEBUG Seriële.printf("Verzenden MQTT typt u %i\n",,berichten[ik].typ); #endif //afhankelijk van het type gegevens om te verzenden wisselen (berichten[ik].typ) { geval LPP_DIGITAL_INPUT : Cayenne.digitale sensor schrijf(ik,berichten[heb ik].gegevens[0]); breken; geval LPP_DIGITAL_OUTPUT : output = true; breken; //geval LPP_ANALOG_INPUT : Cayenne.virtuele schrijven(ik,(berichten[i].data[0]*256 + berichten[i].data[1])/100,"analog_sensor",UNIT_UNDEFINED); break; break; geval LPP_ANALOG_OUTPUT : output = true; breken; geval LPP_LUMINOSITY : Cayenne.luxWrite(ik,berichten[heb ik].de gegevens[0]*256 + van berichten[ik].gegevens[1]); breken; geval LPP_PRESENCE : Cayenne.digitale sensor schrijf(ik,berichten[heb ik].gegevens[0]); breken; geval LPP_TEMPERATURE : Cayenne.Celsius schrijf(ik,(berichten[heb ik].de gegevens[0]*256 + van berichten[ik].gegevens[1])/10); breken; geval LPP_RELATIVE_HUMIDITY : Cayenne.virtuele schrijf(ik,berichten[heb ik].gegevens[0]/2,TYPE_RELATIVE_HUMIDITY,UNIT_PERCENT); breken; geval LPP_ACCELEROMETER : Cayenne.virtuele schrijf(ik,(berichten[heb ik].de gegevens[0]*256 + van berichten[ik].gegevens[1])/1000,"gx","g"); break; geval LPP_BAROMETRIC_PRESSURE : Cayenne.hectopascal schrijf(ik,(berichten[heb ik].de gegevens[0]*256 + van berichten[ik].gegevens[1])/10); breken; //geval LPP_GYROMETER : len = LPP_GYROMETER_SIZE - 2; break; //geval LPP_GPS : len = LPP_GPS_SIZE - 2; break; } als (!output) { berichten[ik].opnieuw = 0; sentData = ware; } } } als (sentData) { //bijwerken Status cayCnt++; cayLast = getLocalTime(); display(); } } CAYENNE_IN_DEFAULT() { uint8_t * pData; , int val; , int ch, = aanvraag.kanaal; #ifdef DEBUG Serial.. println("Cayenne recive"); Seriële.printf("MQTT data voor kanaal %i = %d\n",,ch,getValue.asString()); #endif schakelaar (berichten[ch].type) { case LPP_DIGITAL_OUTPUT : berichten,[ch].gegevens[0] = getValue.asInt(); berichten[ch].nieuwe = 1; breken; geval LPP_ANALOG_OUTPUT : val = ronde(getValue.asDouble()*100); berichten,[ch].data -[0] = val / 256; berichten[ch].data -[1] = val % 256; berichten[ch].nieuw = 1; - einde; } }
3 Reacties
moi
für was genau ist der cayenne server zuständig?
kann ich auch einfach eine lokale ip eines mqtt servers eingeben und die pakete werden an diesen weiter geleitet?
Gerald Lechner
Hallo Marco
Ja du brauchst dafür einen zweiter ESP32 mit LoRa und im nächsten Teil folgt der notwendige Code.
Gruß Gerald
Marco
Hallo,
toller Artikel der Lust aufs Ausprobieren macht. Noch eine Frage. Ihr beschreibt hier das Gateway. Das “spricht” auf der einen Seite LoRa und auf der anderen Seite (via WLan) mit einem Netzwerk.
Ich bräuchte dann für die Kommunikation mittels LoRa dann noch einen zweiten ESP als Client, richtig? Könnt Ihr darüber vielleicht einen 4. Teil machen und erklären wie man dann damit ein Ende-Ende Szenario aufbaut?
Viele Grüße
Marco