This article will get you up and running with Firebase on the ESP32 board in no time. Google’s mobile app development platform, Firebase, contains several services for managing data from iOS, Android, and web applications. You’ll make a Firebase project with a real-time database (RTDB) and learn how to use your ESP32 to save and get data from it.

Project Overview

To follow this project, first, you need to set up a Firebase project and create a real-time database for that project. Then, you’ll program the ESP32 to store and read data from the database. This tutorial is divided into three sections.

  1. Create a Firebase Project
  2. ESP32: Store data to the Firebase Realtime Database
  3. ESP32: Read data from the Firebase Realtime Database

Set Up a Firebase Account and Create a New Project

1. Create a New Project

Follow the next instructions to create a new project on Firebase.

  1. Go to Firebase and sign in using a Google Account.
  2. Click Get Started, and then Add project to create a new project.
  3. Give a name to your project, for example, ESP32 Firebase Demo.
  4. Disable the option Enable Google Analytics for this project as it is not needed, and click Create project.
  5. It will take a few seconds to set up your project. Then, click Continue when it’s ready.
  6. You’ll be redirected to your Project console page.

2. Set Authentication Methods

You need to set authentication methods for your app.

“The identity of a user is required by most programmes. Put it another way, it handles logging in and identifying users (in this case, the ESP32). Knowing a user’s identification enables an app to save user data securely in the cloud and give a consistent tailored experience across all of the user’s devices.” 

  1. On the left sidebar, click on Authentication and then on Get started.
  2. Several authentication methods include email and password, Google accounts, Facebook accounts, and others.
  3. For testing purposes, we can select the Anonymous user (require authentication without requiring users to sign in first by creating temporary anonymous accounts). Enable that option and click Save.

3. Creating a Realtime Database

The next step is creating a Realtime Database for your project. Follow the next steps to create the database.

  1. On the left sidebar, click on Realtime Database and then Create Database.
  2. Select your database location. It should be the closest to your location.
  3. Set up security rules for your database. For testing purposes, select Start in test mode. In later tutorials, you’ll learn how to secure your database using database rules.
  4. Your database is now created. You need to copy and save the database URL—highlighted in the following image—because you’ll need it later in your ESP32 code.

The Realtime Database is all set. Now, you also need to get your project API key.

4. Get Project API Key

  1. To get your project’s API key, on the left sidebar, click on Project Settings.
  2. Copy the API Key to a safe place because you’ll need it later.

CODE

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>

//Provide the token generation process info.
#include "addons/TokenHelper.h"
//Provide the RTDB payload printing info and other helper functions.
#include "addons/RTDBHelper.h"

// Insert your network credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Insert Firebase project API Key
#define API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"

// Insert RTDB URLefine the RTDB URL */
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL" 

//Define Firebase Data object
FirebaseData fbdo;

FirebaseAuth auth;
FirebaseConfig config;

unsigned long sendDataPrevMillis = 0;
int count = 0;
bool signupOK = false;

void setup(){
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  /* Assign the api key (required) */
  config.api_key = API_KEY;

  /* Assign the RTDB URL (required) */
  config.database_url = DATABASE_URL;

  /* Sign up */
  if (Firebase.signUp(&config, &auth, "", "")){
    Serial.println("ok");
    signupOK = true;
  }
  else{
    Serial.printf("%s\n", config.signer.signupError.message.c_str());
  }

  /* Assign the callback function for the long running token generation task */
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h
  
  Firebase.begin(&config, &auth);
  Firebase.reconnectWiFi(true);
}

void loop(){
  if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)){
    sendDataPrevMillis = millis();
    // Write an Int number on the database path test/int
    if (Firebase.RTDB.setInt(&fbdo, "test/int", count)){
      Serial.println("PASSED");
      Serial.println("PATH: " + fbdo.dataPath());
      Serial.println("TYPE: " + fbdo.dataType());
    }
    else {
      Serial.println("FAILED");
      Serial.println("REASON: " + fbdo.errorReason());
    }
    count++;
    
    // Write an Float number on the database path test/float
    if (Firebase.RTDB.setFloat(&fbdo, "test/float", 0.01 + random(0,100))){
      Serial.println("PASSED");
      Serial.println("PATH: " + fbdo.dataPath());
      Serial.println("TYPE: " + fbdo.dataType());
    }
    else {
      Serial.println("FAILED");
      Serial.println("REASON: " + fbdo.errorReason());
    }
  }
}

How code works

First, include the required libraries. The WiFi.h library connects the ESP32 to the internet (or the ESP8266WiFi.h in the case of the ESP8266 board) and the Firebase_ESP_Client.h library to interface the boards with Firebase.

#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>

You also need to include the following for the Firebase library to work.

//Provide the token generation process info.
#include “addons/TokenHelper.h”
//Provide the RTDB payload printing info and other helper functions.
#include “addons/RTDBHelper.h”
Include your network credentials in the following lines.
#define WIFI_SSID “REPLACE_WITH_YOUR_SSID”
#define WIFI_PASSWORD “REPLACE_WITH_YOUR_PASSWORD”
Insert your firebase project API key—the one you’ve gotten in section 4.1.
#define API_KEY “REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY”

Insert your database URL

#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"

setup()

In the setup(), connect your board to your network.

Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print(“Connecting to Wi-Fi”);
while (WiFi.status() != WL_CONNECTED){
  Serial.print(“.”);
  delay(300);
}
Serial.println();
Serial.print(“Connected with IP: “);
Serial.println(WiFi.localIP());
Serial.println();

Assign the API key and the database URL to the Firebase configuration.

/* Assign the api key (required) */
config.api_key = API_KEY;
/* Assign the RTDB URL (required) */
config.database_url = DATABASE_URL;

The following lines take care of the signup for an anonymous user. Notice that you use the signUp() method, and the last two arguments are empty (anonymous user).

/* Sign up */
if (Firebase.signUp(&config, &auth, “”, “”)){
  Serial.println(“ok”);
  signupOK = true;
}
else{
  Serial.printf(“%s\n”, config.signer.signupError.message.c_str());
}

Note: in the anonymous user signup, every time the ESP connects, it creates a new anonymous user.

If the sign-in is successful, the sign upon variable changes to true.

sign upon = true;

The library provides examples for other authentication methods like signing in as a user with email and password, using the database legacy auth token, etc. You can check all the examples for other authentication methods here. If you use other authentication methods, don’t forget that you need to enable them on your firebase project (Build > Authentication > Sign-in method).

loop()

In the loop(), we’ll send data to the database periodically (if the signup is successful and everything is set up).

if (Firebase.ready() && signupOK && (millis() – sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)){

Send Data to the Database

As the library documentation mentions, to store data at a specific node in the Firebase RTDB (realtime database), use the following functions: set, setInt, setFloat, setDouble, setString, setJSON, setArray, setBlob, and setFile.

These functions return a boolean value indicating the success of the operation, which will be true if all of the following conditions are met:

  • The server returns an HTTP status code of 200.
  • The data types matched between request and response. Only setBlob and settle functions make a silent request to the Firebase server, thus, no payload response is returned.

In our example, we’ll send an integer number, so we need to use the setInt() function as follows:

Firebase.RTDB.setInt(&fbdo, “test/int”, count)

The second argument is the database node path, and the last argument is the value you want to pass to that database path—you can choose any other database path. In this case, we pass the value saved in the count variable.

Here’s the complete snippet that stores the value in the database and prints a success or failed message.

if (Firebase.RTDB.setInt(&fbdo, “test/int”, count)) {
  Serial.println(“PASSED”);
  Serial.println(“PATH: ” + fbdo.dataPath());
  Serial.println(“TYPE: ” + fbdo.dataType());
}
else {
  Serial.println(“FAILED”);
  Serial.println(“REASON: ” + fbdo.errorReason());
}

We proceed in a similar way to store a float value. We’re storing a random float value on the test/float path.

if (Firebase.RTDB.setFloat(&fbdo, “test/float”, 0.01 + random(0, 100))) {

  Serial.println(“PASSED”);

  Serial.println(“PATH: ” + fbdo.dataPath());

  Serial.println(“TYPE: ” + fbdo.dataType());

}

else {

  Serial.println(“FAILED”);

  Serial.println(“REASON: ” + fbdo.errorReason());

}

Demonstration

Upload the code to your ESP32 board. Don’t forget to insert your network credentials, database URL path, and the project API key.

After uploading the code, open the Serial Monitor at a baud rate of 115200 and press the ESP32 on-board reset button so it starts running the code.

ESP32 Read From Firebase Database

In this section, you’ll learn how to read data from the database. We’ll read the data stored in the previous section. Remember that we saved an int value in the test/int path and a float value in the test/float path.

CODE

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>

//Provide the token generation process info.
#include "addons/TokenHelper.h"
//Provide the RTDB payload printing info and other helper functions.
#include "addons/RTDBHelper.h"

// Insert your network credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Insert Firebase project API Key
#define API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"

// Insert RTDB URLefine the RTDB URL */
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL" 

//Define Firebase Data object
FirebaseData fbdo;

FirebaseAuth auth;
FirebaseConfig config;

unsigned long sendDataPrevMillis = 0;
int intValue;
float floatValue;
bool signupOK = false;

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  /* Assign the api key (required) */
  config.api_key = API_KEY;

  /* Assign the RTDB URL (required) */
  config.database_url = DATABASE_URL;

  /* Sign up */
  if (Firebase.signUp(&config, &auth, "", "")) {
    Serial.println("ok");
    signupOK = true;
  }
  else {
    Serial.printf("%s\n", config.signer.signupError.message.c_str());
  }

  /* Assign the callback function for the long running token generation task */
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h

  Firebase.begin(&config, &auth);
  Firebase.reconnectWiFi(true);
}

void loop() {
  if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 15000 || sendDataPrevMillis == 0)) {
    sendDataPrevMillis = millis();
    if (Firebase.RTDB.getInt(&fbdo, "/test/int")) {
      if (fbdo.dataType() == "int") {
        intValue = fbdo.intData();
        Serial.println(intValue);
      }
    }
    else {
      Serial.println(fbdo.errorReason());
    }
    
    if (Firebase.RTDB.getFloat(&fbdo, "/test/float")) {
      if (fbdo.dataType() == "float") {
        floatValue = fbdo.floatData();
        Serial.println(floatValue);
      }
    }
    else {
      Serial.println(fbdo.errorReason());
    }
  }
}

How the Code Works

The code is very similar to the previous section’s example but reads data from the database. Let’s take a look at the relevant parts for this section.

Data at a specific node in Firebase RTDB can be read through the following functions: get, getInt, getFloat, getDouble, getBool, getString, getJSON, getArray, getBlob, getFile.

These functions return a boolean value indicating the success of the operation, which will be true if all of the following conditions were met:

  • The server returns HTTP status code 200
  • The data types matched between request and response.

The database data’s payload (response) can be read or access through the following Firebase Data object’s functions: fbdo.intData, fbdo.floatData, fbdo.doubleData, fbdo.boolData, fbdo.stringData, fbdo.jsonString, fbdo.jsonObject, fbdo.jsonObjectPtr, fbdo.jsonArray, fbdo.jsonArrayPtr, fbdo.jsonData (for keeping parse/get result), and fbdo.blobData.

If you use a function that doesn’t match the returned data type in the database, it will return empty (string, object, or array).

The data type of the returning payload can be determined by fbdo.getDataType.

The following snippet shows how to get an integer value stored in the test/int node. First, we use the getInt() function; then, we check if the data type is an integer with fbdo.dataType(), and finally, the fdbo.intData() gets the value stored in that node.

if (Firebase.RTDB.getInt(&fbdo, “/test/int”)) {
  if (fbdo.dataType() == “int”) {
    intValue = fbdo.intData();
    Serial.println(intValue);
  }
}
else {
  Serial.println(fbdo.errorReason());
}
//We use a similar snippet to get the float value.
if (Firebase.RTDB.getFloat(&fbdo, “/test/float”)) {
  if (fbdo.dataType() == “float”) {
    floatValue = fbdo.floatData();
    Serial.println(floatValue);
  }
}
else {
  Serial.println(fbdo.errorReason());
}

Demonstration

Upload the code to your board. Then, open the Serial Monitor at a baud rate of 115200. After a few seconds, the values saved on the database will be printed.

Conclusion

In this tutorial, you’ve created a Firebase project with a Realtime Database and learned how to store and read data from the database using the ESP32

author avatar
Aravind S S