MQTT losing server connection
Posted: Wed Nov 01, 2023 8:11 am
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 the 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.
Thanks for all suggestions and comments
John
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 the 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.
Code: Select all
/*********
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();
}
John