diff --git a/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/2_Firebase_Client.ino b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/2_Firebase_Client.ino new file mode 100644 index 0000000..75c0a6d --- /dev/null +++ b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/2_Firebase_Client.ino @@ -0,0 +1,216 @@ +///////////////////////////////////////////////////////////////// +/* + ESP32 | Cloud Firestore - Ep 2. Firebase Client + Video Tutorial: + Created by Eric N. (ThatProject) +*/ +///////////////////////////////////////////////////////////////// + +#include "DHTesp.h" // Click here to get the library: http://librarymanager/All#DHTesp +#include +#include "Display.h" +#include "Network.h" + +#ifndef ESP32 +#pragma message(THIS EXAMPLE IS FOR ESP32 ONLY!) +#error Select ESP32 board. +#endif + +/**************************************************************/ +/* Example how to read DHT sensors from an ESP32 using multi- */ +/* tasking. */ +/* This example depends on the Ticker library to wake up */ +/* the task every 20 seconds */ +/**************************************************************/ + +Display *display; +Network *network; +DHTesp dht; + +void tempTask(void *pvParameters); +bool getTemperature(); +void triggerGetTemp(); + +/** Task handle for the light value read task */ +TaskHandle_t tempTaskHandle = NULL; +/** Ticker for temperature reading */ +Ticker tempTicker; +/** Comfort profile */ +ComfortState cf; +/** Flag if task should run */ +bool tasksEnabled = false; +/** Pin number for DHT11 data pin */ +int dhtPin = 21; + +/** + * initTemp + * Setup DHT library + * Setup task and timer for repeated measurement + * @return bool + * true if task and timer are started + * false if task or timer couldn't be started + */ +bool initTemp() { + byte resultValue = 0; + // Initialize temperature sensor + dht.setup(dhtPin, DHTesp::DHT11); + Serial.println("DHT initiated"); + + // Start task to get temperature + xTaskCreatePinnedToCore( + tempTask, /* Function to implement the task */ + "tempTask ", /* Name of the task */ + 10000, /* Stack size in words */ + NULL, /* Task input parameter */ + 5, /* Priority of the task */ + &tempTaskHandle, /* Task handle. */ + 1); /* Core where the task should run */ + + if (tempTaskHandle == NULL) { + Serial.println("Failed to start task for temperature update"); + return false; + } else { + // Start update of environment data every 20 seconds + tempTicker.attach(20, triggerGetTemp); + } + return true; +} + +/** + * triggerGetTemp + * Sets flag dhtUpdated to true for handling in loop() + * called by Ticker getTempTimer + */ +void triggerGetTemp() { + if (tempTaskHandle != NULL) { + xTaskResumeFromISR(tempTaskHandle); + } +} + +/** + * Task to reads temperature from DHT11 sensor + * @param pvParameters + * pointer to task parameters + */ +void tempTask(void *pvParameters) { + Serial.println("tempTask loop started"); + while (1) // tempTask loop + { + if (tasksEnabled) { + // Get temperature values + getTemperature(); + } + // Got sleep again + vTaskSuspend(NULL); + } +} + +/** + * getTemperature + * Reads temperature from DHT11 sensor + * @return bool + * true if temperature could be aquired + * false if aquisition failed +*/ +bool getTemperature() { + // Reading temperature for humidity takes about 250 milliseconds! + // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor) + TempAndHumidity newValues = dht.getTempAndHumidity(); + // Check if any reads failed and exit early (to try again). + if (dht.getStatus() != 0) { + Serial.println("DHT11 error status: " + String(dht.getStatusString())); + return false; + } + + float heatIndex = dht.computeHeatIndex(newValues.temperature, newValues.humidity); + float dewPoint = dht.computeDewPoint(newValues.temperature, newValues.humidity); + float cr = dht.getComfortRatio(cf, newValues.temperature, newValues.humidity); + + String comfortStatus; + switch(cf) { + case Comfort_OK: + comfortStatus = "OK"; + break; + case Comfort_TooHot: + comfortStatus = "TooHot"; + break; + case Comfort_TooCold: + comfortStatus = "TooCold"; + break; + case Comfort_TooDry: + comfortStatus = "TooDry"; + break; + case Comfort_TooHumid: + comfortStatus = "TooHumid"; + break; + case Comfort_HotAndHumid: + comfortStatus = "Hot&Humid"; + break; + case Comfort_HotAndDry: + comfortStatus = "Hot&Dry"; + break; + case Comfort_ColdAndHumid: + comfortStatus = "Cold&Humid"; + break; + case Comfort_ColdAndDry: + comfortStatus = "Cold&Dry"; + break; + default: + comfortStatus = "Unknown"; + break; + }; + + Serial.println(" T:" + String(newValues.temperature) + " H:" + String(newValues.humidity) + " I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus); + + display->tempUpdates("Temp " + String(newValues.temperature, 1) +"'C", + "Humidity " + String(newValues.humidity,0) + "%", + comfortStatus); + + network->firestoreDataUpdate(newValues.temperature, newValues.humidity); + + return true; +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println("DHT ESP32 example with tasks"); + + initDisplay(); + initNetwork(); + initTemp(); + // Signal end of setup() to tasks + tasksEnabled = true; +} + +void loop() { + if (!tasksEnabled) { + // Wait 2 seconds to let system settle down + delay(2000); + // Enable task that will read values from the DHT sensor + tasksEnabled = true; + if (tempTaskHandle != NULL) { + vTaskResume(tempTaskHandle); + } + } + yield(); +} + +void initDisplay(){ + display = new Display(); + display->initTFT(); + display->centerMsg("System Init..."); +} + +void initNetwork(){ + network = new Network(); + network->initWiFi(); +} + + + + + + + diff --git a/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.cpp b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.cpp new file mode 100644 index 0000000..7e10929 --- /dev/null +++ b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.cpp @@ -0,0 +1,29 @@ +#include "Display.h" + +Display::Display(){ + tft = new TFT_eSPI(); +} + +Display::~Display(){ + delete tft; +} + +void Display::initTFT(){ + tft->init(); + tft->fillScreen(TFT_BLACK); + tft->setRotation(1); + tft->setTextColor(TFT_WHITE, TFT_BLACK); + tft->setTextDatum(MC_DATUM); + tft->setFreeFont(&Orbitron_Light_24); +} + +void Display::centerMsg(String text){ + tft->drawString(text, tft->width()/2, 60); +} + +void Display::tempUpdates(String temp, String hum, String status){ + tft->setTextPadding(tft->width()); + tft->drawString(temp, tft->width()/2, 40); + tft->drawString(hum, tft->width()/2, 70); + tft->drawString(status, tft->width()/2, 110); +} \ No newline at end of file diff --git a/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.h b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.h new file mode 100644 index 0000000..74e9e26 --- /dev/null +++ b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Display.h @@ -0,0 +1,20 @@ +#ifndef Display_H_ +#define Display_H_ + +#include + +class Display { +private: + TFT_eSPI* tft; + +public: + Display(); + ~Display(); + + void initTFT(); + void centerMsg(String text); + void tempUpdates(String temp, String hum, String status); +}; + + +#endif \ No newline at end of file diff --git a/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.cpp b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.cpp new file mode 100644 index 0000000..60f60c8 --- /dev/null +++ b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.cpp @@ -0,0 +1,92 @@ +#include "Network.h" +#include "addons/TokenHelper.h" + +#define WIFI_SSID "" +#define WIFI_PASSWORD "" + +#define API_KEY "" +#define FIREBASE_PROJECT_ID "" +#define USER_EMAIL "" +#define USER_PASSWORD "" + +static Network *instance = NULL; + +Network::Network(){ + instance = this; +} + +void WiFiEventConnected(WiFiEvent_t event, WiFiEventInfo_t info){ + Serial.println("WIFI CONNECTED! BUT WAIT FOR THE LOCAL IP ADDR"); +} + +void WiFiEventGotIP(WiFiEvent_t event, WiFiEventInfo_t info){ + Serial.print("LOCAL IP ADDRESS: "); + Serial.println(WiFi.localIP()); + instance->firebaseInit(); +} + +void WiFiEventDisconnected(WiFiEvent_t event, WiFiEventInfo_t info){ + Serial.println("WIFI DISCONNECTED!"); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +} + +void FirestoreTokenStatusCallback(TokenInfo info){ + Serial.printf("Token Info: type = %s, status = %s\n", getTokenType(info).c_str(), getTokenStatus(info).c_str()); +} + +void Network::initWiFi(){ + WiFi.disconnect(); + WiFi.onEvent(WiFiEventConnected, SYSTEM_EVENT_STA_CONNECTED); + WiFi.onEvent(WiFiEventGotIP, SYSTEM_EVENT_STA_GOT_IP); + WiFi.onEvent(WiFiEventDisconnected, SYSTEM_EVENT_STA_DISCONNECTED); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); +} + +void Network::firebaseInit(){ + config.api_key = API_KEY; + + auth.user.email = USER_EMAIL; + auth.user.password = USER_PASSWORD; + + config.token_status_callback = FirestoreTokenStatusCallback; + + Firebase.begin(&config, &auth); +} + +void Network::firestoreDataUpdate(double temp, double humi){ + if(WiFi.status() == WL_CONNECTED && Firebase.ready()){ + String documentPath = "House/Room_1"; + + FirebaseJson content; + + content.set("fields/temperature/doubleValue", String(temp).c_str()); + content.set("fields/humidity/doubleValue", String(humi).c_str()); + + if(Firebase.Firestore.patchDocument(&fbdo, FIREBASE_PROJECT_ID, "", documentPath.c_str(), content.raw(), "temperature,humidity")){ + Serial.printf("ok\n%s\n\n", fbdo.payload().c_str()); + return; + }else{ + Serial.println(fbdo.errorReason()); + } + + if(Firebase.Firestore.createDocument(&fbdo, FIREBASE_PROJECT_ID, "", documentPath.c_str(), content.raw())){ + Serial.printf("ok\n%s\n\n", fbdo.payload().c_str()); + return; + }else{ + Serial.println(fbdo.errorReason()); + } + } +} + + + + + + + + + + + + + diff --git a/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.h b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.h new file mode 100644 index 0000000..bf2c20b --- /dev/null +++ b/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client/Network.h @@ -0,0 +1,25 @@ +#ifndef Network_H_ +#define Network_H_ + +#include +#include +class Network{ +private: + FirebaseData fbdo; + FirebaseAuth auth; + FirebaseConfig config; + + void firebaseInit(); + friend void WiFiEventConnected(WiFiEvent_t event, WiFiEventInfo_t info); + friend void WiFiEventGotIP(WiFiEvent_t event, WiFiEventInfo_t info); + friend void WiFiEventDisconnected(WiFiEvent_t event, WiFiEventInfo_t info); + friend void FirestoreTokenStatusCallback(TokenInfo info); + +public: + Network(); + void initWiFi(); + void firestoreDataUpdate(double temp, double humi); +}; + + +#endif \ No newline at end of file diff --git a/README.md b/README.md index 8532d1a..45e9e7b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ Thank you. * [Youtube ESP32 Project](https://www.youtube.com/playlist?list=PLnq7JUnBumAyhSBBp95MsQ5-chBAYheZw) -* [ESP32 | Cloud Firestore - Ep 1. Firebase Setup ][[Video]](https://youtu.be/KV0D8nrsBLg)[[Source Code]](https://github.com/0015/ThatProject/tree/master/FIREBASE/Cloud_Firestore_Application/1_Network_Class) +* [ESP32 | Cloud Firestore - Ep 2. Firebase Client For ESP32][[Video]](https://youtu.be/KiF9uGFkA_o)[[Source Code]](https://github.com/0015/ThatProject/tree/master/FIREBASE/Cloud_Firestore_Application/2_Firebase_Client) + +* [ESP32 | Cloud Firestore - Ep 1. Firebase Setup][[Video]](https://youtu.be/KV0D8nrsBLg)[[Source Code]](https://github.com/0015/ThatProject/tree/master/FIREBASE/Cloud_Firestore_Application/1_Network_Class) * [ESP32 | Cloud Firestore - Ep 0. Showing temp/humidity from DHT11 on TTGO display [Upgraded Version]][[Video]](https://youtu.be/aAUIlCWs_bc)[[Source Code]](https://github.com/0015/ThatProject/tree/master/FIREBASE/Cloud_Firestore_Application/0_ESP32TTGO_DHT11)