Publishing timestmp from NTP to MQTT broker

This is my first venture into programming an ESP32 and an MQTT broker. I would like to monitor the temperature and humidity in a remote location using a DHT22 connected to an ESP32. The ESP32 will wakeup from a deep sleep every 30 minutes, get the current date and time from NTP and get the temperature and humidity from the DHT22. The ESP32 then connects to my MQTT broker and publishes the data. I have everything working properly except for the date and time.

The ESP32 connects to the NTP server and retrieves the correct date and time but I am stuck with getting the values into something that I can publish to my MQTT broker.

I would prefer the date and time to be published as mm/dd hh:mm (all numbers). The timestamp will not be used except for troubleshooting and checking that the ESP is publishing in a timely fashion. My code so far:

include "DHT.h"
#include <WiFi.h>
#include "time.h"
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include <AsyncMqttClient.h>

const int led = 2;

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = -18000;
const int   daylightOffset_sec = 3600;

#define WIFI_SSID "WhoPeedInThePool"
#define WIFI_PASSWORD "superTopSecretPassword"

// Raspberry Pi Mosquitto MQTT Broker
#define MQTT_HOST "myMQTTBroker"
#define MQTT_PORT 1883

// Temperature MQTT Topics
#define MQTT_PUB_TEMP "SlumCity/LivingRoom/temperature"
#define MQTT_PUB_HUM  "SlumCity/LivingRoom/humidity"

// Digital pin connected to the DHT sensor
#define DHTPIN 4

#define DHTTYPE DHT22

#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  1800

// Initialize DHT sensor
DHT dht(DHTPIN, DHTTYPE);

// Variables to hold sensor readings
float temp;
float hum;

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}


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 onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  Serial.begin(115200);
  Serial.println();

  pinMode(led, OUTPUT);
  digitalWrite(led, 1);

  dht.begin();

  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);

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  // If your broker requires authentication (username and password), set them below
  mqttClient.setCredentials("MQTTUser", "topSecretPassword");
  connectToWifi();

  delay(1000);
   
  // New DHT sensor readings
  hum = dht.readHumidity();
  // Read temperature as Celsius (the default)
  //temp = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  temp = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(temp) || isnan(hum)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Publish an MQTT message on topic Estero/LivingRoom/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: %i", MQTT_PUB_TEMP, packetIdPub1);
  Serial.printf("Message: %.2f \n", temp);
  
  // Publish an MQTT message on topic Estero/LivingRoom/humidity
  uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUM, 1, true, String(hum).c_str());
  Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_HUM, packetIdPub2);
  Serial.printf("Message: %.2f \n", hum);

  // Publish an MQTT message on topic Estero/LivingRoom/timestamp
  uint16_t packetIdPub3 = mqttClient.publish(MQTT_PUB_TIMESTAMP, 1, true, String(timestamp).c_str());
  Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_TIMESTAMP, packetIdPub3);
  Serial.printf("Message: %.2f \n", timestamp);

  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  Serial.println(F("WiFi disconnected"));

  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for " + String(TIME_TO_SLEEP) +
                 " Seconds");

  Serial.println("Going to sleep now");
  delay(1000);

  digitalWrite(led, 0);

  Serial.flush();
  esp_deep_sleep_start();
  Serial.println("This will never be printed");

}

void loop() {

}

I would appreciate any help

let me know if this helps.

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  char timestamp[16];
  strftime(timestamp, sizeof(timestamp), "%m/%d %H:%M", &timeinfo);
  Serial.println(timestamp);
  uint16_t packetIdPub = mqttClient.publish(MQTT_PUB_TIMESTAMP, 1, true, timestamp);
  Serial.printf("Publishing timestamp on topic %s at QoS 1, packetId %i: %s\n", MQTT_PUB_TIMESTAMP, packetIdPub, timestamp);
}

// New DHT sensor readings
hum = dht.readHumidity();
// Read temperature as Celsius (the default)
//temp = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
temp = dht.readTemperature(true);

// Check if any reads failed and exit early (to try again).
if (isnan(temp) || isnan(hum)) {
  Serial.println(F("Failed to read from DHT sensor!"));
  return;
}

// Get current time and publish it to MQTT broker
printLocalTime();

// Publish an MQTT message on topic SlumCity/LivingRoom/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 %i, timestamp %s: %.2f \n", MQTT_PUB_TEMP, packetIdPub1, timestamp, temp);

// Publish an MQTT message on topic SlumCity/LivingRoom/humidity
uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUM, 1, true, String(hum).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId %i, timestamp %s: %.2f \n", MQTT_PUB_HUM, packetIdPub2, timestamp, hum);

Z

This is throwing an error:

20:23:16.936 -> Connected to MQTT.
20:23:16.936 -> Session present: 0
20:23:22.696 -> Failed to obtain time

Any suggestions?

I use, GitHub - fbiego/ESP32Time: An Arduino library for setting and retrieving internal RTC time on ESP32 boards for ESP32 time things.

Thanks to all for the help. I was able to get the suggestion from zhomeslice to work by adding configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); immediately before printLocalTime();

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.