Dear friends: I'm having problems with the code I prevously uploaded.
With this code, I want to register temperature all the time. But if for some reason the mqtt server goes down or internet connectivity losses the board keeps waiting for the server response and it doesn't write the data on sd card.
Values saved on sd card are important specially in cases where there is no connection.
What can I do to make sd card writting independent from connectivity to mqtt server?
My code is
// Libraries to get time from NTP Server
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Libraries for SD card
#include "FS.h"
#include "SD.h"
#include <SPI.h>
//DS18B20 libraries
#include <AsyncMqttClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#define WIFI_SSID "XXXXXXXX"
#define WIFI_PASSWORD "XXXXXX"
// For a cloud MQTT broker, type the domain name
#define MQTT_HOST IPAddress(192, 168, 1, 2)
#define MQTT_PORT 1883
// Temperature MQTT Topic
#define MQTT_PUB_TEMP "esp32/ds18b20/temperature"
// Save reading number on RTC memory
RTC_DATA_ATTR int readingID = 0;
String dataMessage;
// GPIO where the DS18B20 is connected to
const int oneWireBus = 22;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Temperature value
float temp;
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;
AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
unsigned long previousMillis = 0; // Stores last time temperature was published
const long interval = 60000; // Interval at which to publish sensor readings
void connectToWifi() {
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}
void connectToMqtt() {
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
xTimerStart(wifiReconnectTimer, 0);
break;
}
}
void onMqttConnect(bool sessionPresent) {
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
xTimerStart(mqttReconnectTimer, 0);
}
}
/*void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
Serial.println("Subscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
Serial.print(" qos: ");
Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
Serial.println("Unsubscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}*/
void onMqttPublish(uint16_t packetId) {
Serial.println("Publish acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
// Function to get temperature
void getReadings(){
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0); // Temperature in Celsius
//temperature = sensors.getTempFByIndex(0); // Temperature in Fahrenheit
Serial.print("Temperature: ");
Serial.println(temp);
}
void setup() {
// Start the DS18B20 sensor
sensors.begin();
Serial.begin(115200);
Serial.println();
Serial.println();
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
WiFi.onEvent(WiFiEvent);
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
//mqttClient.onSubscribe(onMqttSubscribe);
//mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// If your broker requires authentication (username and password), set them below
//mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");
connectToWifi();
// 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(-10800);
// Initialize SD card
SD.begin();
if(!SD.begin()) {
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()) {
Serial.println("ERROR - SD card initialization failed!");
return; // init failed
}
// If the temp1.txt file doesn't exist
// Create a file on the SD card and write the data labels
File file = SD.open("/temp1.txt");
if(!file) {
Serial.println("File doens't exist");
Serial.println("Creating file...");
writeFile(SD, "/temp1.txt", "Reading ID, Date, Hour, Temp (ÂșC) \r\n");
}
else {
Serial.println("File already exists");
}
file.close();
// getReadings();
// getTimeStamp();
// logSDCard();
// Increment readingID on every new reading
// readingID++;
}
void loop() {
unsigned long currentMillis = millis();
// Every X number of seconds (interval = 60 seconds)
// it publishes a new MQTT message
if (currentMillis - previousMillis >= interval) {
// Save the last time a new reading was published
previousMillis = currentMillis;
// New temperature readings
sensors.requestTemperatures();
// Temperature in Celsius degrees
temp = sensors.getTempCByIndex(0);
// Temperature in Fahrenheit degrees
//temp = sensors.getTempFByIndex(0);}
// Publish an MQTT message on topic esp32/ds18b20/temperature
uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId: ", MQTT_PUB_TEMP);
Serial.println(packetIdPub1);
Serial.printf("Message: %.2f /n", sensors.getTempCByIndex(0));
getReadings();
getTimeStamp();
logSDCard();
// Increment readingID on every new reading
readingID++;
}
}
// 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() {
dataMessage = String(readingID) + "," + String(dayStamp) + "," + String(timeStamp) + "," +
String(temp) + "\r\n";
Serial.print("Save data: ");
Serial.println(dataMessage);
appendFile(SD, "/temp1.txt", dataMessage.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();
}
many thanks for your help.
Best regards
DL