FORUM

MQTT losing connection

I’m working on a Lora system, I have a sending unit using a Sparkfun Firebeetle with a BME280 sensor. That sends the values to a the base unit in my house using a ESP32 Dev module. That part is working fine. I’ve now added MQTT to the base unit. I have a Raspberry Pi 4 server running Mosquitto and using Node-Red to display the data. This part also for the most part is working.

The problem seems to be that I keep losing the connection to the server. I had found an example program that checks if the MQTT connection is still there, if not it reconnects, happens about every minute. If I use a program that does not have Lora I can send data to the server without losing the connection.

I’m not sure if something in the code is causing the problem or if there is a hardware, pin definition conflict. here is the code I am running.

    /*********
  Rui Santos
  Complete project details at http://randomnerdtutorials.com  
  Rev 2 added barometric pressure
  Rev 3 moved HTML code to separate tab, will delete later
  Rev 4 Added MQTT client
*********/

// Import libraries
#include <WiFi.h>
#include <SPI.h>
#include <LoRa.h>

// Libraries to get time from NTP Server
#include <NTPClient.h>
#include <WiFiUdp.h>

// Libraries for SD card
#include "FS.h"
#include "SD.h"

// Replace with your network credentials
const char* ssid = "Fios-tCL9H";
const char* password = "PamPolly_1155";

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;

// LoRa Module pin definition
// define the pins used by the LoRa transceiver module
#define ss 5
#define rst 14
#define dio0 2

// Initialize variables to get and save LoRa data
int rssi;
String loRaMessage;
String temperature;
String soilMoisture;
String batteryLevel;
String readingID;
String Humidity;
String pressure;


// Define CS pin for the SD card module
#define SD_CS 22

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

//MQTT Setup Start
#include <PubSubClient.h>
#define mqtt_server "192.168.1.171"
WiFiClient espClient;
PubSubClient client(espClient);
#define mqttTemp1 "greenHouse/temp1"
#define mqttHum1 "greenHouse/hum1"
#define mqttPrss1 "greenHouse/prss1"
#define mqttBatt1 "greenHouse/batt1"
#define mqttTime "greenHouse/time"
//MQTT Setup End

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);

  // Initialize LoRa
  //replace the LoRa.begin(---E-) argument with your location's frequency
  //note: the frequency should match the sender's frequency
  //433E6 for Asia
  //866E6 for Europe
  //915E6 for North America
  LoRa.setPins(ss, rst, dio0);
  while (!LoRa.begin(915E6)) {
    Serial.println(".");
    delay(500);
  }
  // Change sync word (0xF3) to match the sender
  // The sync word assures you don't get LoRa messages from other LoRa transceivers
  // ranges from 0-0xFF
  LoRa.setSyncWord(0xF3);
  Serial.println("LoRa Initializing OK!");

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();

  // Initialize a NTPClient to get time
  timeClient.begin();
  // Set offset time in seconds to adjust for your timezone, for example:
  // GMT +1 = 3600
  // GMT +8 = 28800
  // GMT -1 = -3600
  // GMT 0 = 0
  timeClient.setTimeOffset(-14400);  // 3600

  // Initialize SD card
  SD.begin(SD_CS);
  if (!SD.begin(SD_CS)) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
  Serial.println("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("ERROR - SD card initialization failed!");
    return;  // init failed
  }

  // If the data.txt file doesn't exist
  // Create a file on the SD card and write the data labels
  File file = SD.open("/data.txt");
  if (!file) {
    Serial.println("File doens't exist");
    Serial.println("Creating file...");
    writeFile(SD, "/data.txt", "Reading ID, Date, Hour, Temperature, Humidity (0-100), RSSI, Battery Level(0-100)\r\n");
  } else {
    Serial.println("File already exists");
  }
  file.close();

  // MQTT connection
  client.setServer(mqtt_server, 1883);

}  // end setup

void loop() {

  if (!client.connected()) {
    Serial.println("reconnect()");
    reconnect();
  }

  // Check if there are LoRa packets available
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    getLoRaData();
    getTimeStamp();
    logSDCard();
  }
  WiFiClient client = server.available();  // Listen for incoming clients

  //delay(5000);
  
}  // end loop

void reconnect() {
  // Loop until we're reconnected
  int counter = 0;
  while (!client.connected()) {
    if (counter == 5) {
      ESP.restart();
    }
    counter += 1;
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect

    if (client.connect("greenHouseController")) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// Read LoRa packet and get the sensor readings
void getLoRaData() {
  Serial.print("Lora packet received: ");
  // Read packet
  while (LoRa.available()) {
    String LoRaData = LoRa.readString();
    // LoRaData format: readingID/temperature&soilMoisture#batterylevel
    // String example: 1/27.43&654#95.34
    Serial.print(LoRaData);

    // Get readingID, temperature and humidity
    int pos1 = LoRaData.indexOf('/');
    int pos2 = LoRaData.indexOf('&');
    int pos3 = LoRaData.indexOf('%');
    int pos4 = LoRaData.indexOf('#');
    readingID = LoRaData.substring(0, pos1);
    temperature = LoRaData.substring(pos1 + 1, pos2);
    Humidity = LoRaData.substring(pos2 + 1, pos3);
    pressure = LoRaData.substring(pos3 + 1, pos4);
    batteryLevel = LoRaData.substring(pos4 + 1, LoRaData.length());

    Serial.println(" ");
    Serial.print("Temp = ");
    Serial.println(temperature);
    Serial.print("Humdity = ");
    Serial.println(Humidity);
    Serial.print("Pressure = ");
    Serial.println(pressure);
    Serial.print("Battery = ");
    Serial.println(batteryLevel);
  }
  // Get RSSI
  rssi = LoRa.packetRssi();
  Serial.print(" with RSSI ");
  Serial.println(rssi);

  // publish to MQTT server
  client.publish(mqttTemp1, String(temperature).c_str(), true);
  client.publish(mqttHum1, String(Humidity).c_str(), true);
  client.publish(mqttPrss1, String(pressure).c_str(), true);
  client.publish(mqttBatt1, String(batteryLevel).c_str(), true);
  client.publish(mqttTime, (timeStamp).c_str(),true);

}  // end getloroadata

// Function to get date and time from NTPClient
void getTimeStamp() {
  while (!timeClient.update()) {
    timeClient.forceUpdate();
  }
  // The formattedDate comes with the following format:
  // 2018-05-28T16:00:13Z
  // We need to extract date and time
  formattedDate = timeClient.getFormattedDate();
  Serial.println(formattedDate);

  // Extract date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);
  Serial.println(dayStamp);
  // Extract time
  timeStamp = formattedDate.substring(splitT + 1, formattedDate.length() - 1);
  Serial.println(timeStamp);
}

// Write the sensor readings on the SD card
void logSDCard() {
  loRaMessage = String(readingID) + "," + String(dayStamp) + "," + String(timeStamp) + "," + String(temperature) + "," + String(Humidity) + "," + String(rssi) + "," + String(batteryLevel) + "\r\n";
  appendFile(SD, "/data.txt", loRaMessage.c_str());
}

// Write to the SD card (DON'T MODIFY THIS FUNCTION)
void writeFile(fs::FS& fs, const char* path, const char* message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
void appendFile(fs::FS& fs, const char* path, const char* message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

Thanks for all suggestions and comments.

Shouldn’t mqttclient.loop() be called in loop() ?