ESP32: Начало работы с Firebase (Realtime Database)

Это руководство поможет вам быстро начать работу с Firebase, используя плату ESP32. Firebase – это платформа разработки мобильных приложений от Google, которая включает множество сервисов для управления данными из iOS, Android или веб-приложений. Вы создадите проект Firebase с базой данных реального времени (RTDB) и научитесь сохранять и считывать значения из базы данных с помощью ESP32.

ESP32: Начало работы с Firebase (Realtime Database)

Обновлено 21 апреля 2025 года

В следующем руководстве вы узнаете, как создать веб-приложение Firebase, к которому можно получить доступ из любого места для мониторинга и управления ESP32 с использованием базы данных реального времени Firebase:

У нас есть аналогичное руководство для платы ESP8266: Начало работы с Firebase (Realtime Database)

Что такое Firebase?

Логотип Firebase

Firebase – это платформа разработки мобильных приложений от Google, которая помогает создавать, улучшать и развивать ваше приложение. Она имеет множество сервисов для управления данными из любого Android, iOS или веб-приложения.

Следующий абзац четко объясняет преимущества использования Firebase:

«Firebase – это набор инструментов для «создания, улучшения и развития вашего приложения», и инструменты, которые он предоставляет, охватывают большую часть сервисов, которые разработчикам обычно приходится создавать самостоятельно, но они не очень хотят этим заниматься, потому что предпочли бы сосредоточиться на самом опыте использования приложения. Это включает такие вещи, как аналитика, аутентификация, базы данных, конфигурация, хранение файлов, push-уведомления и так далее. Сервисы размещены в облаке и масштабируются практически без усилий со стороны разработчика.»

Этот абзац взят из этой статьи, и мы рекомендуем вам прочитать её, если вы хотите лучше понять, что такое Firebase и что он позволяет делать.

Вы можете использовать ESP32 для подключения и взаимодействия с вашим проектом Firebase и создавать приложения для управления ESP32 через Firebase из любой точки мира.

В этом руководстве мы создадим проект Firebase с базой данных реального времени и используем ESP32 для сохранения и получения данных. После подключения к интернету ESP32 может получить доступ к базе данных из любой точки мира.

У вас может быть две платы ESP32 в разных сетях: одна сохраняет данные, а другая считывает последние данные, например.

Введение в проект ESP32 Firebase с базой данных реального времени

В следующем руководстве мы создадим веб-приложение с использованием Firebase, которое будет управлять ESP32 для отображения показаний датчиков или управления выходами из любой точки мира.

Пример проекта веб-приложения Firebase с ESP32

Обзор проекта

В этом руководстве вы узнаете, как создать проект Firebase с базой данных реального времени и сохранять/считывать данные из базы данных с помощью ESP32.

Для выполнения этого проекта сначала необходимо настроить проект Firebase и создать базу данных реального времени для этого проекта. Затем вы запрограммируете ESP32 для сохранения и чтения данных из базы данных. Это руководство разделено на три раздела.

  1. Создание проекта Firebase

  2. ESP32: Сохранение данных в Firebase Realtime Database

  3. ESP32: Чтение данных из Firebase Realtime Database

Давайте начнём!


Настройка учётной записи Firebase и создание нового проекта

1. Создание нового проекта

Следуйте приведённым ниже инструкциям для создания нового проекта в Firebase.

  1. Перейдите на Firebase и войдите в систему, используя аккаунт Google.

  2. Перейдите в Firebase Console и создайте новый проект.

  3. Дайте вашему проекту имя, например: ESP-Project, и нажмите Continue.

Настройка проекта Firebase для ESP32 и ESP8266 -- шаг 1
  1. Далее включите или отключите AI-помощника для вашего проекта. Это необязательно.

Настройка проекта Firebase для ESP32 и ESP8266 -- включение AI-помощника
  1. Отключите опцию Enable Google Analytics для этого проекта, так как она не нужна. Затем нажмите Create project.

Отключение Google Analytics для проекта Firebase
  1. Настройка вашего проекта займёт несколько секунд. Нажмите Continue, когда он будет готов.

Проект Firebase для ESP32 готов
  1. Вы будете перенаправлены на страницу консоли вашего проекта.

Консоль проекта Firebase

2. Настройка методов аутентификации

Вам необходимо настроить методы аутентификации для вашего приложения.

«Большинству приложений необходимо знать идентификацию пользователя. Другими словами, это заботится о входе в систему и идентификации пользователей (в данном случае ESP32). Знание идентификации пользователя позволяет приложению безопасно сохранять данные пользователя в облаке…» Чтобы узнать больше о методах аутентификации, вы можете прочитать документацию.

  1. На левой боковой панели нажмите Build > Authentication, а затем Get started.

Настройка аутентификации проекта Firebase
  1. Существует несколько методов аутентификации, таких как email и пароль, аккаунт Google, аккаунт Facebook и другие.

Методы аутентификации Firebase
  1. Выберите Email/Password и включите этот метод аутентификации. Затем нажмите Save.

Включение входа по Email/Password в Firebase
  1. Затем в верхней части нажмите на вкладку Users. Затем нажмите Add user.

Создание нового пользователя Firebase
  1. Создайте нового пользователя с email и паролем. Email может быть вашим личным. Создайте пароль для этого пользователя (вам нужно будет запомнить пароль позже). Наконец, нажмите Add user.

Добавление пользователя Firebase с email и паролем
  1. Пользователь появится в списке пользователей. Вы можете видеть информацию о пользователе: когда он был создан, когда последний раз входил в систему, и его User UID.

Пользователь Firebase создан

3. Создание базы данных реального времени

Далее необходимо создать базу данных реального времени для вашего проекта. Выполните следующие шаги для создания базы данных.

  1. На левой боковой панели нажмите Build > Realtime Database, а затем нажмите Create Database.

Создание базы данных в проекте Firebase
  1. Выберите расположение вашей базы данных. Оно должно быть ближайшим к вашему местоположению.

Настройка расположения Firebase Realtime Database
  1. Настройте правила безопасности для вашей базы данных. Для целей тестирования выберите Start in test mode. В следующих руководствах вы узнаете, как защитить свою базу данных с помощью правил безопасности.

Firebase Realtime Database -- запуск в тестовом режиме
  1. Ваша база данных создана. Вам нужно скопировать и сохранить URL базы данных – выделенный на следующем изображении – потому что он понадобится вам позже в коде ESP32.

URL базы данных Firebase Realtime Database

База данных реального времени настроена. Теперь вам также нужно получить API-ключ вашего проекта.

4. Получение API-ключа проекта

  1. Чтобы получить API-ключ вашего проекта, на левой боковой панели нажмите Project Settings.

Настройки проекта Firebase Realtime Database
  1. Скопируйте API Key в безопасное место, так как он понадобится вам позже.

API-ключ проекта Firebase

Теперь у вас всё готово для подключения ESP32 к базе данных.


Программирование ESP32 для работы с Firebase

Теперь, когда Firebase Realtime Database создана, вы узнаете, как подключить ESP32 к базе данных.

Для программирования ESP32 вы можете использовать Arduino IDE, VS Code с расширением PlatformIO или pioarduino, или другое подходящее программное обеспечение.

Примечание

Для проектов Firebase мы рекомендуем использовать VS Code с расширением PlatformIO или pioarduino. Если вы планируете разрабатывать веб-приложение для подключения ESP32 к Firebase, VS Code предоставляет все необходимые инструменты. Однако, поскольку в этом руководстве мы не будем создавать веб-приложение, вы можете просто использовать Arduino IDE, если предпочитаете.

Установка библиотеки FirebaseClient

Существует библиотека с множеством примеров для использования Firebase с ESP32: библиотека FirebaseClient. Эта библиотека совместима с ESP32, ESP8266 и многими другими платами.

В этом руководстве мы рассмотрим простые примеры для сохранения и чтения данных из базы данных. Библиотека предоставляет множество других примеров, которые вы можете посмотреть здесь. Она также предоставляет подробную документацию, объясняющую, как использовать библиотеку.

Установка – VS Code + PlatformIO

Если вы используете VS Code с расширением PlatformIO, нажмите на иконку PIO Home, а затем выберите вкладку Libraries. Найдите «FirebaseClient». Выберите Firebase Client Library от Mobitz.

Установка библиотеки FirebaseClient в VS Code

Затем нажмите Add to Project и выберите проект, над которым вы работаете.

Добавление библиотеки FirebaseClient в проект в VS Code

Также измените скорость монитора на 115200, добавив следующую строку в файл platformio.ini вашего проекта:

monitor_speed = 115200

Установка – Arduino IDE

Если вы используете Arduino IDE, выполните следующие шаги для установки библиотеки.

  1. Перейдите в Sketch > Include Library > Manage Libraries

  2. Найдите FirebaseClient и установите FirebaseClient от Mobitz. Мы используем версию 2.0.3.

Установка библиотеки Firebase Client в Arduino IDE

Теперь всё готово для начала программирования платы ESP32 для взаимодействия с базой данных.


ESP32: Сохранение данных в базу данных Firebase

Пример проекта ESP32 Firebase -- сохранение данных в базу данных реального времени

Скопируйте следующий код в вашу Arduino IDE. Этот скетч вставляет значение int, число float и строку в базу данных каждые 10 секунд. Это простой пример, показывающий, как подключить ESP32 к базе данных для сохранения данных.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp32-firebase-realtime-database/
*********/
#define ENABLE_USER_AUTH
#define ENABLE_DATABASE

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>

// Network and Firebase credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"
#define USER_EMAIL "REPLACE_WITH_FIREBASE_PROJECT_EMAIL_USER"
#define USER_PASS "REPLACE_WITH_FIREBASE_PROJECT_USER_PASS"

// User function
void processData(AsyncResult &aResult);

// Authentication
UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);

// Firebase components
FirebaseApp app;
WiFiClientSecure ssl_client;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client);
RealtimeDatabase Database;

// Timer variables for sending data every 10 seconds
unsigned long lastSendTime = 0;
const unsigned long sendInterval = 10000; // 10 seconds in milliseconds

// Variables to send to the database
int intValue = 0;
float floatValue = 0.01;
String stringValue = "";

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

  // Connect to Wi-Fi
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(300);
  }
  Serial.println();

  // Configure SSL client
  ssl_client.setInsecure();
  ssl_client.setConnectionTimeout(1000);
  ssl_client.setHandshakeTimeout(5);

  // Initialize Firebase
  initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");
  app.getApp<RealtimeDatabase>(Database);
  Database.url(DATABASE_URL);
}

void loop(){
  // Maintain authentication and async tasks
  app.loop();
  // Check if authentication is ready
  if (app.ready()){
    // Periodic data sending every 10 seconds
    unsigned long currentTime = millis();
    if (currentTime - lastSendTime >= sendInterval){
      // Update the last send time
      lastSendTime = currentTime;

      // send a string
      stringValue = "value_" + String(currentTime);
      Database.set<String>(aClient, "/test/string", stringValue, processData, "RTDB_Send_String");
      // send an int
      Database.set<int>(aClient, "/test/int", intValue, processData, "RTDB_Send_Int");
      intValue++; //increment intValue in every loop

      // send a string
      floatValue = 0.01 + random (0,100);
      Database.set<float>(aClient, "/test/float", floatValue, processData, "RTDB_Send_Float");
    }
  }
}

void processData(AsyncResult &aResult) {
  if (!aResult.isResult())
    return;

  if (aResult.isEvent())
    Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.eventLog().message().c_str(), aResult.eventLog().code());

  if (aResult.isDebug())
    Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str());

  if (aResult.isError())
    Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code());

  if (aResult.available())
    Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());
}

Просмотреть исходный код

Вам необходимо вставить ваши сетевые учётные данные, URL базы данных, API-ключ проекта, email и пароль пользователя Firebase.

Этот скетч основан на этом базовом примере, предоставленном библиотекой. Вы можете найти больше примеров здесь.

Как работает код

Продолжайте чтение, чтобы узнать, как работает код, или перейдите к разделу демонстрации.

Подключение библиотек

Сначала подключите необходимые библиотеки. Библиотека WiFi.h для подключения ESP32 к интернету, WiFiClientSecure для создания Wi-Fi клиента и FirebaseClient.h для взаимодействия ESP32 с Firebase.

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>

Определение учётных данных

Укажите ваши сетевые учётные данные в следующих строках.

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

Вставьте API-ключ вашего проекта Firebase – тот, который вы получили в разделе 4.1.

#define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"

Вставьте URL вашей базы данных – смотрите раздел 3.4.

#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"

Установите email пользователя Firebase и соответствующий пароль. Те, которые вы настроили в разделе 2.

#define USER_EMAIL "REPLACE_WITH_FIREBASE_PROJECT_EMAIL_USER"
#define USER_PASS "REPLACE_WITH_FIREBASE_PROJECT_USER_PASS"

Объявление аутентификации и компонентов Firebase

Следующая строка создаёт объект аутентификации, используя API-ключ проекта, email и пароль пользователя проекта.

UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);

Эта строка создаёт экземпляр FirebaseApp с именем app, который ссылается на приложение Firebase.

FirebaseApp app;

Следующие строки настраивают фреймворк асинхронной связи для взаимодействия с базой данных реального времени Firebase. Вы создаёте SSL-клиент с помощью библиотеки WiFiClientSecure. Затем создаёте асинхронный клиент aClient, который обеспечивает безопасное HTTPS-соединение. Это позволит обрабатывать сетевые операции асинхронно.

WiFiClientSecure ssl_client;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client);

Следующая строка создаёт объект RealtimeDatabase с именем Database, который представляет Firebase Realtime Database.

RealtimeDatabase Database;

Переменные таймера и данных

Затем создайте переменные для отслеживания времени и сохранения данных, которые будут отправлены в базу данных.

unsigned long lastSendTime = 0;
const unsigned long sendInterval = 10000; // 10 seconds in milliseconds
int intValue = 0;
float floatValue = 0.01;
String stringValue = "";

setup()

В setup() инициализируйте Serial Monitor и подключите плату к вашей Wi-Fi сети.

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

Настройте SSL-клиент.

ssl_client.setInsecure();
ssl_client.setConnectionTimeout(1000);
ssl_client.setHandshakeTimeout(5);

Следующая строка инициализирует приложение Firebase с аутентификацией и устанавливает processData() в качестве функции обратного вызова для асинхронных результатов (это означает, что любые результаты функции initializeApp() будут обработаны в функции обратного вызова processData()).

initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");

Затем укажите, что вы хотите установить объект Database, определённый ранее, в качестве базы данных для вашего приложения Firebase.

app.getApp<RealtimeDatabase>(Database);

Наконец, установите URL базы данных.

Database.url(DATABASE_URL);

loop()

Библиотека Firebase, которую мы используем, работает асинхронно и с функциями обратного вызова. Это означает, что когда происходит событие, запускаются соответствующие назначенные функции обратного вызова. Чтобы приложение Firebase продолжало работать, обрабатывая аутентификацию и асинхронные задачи, нам нужно добавить app.loop() в начало нашей функции loop().

void loop(){
  app.loop();

Команда app.ready() проверяет, завершена ли аутентификация Firebase и готова ли она, чтобы мы могли продолжить с другими операциями Firebase (например, записью в базу данных).

if (app.ready()){

Следующие строки проверяют, прошло ли 10 секунд (sendInterval). Мы будем использовать это для периодической отправки данных каждые 10 секунд.

unsigned long currentTime = millis();
if (currentTime - lastSendTime >= sendInterval){
  lastSendTime = currentTime;

Отправка данных в базу данных

Далее в loop() мы отправляем наши данные. Мы отправляем три различных типа переменных. Отправка других типов аналогична. Вам просто нужно указать тип в функции set(), как мы объясним.

Библиотека FirebaseClient поддерживает различные методы отправки данных в базу данных реального времени. В этом примере мы используем асинхронный подход с функцией обратного вызова.

Для отправки данных в базу данных мы используем Database.set(). Это шаблонная функция, поддерживающая различные типы данных. Вот общий синтаксис и аргументы:

Database.set<T>(AsyncClient &client, const String &path, T value, AsyncResultCallback callback, const String &uid);

Давайте разберём, как это работает:

  • <T> – тип данных. В коде используется как Database.set<String>, Database.set<int> и Database.set<float>. Вы можете использовать другие типы данных.

  • AsyncClient &client – объект асинхронного клиента (aClient в коде), который управляет сетевым подключением к Firebase.

  • const String &path – путь в Firebase Realtime Database, куда будут записаны данные. Путь относительно корня базы данных (определённого DATABASE_URL). Например: «test/string».

  • T value – значение, которое будет записано по указанному пути.

  • AsyncResultCallback callback – указатель на функцию обратного вызова, которая обрабатывает результат асинхронной операции. В коде это функция processData(). Она обрабатывает объект AsyncResult для записи событий, ошибок, отладочных сообщений или успешных данных. Функция обратного вызова вызывается, когда сервер Firebase отвечает или если во время запроса возникает ошибка.

  • const String &uid – уникальный идентификатор задачи, используемый для отслеживания конкретной операции в функции обратного вызова. Это помогает различать несколько асинхронных задач в функции processData().

Например, следующие строки отправляют строку в базу данных.

stringValue = "value_" + String(currentTime);
Database.set<String>(aClient, "/test/string", stringValue, processData, "RTDB_Send_String");
  • Клиент: aClient (управляет HTTPS-соединением).

  • Путь: «/test/string».

  • Значение: переменная stringValue, содержащая String.

  • Обратный вызов: processData (обрабатывает результат).

  • UID: «RTDB_Send_String» (идентифицирует эту задачу в логах).

Отправка целого числа и числа с плавающей точкой аналогична.

// send an int
Database.set<int>(aClient, "/test/int", intValue, processData, "RTDB_Send_Int");
intValue++; //increment intValue in every loop

// send a string
floatValue = 0.01 + random (0,100);
Database.set<float>(aClient, "/test/float", floatValue, processData, "RTDB_Send_Float");

Обработка асинхронных результатов

Наконец, функция processData() записывает результаты асинхронных операций Firebase.

void processData(AsyncResult &aResult) {
  if (!aResult.isResult())
    return;

  if (aResult.isEvent())
    Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.eventLog().message().c_str(), aResult.eventLog().code());

  if (aResult.isDebug())
    Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str());

  if (aResult.isError())
    Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code());

  if (aResult.available())
    Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());
}

Демонстрация

Загрузите код на вашу плату ESP32. Не забудьте вставить ваши сетевые учётные данные, URL базы данных, API-ключ проекта, email и пароль пользователя Firebase.

После загрузки кода откройте Serial Monitor на скорости 115200 бод и нажмите кнопку сброса на плате ESP32, чтобы запустить выполнение кода.

Если всё работает правильно, значения должны сохраняться в базе данных, и вы должны получить сообщения об успешном выполнении.

ESP32 отправка данных в Realtime Database Firebase -- демонстрация Serial Monitor

Перейдите в Firebase Realtime Database вашего проекта, и вы увидите значения, сохранённые по различным путям узлов. Каждые 10 секунд сохраняется новое значение. База данных мигает при сохранении новых значений.

ESP32 -- успешное сохранение значений в базе данных Firebase

Поздравляем! Вы успешно сохранили данные в Firebase Realtime Database с помощью ESP32. В следующем разделе вы узнаете, как считывать значения из различных путей узлов базы данных.


ESP32: Чтение данных из базы данных Firebase

Пример проекта ESP32 Firebase -- получение данных из базы данных реального времени

В этом разделе вы узнаете, как читать данные из базы данных. Мы будем считывать данные, сохранённые в предыдущем разделе. Напомним, что мы сохранили значение int по пути test/int, значение float по пути test/float и значение String по пути test/string.

Существуют разные способы получения значений из базы данных. Мы покажем вам, как это сделать синхронно и асинхронно.

ESP32 – Чтение из Firebase RTDB (асинхронный режим)

Следующий пример считывает значения, сохранённые в базе данных, используя асинхронный метод. Загрузите следующий код на вашу плату. Вы можете использовать ту же плату ESP32 или другую плату для получения данных, отправленных предыдущим ESP32.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp32-firebase-realtime-database/
*********/
#define ENABLE_USER_AUTH
#define ENABLE_DATABASE

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>

// Network and Firebase credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"
#define USER_EMAIL "REPLACE_WITH_FIREBASE_PROJECT_EMAIL_USER"
#define USER_PASS "REPLACE_WITH_FIREBASE_PROJECT_USER_PASS"

// User function
void processData(AsyncResult &aResult);

// Authentication
UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);

// Firebase components
FirebaseApp app;
WiFiClientSecure ssl_client;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client);
RealtimeDatabase Database;

// Timer variables for reading data every 10 seconds
unsigned long lastSendTime = 0;
const unsigned long sendInterval = 10000; // 10 seconds in milliseconds

// Variables to save values from the database
int intValue;
float floatValue;
String stringValue;

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

  // Connect to Wi-Fi
  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();

  // Configure SSL client
  ssl_client.setInsecure();
  ssl_client.setConnectionTimeout(1000);
  ssl_client.setHandshakeTimeout(5);

  // Initialize Firebase
  initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");
  app.getApp<RealtimeDatabase>(Database);
  Database.url(DATABASE_URL);
}

void loop(){
  // Maintain authentication and async tasks
  app.loop();

  // Check if authentication is ready
  if (app.ready()){
    // Getting data every 10 seconds
    unsigned long currentTime = millis();
    if (currentTime - lastSendTime >= sendInterval){
      // Update the last send time
      lastSendTime = currentTime;

      // GET VALUES FROM DATABASE (using the callback async method method)
      // you can then get the values on the processData function as soon as the results are available
      Database.get(aClient, "/test/int", processData, false, "RTDB_GetInt");
      Database.get(aClient, "/test/float", processData, false, "RTDB_GetFloat");
      Database.get(aClient, "/test/string", processData, false, "RTDB_GetString");

      Serial.println("Requested data from /test/int, /test/float, and /test/string");
    }
  }
}

void processData(AsyncResult &aResult){
  if (!aResult.isResult())
    return;

  if (aResult.isEvent())
    Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.eventLog().message().c_str(), aResult.eventLog().code());

  if (aResult.isDebug())
    Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str());

  if (aResult.isError())
    Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code());

  // here you get the values from the database and save them in variables if you need to use them later
  if (aResult.available())    {
    // Log the task and payload
    Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());

    // Extract the payload as a String
    String payload = aResult.c_str();

    /// Handle int from /test/int
    if (aResult.uid() == "RTDB_GetInt"){
      // Extract the value as an int
      intValue = payload.toInt();
      Firebase.printf("Stored intValue: %d\n", intValue);
    }
    // Handle float from /test/float
    else if (aResult.uid() == "RTDB_GetFloat"){
      // Extract the value as a float
      floatValue = payload.toFloat();
      Firebase.printf("Stored floatValue: %.2f\n", floatValue);
    }

    // Handle String from /test/string
    else if (aResult.uid() == "RTDB_GetString"){
      // Extract the value as a String
      stringValue = payload;
      Firebase.printf("Stored stringValue: %s\n", stringValue.c_str());
    }
  }
}

Просмотреть исходный код

Вам необходимо вставить ваши сетевые учётные данные, URL базы данных, API-ключ проекта, email и пароль пользователя Firebase.

Как работает код

Первые разделы кода очень похожи на предыдущий пример. Он подключается и аутентифицируется в Firebase и настраивает подключение к базе данных. Затем он получает данные из базы данных в асинхронном режиме. Результаты операции (значения переменных) затем обрабатываются в функции обратного вызова.

Получение данных из базы данных

Для получения данных нам нужно знать точный путь, где они находятся, и их тип (для последующей обработки). Мы можем получить их, используя метод get() объекта Database, следующим образом.

Database.get(AsyncClient &client, const String &path, AsyncResultCallback callback, bool queue, const String &uid);

Вот как это работает:

  • AsyncClient &client – объект асинхронного клиента (aClient в коде), который управляет сетевым подключением к Firebase.

  • const String &path – путь в Firebase Realtime Database, откуда мы получим данные. Путь относительно корня базы данных (определённого DATABASE_URL). Например: «test/string».

  • AsyncResultCallback callback – указатель на функцию обратного вызова, которая обрабатывает результат асинхронной операции. В коде это функция processData(). В этом примере именно здесь мы получим фактические данные из базы данных и сохраним их в переменные.

  • bool queue – флаг, указывающий, должна ли операция быть поставлена в очередь, если клиент занят другой задачей. Установите false для немедленного выполнения или true для постановки запроса в очередь. В более сложных примерах рекомендуется устанавливать значение true.

  • const String &uid – уникальный идентификатор задачи, используемый для отслеживания конкретной операции в функции обратного вызова. Это помогает различать несколько асинхронных задач в функции processData().

Как видите, функция get() очень похожа на функцию set(), которую мы рассматривали ранее.

Например, в следующей строке мы устанавливаем операцию чтения из узла базы данных /test/int. Эта операция будет обработана в задаче с идентификатором RTDB_GetInt.

Database.get(aClient, "/test/int", processData, false, "RTDB_GetInt");

Аналогично мы получаем значения из других путей узлов.

Database.get(aClient, "/test/float", processData, false, "RTDB_GetFloat");
Database.get(aClient, "/test/string", processData, false, "RTDB_GetString");

Сохранение данных в переменные

Результат операции get() затем обрабатывается в функции processData().

Оператор if (aResult.available()) проверяет, содержит ли AsyncResult успешный результат с данными, доступными для обработки. Если available() возвращает true, это означает, что у нас есть данные для обработки – мы успешно получили данные из базы данных.

if (aResult.available())  {
  // Log the task and payload
  Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());

Мы можем получить данные следующим образом:

String payload = aResult.c_str();

Затем с помощью aResult.uid() мы можем проверить, какая операция произошла, по имени задачи, и затем сохранить данные в переменную соответствующего типа.

/// Handle int from /test/int
if (aResult.uid() == "RTDB_GetInt"){
  // Extract the value as an int
  intValue = payload.toInt();
  Firebase.printf("Stored intValue: %d\n", intValue);
}
// Handle float from /test/float
else if (aResult.uid() == "RTDB_GetFloat"){
  // Extract the value as a float
  floatValue = payload.toFloat();
  Firebase.printf("Stored floatValue: %.2f\n", floatValue);
}

// Handle String from /test/string
else if (aResult.uid() == "RTDB_GetString"){
  // Extract the value as a String
  stringValue = payload;
  Firebase.printf("Stored stringValue: %s\n", stringValue.c_str());
}

Демонстрация

Загрузите код на вашу плату. Затем откройте Serial Monitor на скорости 115200 бод. Через несколько секунд он выведет значения, сохранённые в базе данных.

ESP32 получение данных из Firebase Realtime Database -- результат Serial Monitor

ESP32 – Чтение из Firebase RTDB (без асинхронного режима)

Для более простых приложений, где вам не нужно ставить задачи в очередь и блокировка кода не критична во время ожидания операции с базой данных, вы можете использовать функцию get() в упрощённом формате. Это позволяет вам напрямую получить значение из Firebase Realtime Database и немедленно сохранить его в переменную.

Например:

int intValue =  Database.get<int>(aClient, "/test/int");

Database.get<int>(aClient, "/test/int") синхронно получает целое число из пути /test/int Firebase RTDB, используя aClient, присваивает его intValue и блокирует выполнение до завершения. Это идеально подходит для простых приложений, где вам не нужно несколько задач, но это может задержать другие операции.

Вот пример кода, использующий этот метод. Он работает точно так же, как предыдущий пример. Но для более сложных приложений следует использовать асинхронный метод.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp32-firebase-realtime-database/
*********/

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>

// Network and Firebase credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"
#define USER_EMAIL "REPLACE_WITH_FIREBASE_PROJECT_EMAIL_USER"
#define USER_PASS "REPLACE_WITH_FIREBASE_PROJECT_USER_PASS"

// User function
void processData(AsyncResult &aResult);

// Authentication
UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);

// Firebase components
FirebaseApp app;
WiFiClientSecure ssl_client;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client);
RealtimeDatabase Database;

// Timer variables for sending data every 10 seconds
unsigned long lastSendTime = 0;
const unsigned long sendInterval = 10000; // 10 seconds in milliseconds

// Variables to save values from the database
int intValue;
float floatValue;
String stringValue;

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

  // Connect to Wi-Fi
  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();

  // Configure SSL client
  ssl_client.setInsecure();
  ssl_client.setConnectionTimeout(1000);
  ssl_client.setHandshakeTimeout(5);

  // Initialize Firebase
  initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");
  app.getApp<RealtimeDatabase>(Database);
  Database.url(DATABASE_URL);
}

void loop(){
  // Maintain authentication and async tasks
  app.loop();

  // Check if authentication is ready
  if (app.ready()){
    // Periodic data sending every 10 seconds
    unsigned long currentTime = millis();
    if (currentTime - lastSendTime >= sendInterval){
      // Update the last send time
      lastSendTime = currentTime;

      // GET VALUES FROM DATABASE (and save the data in a variable)
      int intValue =  Database.get<int>(aClient, "/test/int");
      check_and_print_value (intValue);

      float floatValue = Database.get<float>(aClient, "/test/float");
      check_and_print_value(floatValue);

      String stringValue = Database.get<String>(aClient, "/test/string");
      check_and_print_value(stringValue);

      Serial.println("Requested data from /test/int, /test/float, and /test/string");
    }
  }
}

template <typename T>
void check_and_print_value(T value){
  // To make sure that we actually get the result or error.
  if (aClient.lastError().code() == 0){
    Serial.print("Success, Value: ");
    Serial.println(value);
  }
  else {
    Firebase.printf("Error, msg: %s, code: %d\n", aClient.lastError().message().c_str(), aClient.lastError().code());
  }
}

void processData(AsyncResult &aResult){
  if (!aResult.isResult())
    return;

  if (aResult.isEvent())
    Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.eventLog().message().c_str(), aResult.eventLog().code());

  if (aResult.isDebug())
    Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str());

  if (aResult.isError())
    Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code());

  if (aResult.available()){
    // Log the task and payload
    Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());
  }
}

Просмотреть исходный код


Заключение

Поздравляем! В этом руководстве вы создали проект Firebase с базой данных реального времени и научились сохранять и считывать данные из базы данных с помощью ESP32.

Для простоты мы сохраняли примеры значений в базе данных. Идея состоит в том, чтобы сохранять полезные данные, такие как показания датчиков или состояние GPIO.

Затем вы можете получить доступ к базе данных с помощью другого ESP32 для получения данных или создать веб-приложение Firebase для использования этих данных для отображения показаний датчиков или управления GPIO ESP32 из любой точки мира. Мы рассматриваем основы создания веб-приложения Firebase в этом руководстве.

Если вы хотите узнать больше о Firebase с ESP32 и ESP8266, ознакомьтесь с электронной книгой:

Если вы хотите узнать больше о ESP32, ознакомьтесь с курсами:


Примечание

Данная статья является переводом оригинальной статьи с сайта Random Nerd Tutorials.