Después de algunos intentos fallidos de construir una puerta de enlace universal LoRa con el ESP32, se creó la siguiente puerta de enlace patentada, que permite que los dispositivos IoT basados en LoRa se conecten al Tablero Cayenne a través de MQTT. En una versión ampliada, la puerta de enlace también administrará dispositivos IoT basados en el protocolo ESP-Now.
Solo necesitamos uno para la puerta de enlace ESP32 con pantalla LoRa y OLEDNo se requieren más componentes. La fuente de alimentación se puede hacer con cualquier fuente de alimentación USB.
Descripción de la función:
La puerta de enlace puede administrar 32 dispositivos con hasta 8 canales cada uno. La transmisión de datos es asíncrona. Cuando la puerta de enlace recibe un paquete de datos LoRa, los primeros seis bytes se interpretan como ID del dispositivo (generalmente la dirección MAC). La puerta de enlace comprueba en una lista de dispositivos si este dispositivo ya está registrado. Si este no es el caso, la ID del dispositivo se guarda y se muestra a través de la interfaz web para el registro.
Si el dispositivo ya está registrado, los datos se leen y se guardan en un búfer de mensajes para cada canal. El número de canal se determina a partir del número de dispositivo (índice en la lista de dispositivos) * 8 + número de canal de los datos recibidos. El dispositivo 0 tiene los canales 0 a 7, el dispositivo 1 tiene los canales 8 a 15, etc.
Un registro de datos comienza con un byte para el número de canal seguido de un byte con el tipo y luego de 1 a 6 bytes de datos según el tipo. Después de que todos los datos se hayan guardado en el búfer de mensajes y se hayan marcado como nuevos, el paquete de respuesta se agrupa en el dispositivo Lora. Comienza de nuevo con los seis bytes de ID del dispositivo. Los canales para este dispositivo se verifican en el búfer de mensajes para determinar si hay un paquete de datos salientes de Cayenne al dispositivo que está marcado con Nuevo. Si se encuentra dicho paquete de datos, se agrega al paquete de respuesta, y el número de canal relativo 0 a 7 se usa nuevamente. Como último paso, el paquete de respuesta se transfiere al dispositivo LoRa.
La función Cayenne.loop (1) se hace cargo de la comunicación con el servidor IoT. En la función de devolución de llamada CAYENNE_OUT_DEFAULT (), se buscan todos los canales en el búfer de mensajes que están marcados con Nuevo y que contienen un paquete de datos de entrada para Cayenne del tipo. Estos paquetes ahora se convierten según el tipo y se envían al servidor IoT. Después de una transferencia exitosa, la nueva bandera se reinicia.
Se llama a una segunda función de devolución de llamada CAYENNE_IN_DEFAULT () siempre que haya datos de Cayenne para un canal de acción. Los datos del servidor IoT se convierten según el tipo y se almacenan en el búfer de mensajes. Están marcados con Nuevo para que se envíen al dispositivo la próxima vez que LoRa se comunique con el paquete de respuesta.
Pantalla:
Además del nombre, la pantalla muestra la fecha y hora actuales. Debajo de eso la dirección IP.
La línea MQTT: muestra el número de transferencias exitosas al servidor IoT, LoRa las transferencias exitosas a dispositivos LoRa y AHORA el número de transferencias exitosas a dispositivos ESP-Now. Actualmente, este último siempre es 0 porque esta función aún no se ha implementado.
Lista de dispositivos y registro:
La lista de dispositivos se guarda como un archivo CSV en el sistema de archivos flash (SPIFFS) para que se conserve incluso si no hay una fuente de alimentación. Esta lista se puede mantener a través del servidor web integrado en la puerta de enlace. Se pueden eliminar dispositivos y registrar nuevos dispositivos.
Paquetes de datos:
Para el tipo, los códigos están de acuerdo con las pautas de IPSO Alliance Smart Objects, pero se resta 3200.
Tipo | IPSO | TypNr. | Bytes | Disolución |
Entrada digital | 3200 | 0 | 1 | 1 |
Salida digital | 3201 | 1 | 1 | 1 |
Entrada analógica | 3202 | 2 | 2 | 0.01 con signo |
Salida analógica | 3203 | 3 | 2 | 0.01 con signo |
Sensor de iluminación | 3301 | 101 | 2 | 1 lux |
Sensor de presencia | 3302 | 102 | 1 | 1 |
Sensor de temperatura | 3303 | 103 | 2 | 0.1°C con el signo |
Sensor húmedo | 3304 | 104 | 1 | 0.5% |
Beschleunigungs el sensor | 3313 | 113 | 6 | 0.001 gr con el signo para eje X, Y y Z |
Presión el sensor | 3315 | 115 | 2 | 0.1 hPa |
Gyrometer | 3334 | 134 | 6 | 0.01% / s con el signo para eje X, Y y Z |
GPS Posición | 3336 | 136 | 9 | Grado de latitud 0.0001 ° con el signo Grado de longitud 0.0001 ° con el signo Altura 0.01 m con el signo |
Sketch:
El registro de la esclusa en Cayenne sucede a la manera misma como en la parte 1 este Blog la serie describían. Luego los datos de acceso tienen que ser dados en el sketch (la señalización amarilla) igualmente los datos de acceso para anunciar en WLAN local. Cayenne Dashboard no indicará ningunos Widgets, dado que todavía ningún utensilio era conectado con la esclusa.
Board para Arduino IDE = TTGO LoRa32-OLED V1
/* La esclusa MQTT forma una interfaz entre LoRa a utensilios y respectivamente utensilios ESP Nowe * y Cayenne MQTT Dashboards. Esto corre en ESP32 con LoRa y display OLED * La configuración sucede del navegador */ #include <SPI.h> #include <LoRa.h> #include "SSD1306.h" #include<Arduino.h> #include <CayenneMQTTESP32.h> #include <CayenneLPP.h> #include <WiFi.h> #include <Servidor de Web.h> #include <time.h> #include "FS.h" #include "SPIFFS.h" //Recibimos los datos para este ajuste de Cayenne Dashboard #define MQTT_USER "" #define MQTT_PASSWORD "" #define MQTT_CLIENTID "" //Datos de acceso para WLAN local #define WIFI_SSID "" #define WIFI_PASSWORD "" //Servidor NTP a la sincronización de tiempo #define NTP_SERVER "de.pool.ntp.org" #define GMT_OFFSET_SEC 3600 #define DAYLIGHT_OFFSET_SEC 0 //Pins para LoRa el chip #define SS 18 #define RST 14 #define DI0 26 //Frecuencia para LoRa el chip #define CINTA 433175000 // #define MAXCHANNELS 256 //número máximo de los canales administrados #define MAXDEVICE 32 //el número máximo de los utensilios administrados MAXCHANNELS/MAXDEVICE = 8 revela el número máximo canales por utensilio //El formato Flash el sistema de file si aún no ocurren #define FORMAT_SPIFFS_IF_FAILED true #define DEBUG 1 //Piedras de construcción para el servidor de Web const char HTML_HEADER[] = "<!DOCTYPE HTML>" "<html>" "<head>" "<meta el nombre = \"viewport \" content = \"width = device-width, inicial scale = 1.0, maximum-scale = 1.0, user-scalable=0> \">" "<meta http-equiv = \"content-type \" content = \"el texto / html; charset=UTF-8 \">" "<title>MQTT Gateway</title>" "<script language = \"javascript \">" "function reload () {" "document.location = \"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:lighter;font-size:10pt;}" "table, th, td {border: 1px px solid black;}" ".titel {font-size:18pt;font-weight:bold;text-align:center;}" "</style>" "</head>" "<body><div da estilo ='margin-left:30px; '>"; const char HTML_END[] = "</div><script language = \"javascript \">setTimeout (reload, 10000) ;</script></body>" "</html>"; const char HTML_TAB_GERAETE[] = "<table da estilo = \"width:100 % \"><tr><th da estilo = \"width:20 % \">ID</th><th da estilo = \"width:10 % \">Nr.</th>" "<th da estilo = \"width:20 % \">Kanäle</th><th da estilo = \"width:20 % \">Name</th>" "<th da estilo = \"width:20 % \">Letzte Daten</th><th da estilo = \"width:10 % \">Aktion</th></tr>"; const char HTML_TAB_END[] = "</table>"; const char HTML_NEWDEVICE[] = "<div da estilo = \"margin-top:20px; \">%s el nombre: <input type = \"el texto \"" el nombre = \"devname \" maxlength = \"da estilo = \"width:200px \a 10 \" value = \"\" > <button el nombre = \"registra \" value = \"% s \">Registrieren</button></div>"; const char HTML_TAB_ZEILE[] = "<tr><td>%s</td><td>%i</td><td>%i hasta %i</td><td>%s</td><td>%s</td><td><button el nombre = \"delete \" value = \"% i \">Löschen</button></td></tr>"; //Estructuras de datos //Noticias el tope struct MSG_BUF { uint8_t tipo; uint8_t de nuevo; uint8_t datos[10]; }; //Definición de utensilios struct DEVICE { uint8_t activamente; uint8_t sirves; //0=LoRa, 1=ESP-Now uint8_t id[6]; Bramante nombre; Bramante leía; }; //Variables globales //Servidor de Web la instancia Servidor de Web servidor(80); //Display OLED SSD1306 display(0x3c, 4, 15); //Tope al interalmacén de las noticias para canal MSG_BUF mensajes[MAXCHANNELS]; //Lista de los utensilios definidos DEVICE devices[MAXDEVICE]; //Id de un utensilio no registrado uint8_t desconocido[6]; //Flag siempre luego verdadero cuando un nuevo utensilio era descubierto boolean un nuevo utensilio = false; //Tipo del nuevo utensilio 0=LöRa 1 =ESPNow uint8_t neuesGeraetTyp = 0; //Contador y Aktivitaets el estatus para el display uint32_t loraCnt = 0; //Número de LoRa recibidos noticias Bramante loraLast = ""; //Fecha y tiempo de últimos LoRa recibidos la noticia uint32_t nowCnt = 0; //Número de las noticias ESP Now recibidas Bramante nowLast = ""; //Fecha y tiempo de últimos LoRa recibidos la noticia uint32_t cayCnt = 0; //Número de las noticias MQTT enviadas Bramante cayLast = ""; //Fecha y tiempo de la última noticia MQTT enviada //La función entrega la fecha y hora en el formato el yyyy el mm dd hh:mm:ss como bramante Bramante getLocalTime() { char sttime[20] = ""; struct tm timeinfo; if(!getLocalTime(&timeinfo)){ Serial.println("Failed to obtain time"); return sttime; } strftime(sttime, sizeof(sttime), "%Y-%m-%d %H:%M:%S", &timeinfo); return sttime; } //La función entrega 6 bytes de Geräte-Id en el formato xx:xx:xx:xx:xx:xx como bramante Bramante getId(uint8_t id[6]) { Bramante stid; char tmp[4]; sprintf(tmp,"x",id[0]); stid=tmp; for (uint8_t j = 1; j<6; j++) { sprintf(tmp,": x",id[j]); stid = stid += tmp ; } return stid; } //prepara el tope de noticias //pone todas las noticias en acaba void initMessageBuffer() { for (int i = 0;i<MAXCHANNELS;i++) mensajes[i].de nuevo = 0; } //Función al almacén de la configuración void schreibeKonfiguration(const char *fn) { File f = SPIFFS.open(fn, FILE_WRITE); if (!f) { Serial.println(F("ERROR: SPIFFS los puede la configuración no guardan")); return; } for (uint8_t i = 0; i<MAXDEVICE; i++) { f.print(devices[i].activamente);f.print(","); f.print(devices[i].sirves);f.print(","); f.print(getId(devices[i].id));f.print(","); f.print(devices[i].nombre);f.print(","); f.println(devices[i].leía); } } //Función para registrar un nuevo utensilio void geraetRegistrieren() { uint8_t i = 0; //busca la inscripción libre while ((i<MAXDEVICE) && devices[i].activamente) i++; //si no hay ninguna nueva inscripción no hacemos nada if (i < MAXDEVICE) { //además el utensilio registran el nombre = el nombre dado //o desconocido si nadie era dado if (servidor.hasArg("devname")) { devices[i].nombre = servidor.mucho("devname"); } else { devices[i].nombre = "desconocido"; } for (uint8_t j = 0; j<6; j++) devices[i].id[j]=desconocido[j]; devices[i].activamente = 1; devices[i].sirves= neuesGeraetTyp; devices[i].leía = ""; schreibeKonfiguration("/konfiguration.csv"); un nuevo utensilio = false; } } //El servicio la función de la Web del servidor void handleRoot() { char htmlbuf[1024]; char tmp1[20]; char tmp2[20]; char tmp3[20]; int índice; //¿el apaga el botón era hecho clic? if (servidor.hasArg("delete")) { índice = servidor.mucho("delete").toInt(); #ifdef DEGUG Serial.printf("Lösche device %i =",índice); Serial.println(devices[índice].nombre); #endif devices[índice].activamente=0; schreibeKonfiguration("/konfiguration.csv"); } //¿el registrar el botón era hecho clic? if (servidor.hasArg("registrar")) { geraetRegistrieren(); } //Envían el HTML actual al lado al navegador servidor.setContentLength(CONTENT_LENGTH_UNKNOWN); //Header WiFi.localIP().toString().toCharArray(tmp1,20); sprintf(htmlbuf,HTML_HEADER,tmp1); servidor.envía(200, "texto / html",htmlbuf); //Formulario el principio servidor.sendContent("<div class = \"el título \">MQTT - Gateway</div><form>"); //Tabla de los utensilios activos servidor.sendContent(HTML_TAB_GERAETE); for (uint8_t i = 0; i<MAXDEVICE; i++) { if (devices[i].activamente == 1) { getId(devices[i].id).toCharArray(tmp1,20); devices[i].nombre.toCharArray(tmp2,20); devices[i].leía.toCharArray(tmp3,20); sprintf(htmlbuf,HTML_TAB_ZEILE,tmp1,i,i*8,i*8+7,tmp2,tmp3,i); servidor.sendContent(htmlbuf); } } servidor.sendContent(HTML_TAB_END); //En caso de que un nuevo utensilio fuera encontrado sus ID así como un campo de entrada se hacen para el nombre //y un botón para registrar el nuevo utensilio indicado if (un nuevo utensilio) { getId(desconocido).toCharArray(tmp1,20); sprintf(htmlbuf,HTML_NEWDEVICE,tmp1,tmp1); servidor.sendContent(htmlbuf); } servidor.sendContent(HTML_END); } //Función a la busca de un utensilio en la lista de utensilios //La devolución el índice del utensilio o-1 si no era encontrado int findDevice(uint8_t dev[6]) { uint8_t j; uint8_t i = 0; boolean found = false; do { j = 0; if (devices[i].activamente == 0) { i++; } else { while ((j < 6) && (dev[j] == devices[i].id[j])) {j++;} found = (j == 6); if (!found) i++; } } while ((i<MAXDEVICE) && (!found)); if (found) {return i;} else {return -1;} } //Función al anuncio del estatus en el display OLED void indica() { display.clear(); display.drawString(0,0,"La esclusa MQTT"); display.drawString(0,10,getLocalTime()); display.drawString(0,20,WiFi.localIP().toString()); display.drawString(0,34,"MQTT:"); display.drawString(60,34,Bramante(cayCnt)); display.drawString(0,44,"LoRa:"); display.drawString(60,44,Bramante(loraCnt)); display.drawString(0,54,"NOW:"); display.drawString(60,54,Bramante(nowCnt)); display.display(); } //Tratan una noticia de LoRa el cliente void readLoRa() { int devnr; uint8_t devid[6]; uint8_t canal; uint8_t tipo; uint8_t len; uint8_t dat; boolean producción total; //Datos van a buscar disponible en caso de que int packetSize = LoRa.parsePacket(); //¿hemos recibido datos? if (packetSize > 5) { #ifdef DEBUG Serial.println(getLocalTime()); Serial.print("RX"); Serial.print(packetSize); Serial.println("Bytes"); Serial.print("Device ID"); #endif //al principio Geräte-Id leen for (uint8_t i=0; i<6;i++){ devid[i]=LoRa.read(); #ifdef DEBUG Serial.printf("- x",devid[i]); #endif } #ifdef DEBUG Serial.println(); #endif //Calculan el paquete de resto packetSize -= 6; //revisan si el utensilio está registrado devnr = findDevice(devid); if (devnr >= 0) { //si ponemos el sello de tiempo para el último mensaje y //si leen los datos devices[devnr].leía = getLocalTime(); schreibeKonfiguration("/konfiguration.csv"); while (packetSize > 0) { //Número de canal = el número de utensilios * 16 canales de utensilios canal = LoRa.read() + devnr*16; #ifdef DEBUG Serial.printf("El canal: x",canal); #endif //tipo del canal tipo = LoRa.read(); #ifdef DEBUG Serial.printf("El tipo: x",tipo); #endif //instruyen a la longitud del paquete de datos y si el canal es Aktuator producción total = false; switch(tipo) { case LPP_DIGITAL_INPUT : len = LPP_DIGITAL_INPUT_SIZE - 2; break; case LPP_DIGITAL_OUTPUT : len = LPP_DIGITAL_OUTPUT_SIZE - 2; salida = cierto; descanso; caso LPP_ANALOG_INPUT : Len = LPP_ANALOG_INPUT_SIZE - 2; descanso; caso LPP_ANALOG_OUTPUT : Len = LPP_ANALOG_OUTPUT_SIZE - 2; salida = cierto; descanso; caso LPP_LUMINOSITY : Len = LPP_LUMINOSITY_SIZE - 2; descanso; caso LPP_PRESENCE : Len = LPP_PRESENCE_SIZE - 2; descanso; caso LPP_TEMPERATURE : Len = LPP_TEMPERATURE_SIZE - 2; descanso; caso LPP_HUMIDIDAD_RELATIVA : Len = LPP_RELATIVE_HUMIDITY_SIZE - 2; descanso; caso LPP_ACCELEROMETER : Len = LPP_ACCELEROMETER_SIZE - 2; descanso; caso LPP_BAROMETRIC_PRESSURE : Len = LPP_BAROMETRIC_PRESSURE_SIZE - 2; descanso; caso LPP_GYROMETER : Len = LPP_GYROMETER_SIZE - 2; descanso; caso LPP_GPS : Len = LPP_GPS_SIZE - 2; descanso; defecto: 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 Si (!salida) mensajes[canal].neu =1; mensajes[canal].Typ = Typ; // Restpaket = 2 weniger da Kanal und Typ gelesen wurden tamaño del paquete -= 2; #ifdef DEPURAR De serie.impresión("Daten:"); #terminara si // nun lesen wir die empfangenen Daten mit der ermittelten Länge para (uint8_t yo=0; yo<Len; yo++) { dat = LoRa.leer(); // für Aktuatoren merken wir uns keine Daten Si (! salida) mensajes[canal].daten[yo] = dat; #ifdef DEPURAR De serie.printf("-% 02x",dat); #terminara si // Restpaket um eins vermindern tamaño del paquete --; } #ifdef DEPURAR De serie.println(); #terminara si } // Status aktualisieren loraCnt++; loraÚltimo = getLocalTime(); anzeige(); } más { // Das Gerät ist nicht registriert // wir merken uns die Geräte-Id um sie für die Registriuerung anzuzeigen para (uint8_t yo = 0; yo<6; yo++) unbekannt[yo] = devid[yo]; neuesGeraet = cierto; neuesGeraetTyp = 0; // LoRa Gerät } // Teil zwei Antwort an das LoRa Gerät senden retrasar(100); LoRa.beginPacket(); // soy Anfang die Geräte-Id LoRa.escribir(devid,6); // wir prüfen ob wir Salida Daten für das aktuelle LoRa-Gerät haben En t devbase = devnr*16; para (En t yo = devbase; yo<devbase+8; yo++) { // je nach typ Digital oder Analogdaten cambiar (mensajes[yo].Typ) { caso LPP_DIGITAL_OUTPUT : LoRa.escribir(yo-devbase); LoRa.escribir(mensajes[yo].Typ); LoRa.escribir(mensajes[yo].daten,1); #ifdef DEPURAR De serie.println("Ausgang digital"); #terminara si descanso; caso LPP_ANALOG_OUTPUT : LoRa.escribir(yo-devbase); LoRa.escribir(mensajes[yo].Typ); LoRa.escribir(mensajes[yo].daten,2); #ifdef DEPURAR De serie.println("Ausgang analógico"); #terminara si descanso; } } En t lstatus = LoRa.endPacket(); #ifdef DEPURAR De serie.impresión("Sendestatus ="); De serie.println(lstatus); #terminara si } } // Funktion zum lesen der Konfiguration vacío leseKonfiguration(const carbonizarse *fn) { uint8_t yo = 0; Cuerda tmp; carbonizarse maleficio[3]; Si (!SPIFFS.existe(fn)) { // existiert noch nicht dann erzeugen schreibeKonfiguration(fn); regreso; } Archivo F = SPIFFS.abierto(fn, "r"); Si (!F) { De serie.println(F("ERROR :: SPIFFS Kann Konfiguration nicht öffnen")); regreso; } mientras (F.disponible() && (yo<MAXDEVICE)) { tmp = F.readStringUntil(','); dispositivos[yo].aktiv = (tmp == "1"); tmp = F.readStringUntil(','); dispositivos[yo].dienst = tmp.toInt(); tmp = F.readStringUntil(','); para (uint8_t j=0; j<6; j++){ maleficio[0]=tmp[j*3]; maleficio[1]=tmp[j*3+1]; maleficio[2]=0; dispositivos[yo].carné de identidad[j]= (byte) strtol(maleficio,NULO,16); } tmp = F.readStringUntil(','); dispositivos[yo].nombre = tmp; tmp = F.readStringUntil(','); dispositivos[yo].último = tmp; yo++; } } vacío preparar() { // gerätespeicher initialisieren para (uint8_t yo =0; yo<MAXDEVICE; yo++) dispositivos[yo].aktiv = 0; // Pantalla OLED initialisieren pinMode(16,SALIDA); digitalWrite(16, BAJO); retrasar(50); digitalWrite(16, ALTO); monitor.en eso(); monitor.flipScreenVertically(); monitor.setFont(ArialMT_Plain_10); monitor.setTextAlignment(TEXT_ALIGN_LEFT); //Lanzan la interface en serie Serial.begin(115200); while (!Serial); Serial.println("Salida"); //Flash el file syastem if (SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) Serial.println(F("SPIFFS de modo cargado")); //Configuración einlesen configuración de vendimia("/konfiguration.csv"); initMessageBuffer(); //SPI y LoRa inicializan SPI.begin(5,19,27,18); LoRa.setPins(SS,RST,DI0); Serial.println("LoRa TRX"); if (!LoRa.begin(CINTA)) { Serial.println("¡Starting LoRa failed!"); while (1); } LoRa.enableCrc(); Serial.println("¡LoRa Inicialmente el OKEY!"); delay(2000); //Ligan con WLAN y servidor MQTT Serial.println("WLAN ligan"); Cayenne.begin(MQTT_USER, MQTT_PASSWORD, MQTT_CLIENTID, WIFI_SSID, WIFI_PASSWORD); Serial.print("IP address:"); Serial.println(WiFi.localIP()); //La Web servidores inicializan servidor.on("/", handleRoot); servidor.begin(); //La hora sincronizan el servidor de tiempo configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER); //Distribuyen hora actual Serial.println(getLocalTime()); } void loop() { indica(); //Examinan LoRa la interfaz en datos readLoRa(); //con Cayenne MQTT servidores comunican Cayenne.loop(1); //La Web servidores sirven servidor.handleClient(); } //Datos del tope de noticias envían al servidor MQTT CAYENNE_OUT_DEFAULT() { boolean producción total = false; boolean sentData = false; #ifdef DEBUG Serial.println(getLocalTime()); Serial.println("Cayenne envía"); #endif for (int i = 0; i<MAXCHANNELS; i++) { //noticias sólo nuevas envían if (mensajes[i].de nuevo == 1) { #ifdef DEBUG Serial.printf("Sende MQTT Typ %i\n",mensajes[i].tipo); #endif //según el tipo Datos envían switch (mensajes[i].tipo) { case LPP_DIGITAL_INPUT : Cayenne.digitalSensorWrite(i,mensajes[i].datos[0]); break; case LPP_DIGITAL_OUTPUT : producción total = true; break; //case LPP_ANALOG_INPUT: Cayenne.virtualWrite (i, (mensajes [i].daten [0] *256 mensajes [i].daten [1])/100, "analog_sensor", UNIT_UNDEFINED); break; break; case LPP_ANALOG_OUTPUT : producción total = true; break; case LPP_LUMINOSITY : Cayenne.luxWrite(i,mensajes[i].datos[0]*256 + mensajes[i].datos[1]); break; case LPP_PRESENCE : Cayenne.digitalSensorWrite(i,mensajes[i].datos[0]); break; case LPP_TEMPERATURE : Cayenne.celsiusWrite(i,(mensajes[i].datos[0]*256 + mensajes[i].datos[1])/10); break; case LPP_RELATIVE_HUMIDITY : Cayenne.virtualWrite(i,mensajes[i].datos[0]/2,TYPE_RELATIVE_HUMIDITY,UNIT_PERCENT); break; case LPP_ACCELEROMETER : Cayenne.virtualWrite(i,(mensajes[i].datos[0]*256 + mensajes[i].datos[1])/1000,"gx","g"); break; case LPP_BAROMETRIC_PRESSURE : Cayenne.hectoPascalWrite(i,(mensajes[i].datos[0]*256 + mensajes[i].datos[1])/10); break; //case LPP_GYROMETER: len = LPP_GYROMETER_SIZE - 2; break; //case LPP_GPS: len = LPP_GPS_SIZE - 2; break; } if (!producción total) { mensajes[i].de nuevo = 0; sentData = true; } } } if (sentData) { //Actualizan el estatus cayCnt++; cayLast = getLocalTime(); indica(); } } CAYENNE_IN_DEFAULT() { uint8_t * pData; int val; int ch = request.canal; #ifdef DEBUG Serial.println("Cayenne recive"); Serial.printf("Datos MQTT para el canal %i = %s\n",ch,getValue.asString()); #endif switch (mensajes[ch].tipo) { case LPP_DIGITAL_OUTPUT : mensajes[ch].datos[0] = getValue.asInt(); mensajes[ch].de nuevo = 1; break; case LPP_ANALOG_OUTPUT : val = round(getValue.asDouble()*100); mensajes[ch].datos[0] = val / 256; mensajes[ch].datos[1] = val % 256; mensajes[ch].de nuevo = 1; break; } }
3 comentarios
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