1. Instrucciones en Arduino IDE
Para el envío de los mensajes hacia el broker MQTT y Home Assistant se usa un dispositivo configurado como gateway.
Se usa un dispositivo en lugar de un concentrador en la etapa de prototipo considerando los costos involucrados. La próxima tarea es desarrollar el gateway usando un concentrador, cuyo valor es más alto.
/* Gateway LoRa Lora/Wifi/MQTT/Home-Assistant Envia información por red Lora/Gateway WiFi hacia un broker MQTT y gestionar datos en Home-Assistant edelros@espol.edu.ec http://blog.espol.edu.ec/edelros/ Referencia: Aaron.Lee www.heltec.cn https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series */ #include "heltec.h" #include <WiFi.h> #include <PubSubClient.h> // DISPOSITIVO LORA Banda ISM en Región 915Mhz #define BAND 915E6 //433E6,868E6,915E6 // ranges from 6-12,default 7 see API docs byte spread_factor = 8; // LoRa Mensaje a enviar por direcciones String paqueteEnv = ""; byte dir_local = 0xC1; // Concentrador 1 byte dir_destino = 0xD1; // Dispositivo 1 byte msjContador = 0; // identificador de mensaje // tiempo entre lecturas long t_anterior = 0; int t_intervalo = 4000; // LoRa Mensaje Recibido byte dir_envio = 0xC1; // Concentrador 1 int dir_remite = 0xD0; // Inicia Remitente String paqueteRcb = ""; byte paqrcbID = 0; byte paqrcbEstado = 0; // 0:vacio, 1: nuevo, 2:incompleto // 3:otro destinatario, 4:Broadcast // Mensajes por Puerto Serial volatile boolean serial_msj = true; // WIFI: conexión a Router char* ssid = "giotirni20"; char* password = "Anera2020@"; // MQTT: Servidor char* MQTT_IP = "192.168.10.50"; uint16_t MQTT_puerto = 1883; char* MQTT_usuario = "usuarioprueba"; char* MQTT_contrasena = "usuarioclave"; // MQTT: Dispositivo Sensor char* MQTT_ID = "LoraGatewayC1"; char MQTT_TOPIC_T[50] = "invernadero/loraD1/temperatura"; char MQTT_TOPIC_H[50] = "invernadero/loraD1/humedad"; char MQTT_TOPIC_V[50] = "invernadero/loraD1/voltaje"; char MQTT_SensorEstado[10] = "OFF"; volatile boolean mqtt_desconectado = true; // MQTT: Dispositivo Actuador char* MQTT_COMMAND = "invernadero/loraD1/cambia"; char MQTT_ActuadorEstado[10] = "OFF"; volatile boolean actuador_estado = false; volatile boolean actuador_bandera = false; char temperatura[10] = "00.00"; char humedad[10] = "00.00"; char voltaje[10] = "00.00"; // Clientes WiFi y MQTT WiFiClient wificlient; PubSubClient mqttclient(wificlient); void setup(){ Heltec.begin(false /*DisplayEnable Enable*/, true /*Heltec.Heltec.Heltec.LoRa Disable*/, serial_msj /*Serial Enable*/, true /*PABOOST Enable*/, BAND /*long BAND*/); // ranges from 6-12,default 7 see API docs LoRa.setSpreadingFactor(spread_factor); //LoRa.onReceive(cbk); LoRa.receive(); // conexión WIFI y MQTT inicia_wifi(); if (WiFi.status() == WL_CONNECTED){ inicia_mqtt(); } } void loop(){ // parametros de recepción int rssi_lora = 0; int snr_lora = 0; // Revisa mensajes LoRa entrantes int msjRcbLoRa = LoRa.parsePacket(); if (msjRcbLoRa !=0){ recibirlora(msjRcbLoRa); rssi_lora = LoRa.packetRssi(); snr_lora = LoRa.packetSnr(); if (serial_msj==true){ Serial.println("remite,msjID,mensaje,estado,Rssi,Snr"); Serial.print(String(dir_remite, HEX)); Serial.print(","); Serial.print(paqrcbID); Serial.print(","); Serial.print(paqueteRcb); Serial.print(","); Serial.print(paqrcbEstado); Serial.print(","); Serial.print(rssi_lora); Serial.print(","); Serial.println(snr_lora); } yield(); // procesa wifi // LED parpadea Rebibido Lora digitalWrite(LED, HIGH); delay(50); digitalWrite(LED, LOW); delay(50); digitalWrite(LED, HIGH); delay(50); digitalWrite(LED, LOW); yield(); // procesa wifi delay(100); } // Procesa a MQTT mensaje completo if (msjRcbLoRa !=0 && paqrcbEstado == 1){ // Separa parámetros String t = paqueteRcb.substring(1,6); String h = paqueteRcb.substring(8,10); String v = paqueteRcb.substring(12); // procesa tópico MQTT // añade dispositivo String topico = "invernadero/lora"; String remite = String(dir_remite, HEX); remite.toUpperCase(); topico = topico + remite; // procesa topico String topicot = topico + "/temperatura"; String topicoh = topico + "/humedad"; String topicov = topico + "/voltaje"; topicot.toCharArray(MQTT_TOPIC_T,topicot.length()+1); topicoh.toCharArray(MQTT_TOPIC_H,topicoh.length()+1); topicov.toCharArray(MQTT_TOPIC_V,topicov.length()+1); t.toCharArray(temperatura,t.length()+1); h.toCharArray(humedad,h.length()+1); v.toCharArray(voltaje,v.length()+1); Serial.println(topicov); publica_estado(); } yield(); // procesa wifi delay(20); // reenviar a dispositivo if (actuador_bandera == true){ msjContador = msjContador +1; enviarlora(dir_destino, dir_local, msjContador, paqueteEnv); actuador_bandera = false; } yield(); // procesa wifi delay(20); if (WiFi.status() != WL_CONNECTED){ inicia_wifi(); }else{ if (mqttclient.connected()==false){ mqtt_desconectado = true; inicia_mqtt(); // reintento } if (mqttclient.connected()==true){ if (mqtt_desconectado==true){ publica_estado(); mqtt_desconectado=false; } mqttclient.loop(); } } yield(); // procesa wifi } void enviarlora(byte destino, byte remite, byte paqueteID, String paquete){ // espera que el radio esté listo // para enviar un paquete while(LoRa.beginPacket() == 0){ if (serial_msj==true){ Serial.println("Esperando radio disponible..."); } yield(); // procesa wifi delay(100); } // envio del mensaje LoRa LoRa.beginPacket(); LoRa.write(destino); LoRa.write(remite); LoRa.write(paqueteID); LoRa.write(paquete.length()); LoRa.print(paquete); LoRa.endPacket(); } void recibirlora(int tamano){ if (tamano == 0){ paqrcbEstado = 0; //vacio return; } // lectura de paquete paqueteRcb = ""; dir_envio = LoRa.read(); dir_remite = LoRa.read(); paqrcbID = LoRa.read(); byte paqrcbTamano = LoRa.read(); while(LoRa.available()){ paqueteRcb += (char)LoRa.read(); } if (paqrcbTamano != paqueteRcb.length()){ paqrcbEstado = 2; // Tamaño incompleto return; } if (dir_envio != dir_local){ paqrcbEstado = 3; // otro destino return; } if (dir_envio == 0xFF) { paqrcbEstado = 4; // Broadcast return; } paqrcbEstado = 1; // mensaje Nuevo } void inicia_mqtt(void){ int intentosmqtt = 5; int cuentamqtt = 0; if (serial_msj){ Serial.print(" MQTT Conectando a "); Serial.println(MQTT_IP); } mqttclient.setServer(MQTT_IP, MQTT_puerto); mqttclient.connect(MQTT_ID, MQTT_usuario, MQTT_contrasena); mqttclient.setCallback(recibirmqtt); while (!mqttclient.connected() && (cuentamqtt<=intentosmqtt)){ if (serial_msj){ Serial.print("."); } cuentamqtt = cuentamqtt + 1; // LED Monitor parpadeo MQTT digitalWrite(LED, HIGH); delay(200); digitalWrite(LED, LOW); delay(200); } if (mqttclient.connected()){ publica_estado(); } if (serial_msj){ //Fin de "...." Serial.println(); Serial.print(" MQTT Conectado: "); Serial.print(mqttclient.connected()); Serial.print("\t MQTT Estado: "); Serial.println(mqttclient.state()); } } void publica_estado() { if (mqttclient.connected()==true){ mqttclient.publish(MQTT_TOPIC_T,temperatura,true); mqttclient.publish(MQTT_TOPIC_H,humedad,true); mqttclient.publish(MQTT_TOPIC_V,voltaje,true); mqttclient.subscribe(MQTT_COMMAND); }else{ mqtt_desconectado = true; } } // llega mensaje MQTT, callback mqtt void recibirmqtt(char* p_topic, byte* p_payload, unsigned int p_length) { Serial.println("un mensaje mqtt"); Serial.println(p_topic); // convierte a texto String payload; for (uint8_t i = 0; i < p_length; i++) { payload.concat((char)p_payload[i]); } // String dispositivo = p_topic[16] + String(p_topic[17]); char dispositivo[3] = "D0"; dispositivo[1]=p_topic[17]; dir_destino = (int) strtol(dispositivo,NULL,16); paqueteEnv = payload; actuador_bandera = true; if (mqttclient.connected()==true){ mqttclient.subscribe(MQTT_COMMAND); }else{ mqtt_desconectado = true; } } void inicia_wifi(void) { int intentoswifi = 10; int cuentawifi = 0; if (serial_msj){ Serial.print(" WiFi Conectando a "); Serial.println(ssid); } WiFi.disconnect(true); delay(1000); WiFi.mode(WIFI_STA); WiFi.setAutoConnect(true); WiFi.begin(ssid,password); delay(100); while(WiFi.status() != WL_CONNECTED && cuentawifi < intentoswifi){ if (serial_msj){ Serial.print("."); } cuentawifi = cuentawifi + 1; // Parpadeo de Monitor Wifi digitalWrite(LED, HIGH);delay(300); digitalWrite(LED, LOW);delay(200); } if (serial_msj){ // mensaje a serial Serial.println(); if (WiFi.status() == WL_CONNECTED){ Serial.print(" Estado: "); Serial.println(WiFi.status()); Serial.print(" MAC: "); Serial.println(WiFi.macAddress()); Serial.print(" IP: "); Serial.println(WiFi.localIP()); Serial.print(" RSSI: "); Serial.println(WiFi.RSSI()); Serial.println(); } if (WiFi.status() != WL_CONNECTED){ WiFi.printDiag(Serial); Serial.println(); } } }