In this step we have added Queue using cppQueue.h, it heps to save data in case of WIFI failure.
WIFI connectivity status and Battery status also display in OLED
#include <WiFi.h>
#include <Wire.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h" // DHT sensor library
#include <NTPClient.h>
#include "Time_a.h"
#include <TimeLib.h> // unix time libray
#include <cppQueue.h>
#define IMPLEMENTATION FIFO
#define queue_size 3000
#define OVERWRITE true
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
/////////////////////////////////////////////////////////////////////////
#define timeSeconds 10
// Set GPIOs for LED and PIR Motion Sensor
const int led = 14;
const int motionSensor = 12;
// Timer: Auxiliary variables
unsigned long now_delay = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;
// Checks if motion was detected, sets LED HIGH and starts a timer
void IRAM_ATTR detectsMovement() {
Serial.println("MOTION DETECTED!!!");
digitalWrite(led, HIGH);
startTimer = true;
lastTrigger = millis();
}
////////////////////////////////////////////////////////////////
int battery_level=38;
#define DHTPIN 26 // DHT conected to pin 26
#define DHTTYPE DHT11 //
unsigned long offset_days = 3; // 3 days
//unsigned long t_unix_date1;
//
// const char* ssid = "AndroidAP"; // change here
// const char* password = "sema9444"; // change here
// const char* mqtt_server = "broker.hivemq.com";
// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "Dialog 4G";
const char* password = "YJNHQ102RD8";
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "192.168.0.105";
// Lamp - LED - GPIO 4 = D2 on ESP-12E NodeMCU board
const int lamp = 4;
// Lamp - LED - GPIO 12 = D6 on ESP-12E NodeMCU board
const int lamp1 = 5 ;
int status = WL_IDLE_STATUS; // the Wifi radio's status
////////////////wifi cnnected image////////////////////////////////////////////////////////////////
static const unsigned char PROGMEM image_wifi[] = {
// 'wifi-icon-260nw-329468402', 14x14px
0x07, 0x80, 0x1f, 0xe0, 0x70, 0x30, 0xe3, 0x18, 0xcf, 0xcc, 0x38, 0x70, 0x30, 0x30, 0x0f, 0x80,
0x0d, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00};
/////////////////////////battery status ///////////////////////////////////////////////////////////
static const unsigned char PROGMEM battery_empty[] = { ///
// 'battery empty', 15x24px
0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x7f, 0xfc, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c,
0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x6f, 0xec,
0x6f, 0xec, 0x6f, 0xec, 0x60, 0x0c, 0x60, 0x0c, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};///
///
static const unsigned char PROGMEM battery_half[] = { ///
// 'battery half', 15x24px
0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x7f, 0xfc, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c,
0x60, 0x0c, 0x60, 0x0c, 0x6f, 0xec, 0x6f, 0xec, 0x6f, 0xec, 0x60, 0x0c, 0x60, 0x0c, 0x6f, 0xec,
0x6f, 0xec, 0x6f, 0xec, 0x60, 0x0c, 0x7f, 0xfc, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};///
///
static const unsigned char PROGMEM battery_full[] = { ///
// 'battery full', 15x24px
0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x3f, 0xfc, 0x60, 0x0c, 0x6f, 0xec, 0x6f, 0xec, 0x6f, 0xec,
0x60, 0x0c, 0x60, 0x0c, 0x6f, 0xec, 0x6f, 0xec, 0x6f, 0xec, 0x60, 0x0c, 0x6f, 0xec, 0x6f, 0xec,
0x6f, 0xec, 0x60, 0x0c, 0x3f, 0xfc, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};//
///
///////////////////////////////////////////////////////////////////////////////////////////////////
WiFiClient espClient;
PubSubClient client(espClient);
char mqtt_msg[10];
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
time_t et;
DHT dht(DHTPIN, DHTTYPE);
float dht11_hum, dht11_temp;
uint32_t t; //unix time
uint32_t count=0;
int len =0;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
/////////////////////////////////////////////////////////////////////////////////////
typedef struct strRec {
uint16_t t;
float dht11_temp;
float dht11_hum;
} Rec;
//Rec = rec.dht11_temp;
Queue q(sizeof(Rec), queue_size, IMPLEMENTATION,OVERWRITE); // Instantiate queue
/////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
connect_wifi();
update_time ();
display.clearDisplay(); //clear OLED
/////////////////////////////////////////////////////////////////////////
pinMode(lamp, OUTPUT);
// pinMode(lamp1, OUTPUT)
//////////////////////////////////////////////////////////////////////////////
// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
// Set LED to LOW
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
///////////////////////////////////////////////////////////////////////////////////////
///////////// to display wifi connection status https://www.arduino.cc/en/Reference/WiFiStatus
//if(WiFi.status()== WL_CONNECTED){
// Draw bitmap on the screen
display.drawBitmap(112, 0, image_wifi, 14, 14, 1);
display.display();
// while(true);};
///////////////battery level display ///////////////////////////////
if (battery_level<30){
display.drawBitmap(110, 40, battery_empty, 15, 24, 1);display.display();};
if(battery_level>31){
if(battery_level<50){
display.drawBitmap(110, 40, battery_half, 15, 24, 1);display.display();}};
if(battery_level>51){
display.drawBitmap(110, 40, battery_full, 15, 24, 1);display.display();};
//splay.clearDisplay(); //clear OLED
////////////////////////////////////////////////////////////////////
dht.begin(); // Start the DHT11 sensor
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
//////////////////////////////////////////////////////////////////////////////
// Current time for interruprt
now_delay = millis();
// Turn off the LED after the number of seconds defined in the timeSeconds variable
if(startTimer && (now_delay - lastTrigger > (timeSeconds*1000))) {
Serial.println("Motion stopped...");
digitalWrite(led, LOW);
startTimer = false;
}
//////////////////////////////////////////////////////////////////////////////
if(len>30){
len=0;
Serial.println("Queue data lost !");
}
/// read data from sensors //////////////////////////////////
dht11_hum = dht.readHumidity(); // humidity ///
dht11_temp = dht.readTemperature(); // temp ///
t = now(); // time stamp ///
///
/////////////////////////////////////////////////////////////
////////////// unix time convert ///////////////////
Serial.print(t); // https://arduino.stackexchange.com/questions/38765/convert-to-and-from-unix-timestamp
printf(" : %4d-%02d-%02d %02d:%02d:%02d\n", year(t), month(t), day(t), hour(t), minute(t), second(t));
display_oled();
//publish_mqtt ();
//putInQueue();
//connect_wifi ();
if(WiFi.status()==WL_CONNECTED){
subscribeToLamps();
putInQueuePubToMqtt();}
if(WiFi.status()==WL_CONNECTION_LOST){
Serial.println("wifi CONNECTION_LOST, Data Write to Queue");
putInQueue();
connect_wifi();
if(WiFi.status()==WL_CONNECTED){
Serial.println("Queue data due to CONNECTION_LOST");
pubQueue ();
Serial.println("Queue data due to CONNECTION_LOST is finished");}
}
if(WiFi.status()==WL_NO_SSID_AVAIL){
Serial.println("wifi NO_SSID_AVAIL, Data Write to Queue");
putInQueue();
connect_wifi();
if(WiFi.status()==WL_CONNECTED){
Serial.println("Queue data due to WL_NO_SSID_AVAIL");
pubQueue ();
Serial.println("Queue data due to WL_NO_SSID_AVAIL is finished");}
}
if(WiFi.status()==WL_DISCONNECTED){
Serial.println("wifi DISCONNECTED, Data Write to Queue");
putInQueue();
connect_wifi();
if(WiFi.status()==WL_CONNECTED){
Serial.println("Queue data due to WL_DISCONNECTED");
pubQueue ();
Serial.println("Queue data due to WL_DISCONNECTED is finished");
}
}
// WiFi.disconnect();
// Serial.print("wifi Disconnected");
// delay(30000);
////////sleep for 20 secound/////////////////////
// esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
// esp_sleep_enable_timer_wakeup(20000000);
// esp_deep_sleep_start();
}
/////////////////////QUEUE/////////////////////////////////////////////////////////////////
void subscribeToLamps(){
client.subscribe("room/lamp");
client.subscribe("room/lamp1");
}
void putInQueue (){
for (int i=0; i<10; i++){
dht11_hum = dht.readHumidity(); // humidity
dht11_temp = dht.readTemperature(); // temp
t = now(); // time stamp
Rec rec;
rec.t = t;
rec.dht11_temp = dht11_temp;
rec.dht11_hum = dht11_hum;
q.push(&rec);
delay(10000);
len=q.getCount();
Serial.println(" ");
Serial.print(len);}
}
void pubQueue(){
len=q.getCount();
for(len ;len>0; len--){
Rec rec;
q.pop(&rec);
Serial.print(rec.t); Serial.print(" ");
Serial.print(rec.dht11_temp); Serial.print(" ");
Serial.print(rec.dht11_hum); Serial.print(" ");
Serial.println(len);
sprintf(mqtt_msg,"%u %2.0f %2.1f",t,dht11_hum,dht11_temp);
//client.connect("mel5405-2018AE03");
client.publish("mel5405/2018AE03/all",mqtt_msg);
Serial.println(mqtt_msg);
//delay(5000);
delay(300);
}
len=0;
}
//////////////////////QUEUE TO MQTT ///////////////////////////////////////////////
void putInQueuePubToMqtt(){
for (int i=0; i<5; i++){
dht11_hum = dht.readHumidity(); // humidity
dht11_temp = dht.readTemperature(); // temp
t = now(); // time stamp
Rec rec;
rec.t = t;
rec.dht11_temp = dht11_temp;
rec.dht11_hum = dht11_hum;
q.push(&rec);
delay(10000);}
len=q.getCount();
if(len%5==0){
for(len ;len>0; len--){
Rec rec;
q.pop(&rec);
Serial.print(rec.t);
Serial.print(" ");
Serial.print(rec.dht11_temp);
Serial.print(" ");
Serial.print(rec.dht11_hum);
Serial.print(" ");
Serial.println(len);
sprintf(mqtt_msg,"%u %2.2f %2.2f",rec.t,rec.dht11_temp,rec.dht11_hum);
client.connect("mel5405-2018AE03");
client.publish("mel5405/2018AE03/all",mqtt_msg);
Serial.println(mqtt_msg);
delay(500);
sprintf(mqtt_msg," %2.2f",rec.dht11_temp);
client.connect("mel5405-2018AE03");
client.publish("mel5405/2018AE03/temp",mqtt_msg);
Serial.println(mqtt_msg);
delay(500);
// sprintf(mqtt_msg," %2.2f",rec.dht11_hum);
// client.connect("mel5405-2018AE03");
// client.publish("mel5405/2018AE03/hum",mqtt_msg);
// Serial.println(mqtt_msg);
// delay(500);
// delay(5000);
// delay(300);
}
len=0;
}
}
////////////////////////////////////////////////////////////////////////////////
// void publish_mqtt() {
// ////////////////// publish data using MQTT////////////////////////////////
// sprintf(mqtt_msg,"%2.4f",dht11_hum);
// client.connect("mel5405-2018AE03"); // change here
// client.publish("mel5405/2018AE03/humidity", mqtt_msg); // change here
// Serial.println(mqtt_msg);
// delay(5000);
// sprintf(mqtt_msg,"%2.4f",dht11_temp);
// client.connect("mel5405-2018AE03"); // change here
// client.publish("mel5405/2018AE03/temp", mqtt_msg); // change here
// Serial.println(mqtt_msg);
// delay(5000);
// sprintf(mqtt_msg,"%u",t);
// client.connect("mel5405-2018AE03"); // change here
// client.publish("mel5405/2018AE03/time", mqtt_msg); // change here
// Serial.println(mqtt_msg);
// delay(5000);
// sprintf(mqtt_msg,"%2.0f-%2.1f",dht11_hum,dht11_temp);
// client.connect("mel5405-2018AE03");
// client.publish("mel5405/2018AE03/all",mqtt_msg);
// Serial.println(mqtt_msg);
// delay(5000);
// }
void display_oled(){
/////////////Display data on OLED ///////////////////////////
display.setTextSize(1); //set OLED text size
display.setTextColor(WHITE); // set text colour
display.print(WiFi.localIP()); //Display IP of ESP
delay(2000);
//display.clearDisplay(); //clear OLED
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(2, 15);
display.print(dht11_temp);
display.print(" C");
display.setCursor(2, 30);
display.print(dht11_hum);
display.print(" %");
display.setTextSize(1); // Draw 1X-scale text
display.setCursor(1, 55);
display.print(t);
display.setCursor(64, 55);
display.print(count);
display.display();
}
void update_time(){
///////////////// time update///////////////////////////////////////////////////
timeClient.begin();
timeClient.setTimeOffset(0); // GMT +5:30 = 19800
while(!timeClient.update()) {
timeClient.forceUpdate();
delay(100);
Serial.print("*");
count ++;
if (count>3)break;}
if (count<3){
Serial.println("");
Serial.print("NTP time set: ");
setTime(timeClient.getEpochTime()); // update ESP32 time
}
else {
Serial.println("");
Serial.println("Time not set");
}
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(100);
}
void connect_wifi(){
int count=0;
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
count ++;
if (count>40)break;}
if (count<40){
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());}
else {(Serial.print("No WiFi"));
}
}
void callback(String topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
if(topic=="room/lamp1"){
Serial.print("Changing Room lamp1 to ");
if(messageTemp == "on"){
digitalWrite(lamp1, HIGH);
Serial.print("On");
}
else if(messageTemp == "off"){
digitalWrite(lamp1, LOW);
Serial.print("Off");
}
}
Serial.println();
// If a message is received on the topic room/lamp, you check if the message is either on or off. Turns the lamp GPIO according to the message
if(topic=="room/lamp"){
Serial.print("Changing Room lamp to ");
if(messageTemp == "on"){
digitalWrite(lamp, HIGH);
Serial.print("On");
}
else if(messageTemp == "off"){
digitalWrite(lamp, LOW);
Serial.print("Off");
}
}
Serial.println();
}