Firebase: Управление GPIO ESP32 из любой точки мира
В этом руководстве вы узнаете, как управлять GPIO ESP32 из любой точки мира с помощью Firebase. Мы создадим узлы в Firebase Realtime Database для сохранения текущих состояний GPIO. Всякий раз, когда в узлах базы данных происходит изменение, ESP32 соответствующим образом обновляет свои GPIO. Вы можете изменять состояния GPIO, записывая данные в базу данных вручную, или можете создать веб-приложение для этого (смотрите это руководство).
Обновлено 26 мая 2025 г.
ЧАСТЬ 2: Управление GPIO ESP32/ESP8266 из любой точки мира (Firebase Web App)
У нас есть аналогичное руководство для платы ESP8266: Firebase: Управление GPIO ESP8266 NodeMCU из любой точки мира.
Другие руководства по Firebase с ESP32/ESP8266, которые могут вас заинтересовать:
ESP32 Firebase: Отправка показаний BME280 в Realtime Database
ESP32: Firebase Web App для отображения показаний датчиков (с аутентификацией)
ESP32: Firebase Data Logging Web App (Gauges, Charts и Table)
Что такое Firebase?
Firebase — это платформа разработки мобильных приложений Google, которая помогает вам создавать, улучшать и развивать ваше приложение. Firebase предоставляет бесплатные сервисы, такие как хостинг (hosting), аутентификация (authentication) и база данных реального времени (realtime database), которые позволяют создать полнофункциональное веб-приложение для управления и мониторинга плат ESP32 и ESP8266, что было бы гораздо сложнее и трудоёмнее создавать и настраивать самостоятельно.
Обзор проекта
На следующей диаграмме показан общий обзор проекта, который мы создадим.
ESP32 аутентифицируется как пользователь с email и паролем, чтобы получить доступ к базе данных (этот пользователь должен быть добавлен в методы аутентификации Firebase);
База данных защищена с помощью правил базы данных. Мы добавим следующее правило: только аутентифицированные пользователи могут получить доступ к базе данных;
В базе данных есть несколько узлов, которые сохраняют состояния GPIO ESP32. В качестве примера мы будем управлять тремя GPIO (12, 13 и 14). Вы можете добавлять или удалять узлы для управления большим или меньшим количеством GPIO.
ESP32 будет прослушивать изменения в узлах GPIO базы данных. Всякий раз, когда происходит изменение, он обновляет состояния GPIO соответствующим образом.
Вы можете изменять состояния GPIO вручную в базе данных с помощью консоли Firebase, или вы можете создать веб-страницу (доступную из любой точки мира) с кнопками для управления GPIO и отображения текущих состояний GPIO (смотрите ЧАСТЬ 2).
Вот основные шаги для завершения этого проекта:
Создать проект Firebase
Настроить методы аутентификации
Получить API-ключ проекта
Настроить Realtime Database
Настроить правила безопасности базы данных
Организовать узлы базы данных
ESP32: Прослушивание изменений базы данных (управление GPIO)
Подготовка Arduino IDE
Для этого руководства мы будем программировать плату ESP32 с использованием ядра Arduino. Убедитесь, что у вас установлено дополнение ESP32 в Arduino IDE:
Если вы хотите программировать платы ESP32/ESP8266 с помощью VS Code с расширениями pioarduino или PlatformIO, следуйте этим руководствам:
1) Создание проекта Firebase
Следуйте приведённым ниже инструкциям, чтобы создать новый проект в Firebase.
Перейдите в Firebase и войдите с помощью учётной записи Google.
Перейдите в Firebase Console и создайте новый проект.
Дайте имя вашему проекту, например: ESP-Project, и нажмите Continue.
Далее включите или отключите AI-помощника для вашего проекта. Это необязательно.
Отключите опцию Enable Google Analytics для этого проекта, так как она не нужна. Затем нажмите Create project.
Настройка проекта займёт несколько секунд. Нажмите Continue, когда всё будет готово.
Вы будете перенаправлены на страницу консоли вашего проекта.
2) Настройка методов аутентификации
Чтобы разрешить аутентификацию с помощью email и пароля, сначала необходимо настроить методы аутентификации для вашего приложения.
«Большинству приложений необходимо знать идентификацию пользователя. Другими словами, это заботится о входе в систему и идентификации пользователей (в данном случае ESP32 или ESP8266). Знание идентификации пользователя позволяет приложению безопасно сохранять данные пользователя в облаке и обеспечивать одинаковый персонализированный опыт на всех устройствах пользователя.» Чтобы узнать больше о методах аутентификации, вы можете прочитать документацию.
На левой боковой панели нажмите на Build > Authentication, а затем на Get started.
Существует несколько методов аутентификации, таких как email и пароль, учётная запись Google, учётная запись Facebook и другие.
Выберите Email/Password и включите этот метод аутентификации. Затем нажмите Save.
Затем вверху нажмите на вкладку Users. После этого нажмите Add user.
Создайте нового пользователя с email и паролем. Email может быть вашим личным. Создайте пароль для этого пользователя (вам нужно будет запомнить пароль позже). Наконец, нажмите Add user.
Пользователь появится в списке пользователей. Вы можете увидеть информацию о пользователе, например, когда он был создан, когда последний раз входил в систему, и его User UID.
Firebase создаёт уникальный UID для каждого зарегистрированного пользователя. User UID позволяет нам идентифицировать пользователя и отслеживать его для предоставления или отказа в доступе к проекту или базе данных. Также есть столбец, который регистрирует дату последнего входа. На данный момент он пуст, потому что мы ещё не входили с этим пользователем.
Скопируйте User UID, потому что он понадобится вам позже.
3) Получение API-ключа проекта
Для взаимодействия с вашим проектом Firebase с помощью плат ESP32 или ESP8266 вам нужно получить API-ключ вашего проекта. Следуйте приведённым ниже шагам, чтобы получить API-ключ вашего проекта.
Чтобы получить API-ключ вашего проекта, на левой боковой панели нажмите Project Settings.
Скопируйте API Key в безопасное место, потому что он понадобится вам позже.
4) Настройка Realtime Database
Теперь давайте создадим базу данных реального времени и настроим правила базы данных для нашего проекта.
1) На левой боковой панели нажмите Realtime Database, а затем нажмите Create Database.
2) Выберите расположение вашей базы данных. Оно должно быть ближайшим к вашему местоположению.
3) Настройте правила безопасности для вашей базы данных. Вы можете выбрать Start in test mode. Мы изменим правила базы данных чуть позже.
4) Ваша база данных создана. Вам нужно скопировать и сохранить URL базы данных — выделенный на следующем изображении — потому что он понадобится вам позже в коде ESP32/ESP8266.
5) Настройка правил безопасности базы данных
Теперь давайте настроим правила базы данных. На вкладке Realtime Database выберите вкладку Rules вверху. Затем нажмите Edit rules и добавьте следующие правила.
{
"rules": {
".read": "auth.uid === 'REPLACE_WITH_YOUR_USER_UID'",
".write": "auth.uid === 'REPLACE_WITH_YOUR_USER_UID'"
}
}
Вставьте UID пользователя, которого вы создали ранее. Затем нажмите Publish.
Эти правила базы данных определяют, что:
Только пользователь с этим конкретным UID может читать и записывать данные в базу данных (изменять состояния GPIO).
Добавление дополнительных пользователей
Чтобы добавить больше пользователей, просто перейдите на вкладку Authentication и нажмите Add user. Добавьте email и пароль для нового пользователя, и наконец нажмите Add user, чтобы создать пользователя.
Скопируйте User UID этого нового пользователя и добавьте его в правила базы данных следующим образом:
{
"rules": {
".read": "auth.uid === 'REPLACE_WITH_YOUR_USER_UID' || auth.uid === 'REPLACE_WITH_USER_UID2'",
".write": "auth.uid === 'REPLACE_WITH_YOUR_USER_UID' || auth.uid === 'REPLACE_WITH_USER_UID2'"
}
}
Например. В моём случае UID пользователей: RjO3taAzMMXB82Xmir2LQ7XXXXXX и 9QdDc9as5mRXGAjEsQiUJkXXXXXX. Таким образом, правила базы данных будут выглядеть следующим образом:
{
"rules": {
".read": "auth.uid === 'RjO3taAzMMXB82Xmir2LQ7XXXXXX' || auth.uid === '9QdDc9as5mRXGAjEsQiUJkXXXXXX'",
".write": "auth.uid === 'RjO3taAzMMXB82Xmir2LQ7XXXXXX' || auth.uid === '9QdDc9as5mRXGAjEsQiUJkXXXXXX'"
}
}
Наконец, опубликуйте ваши правила базы данных.
Чтобы узнать больше о правилах базы данных, вы можете ознакомиться с документацией Firebase.
6) Организация узлов базы данных
Все данные, хранящиеся в Firebase Realtime Database, хранятся как JSON-объекты. Таким образом, вы можете думать о базе данных как об облачном JSON-дереве. Когда вы добавляете данные в JSON-дерево, они становятся узлом с ассоциированным ключом в существующей структуре JSON.
Не знакомы с JSON? Прочитайте это краткое руководство.
Мы хотим управлять GPIO ESP32. Мы можем организовать данные таким образом, чтобы было легко добавлять больше GPIO и плат в будущем. Итак, мы можем структурировать базу данных следующим образом:
board1: - outputs:
digital: - 12: 0 - 13: 0 - 14: 0
В формате JSON это будет выглядеть так:
{
"board1": {
"outputs": {
"digital": {
"12": 0,
"13": 0,
"14": 0
}
}
}
}
Создание узлов базы данных
Теперь давайте создадим узлы базы данных в нашей базе данных. Вы можете создать узлы вручную, записывая их в консоли Firebase, в веб-приложении или через ESP32. Мы создадим их вручную, чтобы было проще следовать руководству.
1) Нажмите на Realtime Database, чтобы начать создание узлов.
2) Вы можете создавать узлы базы данных вручную, используя значки (+) в базе данных. Однако, чтобы избежать опечаток, мы предоставляем JSON-файл, который вы можете загрузить для создания тех же узлов, что и наши. Нажмите на ссылку ниже, чтобы скачать JSON-файл.
После скачивания распакуйте папку, чтобы получить доступ к файлу .json.
3) Теперь вернитесь к вашей базе данных в консоли Firebase. Нажмите на значок с тремя точками и выберите Import JSON.
4) Выберите JSON-файл, который вы только что скачали.
5) Ваша база данных должна выглядеть так, как показано ниже.
Все узлы базы данных, необходимые для этого проекта, созданы. Вы можете перейти к следующему разделу.
7) ESP32: Прослушивание изменений базы данных (управление GPIO)
В этом разделе мы запрограммируем плату ESP32 для выполнения следующих задач:
Аутентификация как пользователь с email и паролем (пользователь, которого вы настроили в разделе аутентификации);
Прослушивание изменений базы данных в узлах GPIO и соответствующее изменение их состояний.
Необходимые компоненты
Для этого проекта вам понадобятся следующие компоненты:
Схема подключения
В этом примере мы будем управлять тремя светодиодами, подключёнными к GPIO 12, 13 и 14. Подключите три светодиода к ESP32. Вы можете следовать схеме подключения ниже.
Вы можете использовать любые другие подходящие GPIO ESP32, но вам также нужно будет изменить узлы базы данных.
Установка библиотек
Для этого руководства вам нужно установить библиотеку FirebaseClient.
Установка — Arduino IDE
Следуйте этому разделу, если вы используете Arduino IDE.
Перейдите в Sketch > Include Library > Manage Libraries, найдите название библиотеки и установите её.
Теперь вы готовы начать программирование плат ESP32 и ESP8266 для взаимодействия с базой данных.
Установка библиотек — VS Code
Следуйте этим инструкциям, если вы используете VS Code с расширением PlatformIO или pioarduino.
Установка библиотеки FirebaseClient
Нажмите на значок PIO Home и выберите вкладку Libraries. Найдите «FirebaseClient». Выберите FirebaseClient Library от Mobitz.
Затем нажмите Add to Project и выберите проект, над которым вы работаете.
Также измените скорость монитора на 115200, добавив следующую строку в файл platformio.ini вашего проекта:
monitor_speed = 115200
Код прослушивания изменений базы данных (состояния GPIO)
Скопируйте следующий код в Arduino IDE или в файл main.cpp, если вы используете VS Code.
Вам нужно вставить следующие данные в код перед загрузкой на вашу плату:
ваши сетевые учётные данные
API-ключ проекта
URL базы данных
email и пароль авторизованного пользователя
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at our blog.
- ESP32: https://RandomNerdTutorials.com/firebase-control-esp32-gpios/
- ESP8266: https://RandomNerdTutorials.com/firebase-control-esp8266-nodemcu-gpios/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Based in the RTDB Basic Example by Firebase-ESP-Client library by mobizt
https://github.com/mobizt/FirebaseClient/blob/main/examples/RealtimeDatabase/Get/Get.ino
*/
#define ENABLE_USER_AUTH
#define ENABLE_DATABASE
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>
#include "ExampleFunctions.h" // Provides the functions used in the examples.
#include <ArduinoJson.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 functions
void processData(AsyncResult &aResult);
// Authentication
UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);
SSL_CLIENT ssl_client, stream_ssl_client;
// Firebase components
FirebaseApp app;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client), streamClient(stream_ssl_client);
RealtimeDatabase Database;
// Timer variables for loop
unsigned long lastSendTime = 0;
const unsigned long sendInterval = 10000; // 10 seconds in milliseconds
// Database path (where the data is)
String listenerPath = "board1/outputs/digital/";
// Declare outputs
const int output1 = 12;
const int output2 = 13;
const int output3 = 14;
// Initialize WiFi
void initWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
Serial.println();
}
void setup(){
Serial.begin(115200);
// Declare pins as outputs
pinMode(output1, OUTPUT);
pinMode(output2, OUTPUT);
pinMode(output3, OUTPUT);
initWiFi();
// Configure SSL client
ssl_client.setInsecure();
stream_ssl_client.setInsecure();
#if defined(ESP32)
ssl_client.setConnectionTimeout(1000);
ssl_client.setHandshakeTimeout(5);
stream_ssl_client.setConnectionTimeout(1000);
stream_ssl_client.setHandshakeTimeout(5);
#elif defined(ESP8266)
ssl_client.setTimeout(1000); // Set connection timeout
ssl_client.setBufferSizes(4096, 1024); // Set buffer sizes
stream_ssl_client.setTimeout(1000); // Set connection timeout
stream_ssl_client.setBufferSizes(4096, 1024); // Set buffer sizes
#endif
// Initialize Firebase
initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");
app.getApp<RealtimeDatabase>(Database);
Database.url(DATABASE_URL);
// Set a database listener
streamClient.setSSEFilters("get,put,patch,keep-alive,cancel,auth_revoked");
Database.get(streamClient, listenerPath, processData, true /* SSE mode (HTTP Streaming) */, "streamTask");
}
void loop(){
// Maintain authentication and async tasks
app.loop();
// Check if authentication is ready
if (app.ready()){
//Do nothing - everything works with callback functions
unsigned long currentTime = millis();
if (currentTime - lastSendTime >= sendInterval){
// Update the last send time
lastSendTime = currentTime;
Serial.printf("Program running for %lu\n", currentTime);
}
}
}
void processData(AsyncResult &aResult){
// Exits when no result available when calling from the loop.
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());
}
// When it receives data from the database
if (aResult.available()){
RealtimeDatabaseResult &RTDB = aResult.to<RealtimeDatabaseResult>();
// we received data from the streaming client
if (RTDB.isStream()) {
Serial.println("----------------------------");
Firebase.printf("task: %s\n", aResult.uid().c_str());
Firebase.printf("event: %s\n", RTDB.event().c_str());
Firebase.printf("path: %s\n", RTDB.dataPath().c_str());
Firebase.printf("etag: %s\n", RTDB.ETag().c_str());
Firebase.printf("data: %s\n", RTDB.to<const char *>());
Firebase.printf("type: %d\n", RTDB.type());
// RTDB.type = 6 means the result is a JSON : https://github.com/mobizt/FirebaseClient/blob/main/resources/docs/realtime_database_result.md#--realtime_database_data_type-type
// You receive a JSON when you initialize the stream
if (RTDB.type() == 6) {
Serial.println(RTDB.to<String>());
// Parse JSON
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc, RTDB.to<String>());
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
// Iterate through JSON object
for (JsonPair kv : doc.as<JsonObject>()) {
int gpioPin = atoi(kv.key().c_str()); // Convert key (e.g., "12") to int
bool state = kv.value().as<bool>();
digitalWrite(gpioPin, state ? HIGH : LOW);
}
}
// RTDB.type() = 4 means the result is a boolean
// RTDB.type() = 1 means the result is an integer
// learn more here: https://github.com/mobizt/FirebaseClient/blob/main/resources/docs/realtime_database_result.md#--realtime_database_data_type-type
if (RTDB.type() == 4 || RTDB.type() == 1){
// get the GPIO number
int GPIO_number = RTDB.dataPath().substring(1).toInt();
bool state = RTDB.to<bool>();
digitalWrite(GPIO_number, state);
Serial.println("Updating GPIO State");
}
// The stream event from RealtimeDatabaseResult can be converted to values as following.
/*bool v1 = RTDB.to<bool>();
int v2 = RTDB.to<int>();
float v3 = RTDB.to<float>();
double v4 = RTDB.to<double>();
String v5 = RTDB.to<String>();
Serial.println(v5); */
}
else{
Serial.println("----------------------------");
Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str());
}
}
}
Как работает код
Продолжайте чтение, чтобы узнать, как работает код, или перейдите к разделу демонстрации.
Подключение библиотек
Сначала подключите необходимые библиотеки. Этот код также совместим с ESP8266.
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>
#include "ExampleFunctions.h" // Provides the functions used in the examples.
#include <ArduinoJson.h>
Сетевые учётные данные
Укажите ваши сетевые учётные данные в следующих строках, чтобы ваши платы могли подключиться к интернету через вашу локальную сеть.
// Network and Firebase credentials
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
API-ключ проекта Firebase, пользователь Firebase и URL базы данных
Вставьте API-ключ вашего проекта Firebase — тот, который вы получили в разделе получения API-ключа.
#define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY"
Вставьте URL вашей базы данных в следующую строку:
#define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL"
Вставьте авторизованный email и соответствующий пароль — это данные пользователя, которого вы добавили в разделе настройки аутентификации.
#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);
Создайте два SSL-клиента. Один для обработки операций Firebase, а другой для потоковой передачи базы данных (необходим для прослушивания изменений базы данных).
SSL_CLIENT ssl_client, stream_ssl_client;
Это создаёт экземпляр FirebaseApp под названием app, который ссылается на приложение Firebase.
FirebaseApp app;
Следующие строки настраивают фреймворк асинхронной связи для взаимодействия с Firebase Realtime Database. Вам нужно создать экземпляр асинхронного клиента aClient, который обеспечивает безопасный HTTPS для обработки операций Firebase, и другой — streamClient — для обработки потоковой передачи базы данных (прослушивание изменений базы данных). Это позволит вам обрабатывать сетевые операции и потоковую передачу базы данных асинхронно.
FirebaseApp app;
using AsyncClient = AsyncClientClass;
AsyncClient aClient(ssl_client), streamClient(stream_ssl_client);
Следующая строка создаёт объект RealtimeDatabase под названием Database, который представляет Firebase Realtime Database.
RealtimeDatabase Database;
Путь базы данных
Затем создайте переменную, которая сохраняет путь базы данных, по которому мы будем прослушивать изменения. Учитывая структуру базы данных, которую мы создали ранее, путь прослушивания должен быть следующим:
// Database path (where the data is)
String listenerPath = "board1/outputs/digital/";
Если вы хотите добавить больше плат, вам просто нужно изменить путь прослушивания соответствующим образом.
Создайте переменные для выходов, которыми вы будете управлять. В нашем случае мы управляем GPIO 12, 13 и 14. Вы можете управлять любыми другими GPIO ESP32 (вам также нужно будет изменить узлы базы данных):
const int output1 = 12;
const int output2 = 13;
const int output3 = 14;
initWifi()
Функция initWifi() подключает ESP32 к вашей локальной сети. Мы вызовем её позже в setup() для инициализации Wi-Fi.
// Initialize WiFi
void initWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
Serial.println();
}
setup()
Давайте теперь перейдём к setup().
Инициализируйте Serial Monitor:
Serial.begin(115200);
Объявите ваши GPIO как выходы с помощью функции pinMode().
pinMode(output1, OUTPUT);
pinMode(output2, OUTPUT);
pinMode(output3, OUTPUT);
Вызовите функцию initWiFi(), которую мы создали ранее, чтобы подключить вашу плату к локальной сети.
initWiFi();
Настройте SSL-клиент.
// Configure SSL client
ssl_client.setInsecure();
stream_ssl_client.setInsecure();
#if defined(ESP32)
ssl_client.setConnectionTimeout(1000);
ssl_client.setHandshakeTimeout(5);
stream_ssl_client.setConnectionTimeout(1000);
stream_ssl_client.setHandshakeTimeout(5);
#elif defined(ESP8266)
ssl_client.setTimeout(1000); // Set connection timeout
ssl_client.setBufferSizes(4096, 1024); // Set buffer sizes
stream_ssl_client.setTimeout(1000); // Set connection timeout
stream_ssl_client.setBufferSizes(4096, 1024); // Set buffer sizes
#endif
Следующая строка инициализирует приложение Firebase с аутентификацией и устанавливает processData() в качестве функции обратного вызова для асинхронных результатов (это означает, что любые результаты функции initializeApp() будут обработаны в функции обратного вызова processData()).
initializeApp(aClient, app, getAuth(user_auth), processData, "authTask");
Затем укажите, что вы хотите установить объект Database, определённый ранее, как базу данных для нашего приложения Firebase.
app.getApp<RealtimeDatabase>(Database);
Наконец, установите URL базы данных.
Database.url(DATABASE_URL);
Потоковая передача базы данных — Прослушивание изменений
Теперь нам нужно установить прослушиватель базы данных, чтобы мы получали данные на ESP32 при изменении базы данных.
Следующая строка настраивает типы событий Server-Sent Events (SSE), которые streamClient будет прослушивать при подключении к Firebase Realtime Database. В данном случае мы включаем все типы событий.
streamClient.setSSEFilters("get,put,patch,keep-alive,cancel,auth_revoked");
Наконец, следующая строка инициирует потоковое подключение к Firebase Realtime Database по указанному listenerPath, используя streamClient для прослушивания обновлений в реальном времени. Когда происходят события, они обрабатываются функцией обратного вызова processData() (определённой далее в коде).
Database.get(streamClient, listenerPath, processData, true /* SSE mode (HTTP Streaming) */, "streamTask");
loop()
Функция loop() пуста и только выводит, как долго работает программа (это необязательно). Вам просто нужно поддерживать команду app.loop().
void loop(){
// Maintain authentication and async tasks
app.loop();
// Check if authentication is ready
if (app.ready()){
//Do nothing - everything works with callback functions
unsigned long currentTime = millis();
if (currentTime - lastSendTime >= sendInterval){
// Update the last send time
lastSendTime = currentTime;
Serial.printf("Program running for %lu\n", currentTime);
}
}
}
Функция processData — Обработка изменений базы данных
Функция processData() будет обрабатывать все события, связанные с операциями Firebase, включая изменения данных в базе данных.
Мы можем проверить, есть ли новые данные в базе данных, используя команду aResult.available().
if (aResult.available()){
Затем мы преобразуем результат в формат, к которому можно получить доступ в нашем коде — переменную типа RealtimeDatabaseResult.
RealtimeDatabaseResult &RTDB = aResult.to<RealtimeDatabaseResult>();
Мы проверяем, получены ли данные от потокового клиента.
if (RTDB.isStream()) {
Затем мы можем вывести доступные данные о событии.
Firebase.printf("task: %s\n", aResult.uid().c_str());
Firebase.printf("event: %s\n", RTDB.event().c_str());
Firebase.printf("path: %s\n", RTDB.dataPath().c_str());
Firebase.printf("etag: %s\n", RTDB.ETag().c_str());
Firebase.printf("data: %s\n", RTDB.to<const char *>());
Firebase.printf("type: %d\n", RTDB.type());
Команда RTDB.type() сообщает нам, какой тип данных мы получили из базы данных. Результаты могут быть:
realtime_database_data_type_undefined или -1
realtime_database_data_type_null или 0
realtime_database_data_type_integer или 1
realtime_database_data_type_float или 2
realtime_database_data_type_double или 3
realtime_database_data_type_boolean или 4
realtime_database_data_type_string или 5
realtime_database_data_type_json или 6
realtime_database_data_type_array или 7
Когда ESP впервые подключается к базе данных, он срабатывает по корневому (/) пути и возвращает JSON-объект со всеми дочерними узлами (RTDB.type() = 6). Таким образом, мы можем получить все значения из базы данных и обновить GPIO ESP32 при первом запуске. Это также полезно, потому что если ESP32 перезагрузится, он всегда сначала получит этот JSON-объект и сможет обновить все GPIO.
Как видно из предыдущего скриншота, JSON-объект, который он получает, выглядит следующим образом (он может отличаться в зависимости от состояний GPIO):
{
"12": 0,
"13": 0,
"14": 0
}
Когда это происходит, полученные данные имеют тип JSON. Мы можем получить их и преобразовать в JSON-переменную doc следующим образом:
if (RTDB.type() == 6) {
Serial.println(RTDB.to<String>());
// Parse JSON
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc, RTDB.to<String>());
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
Затем мы можем перебрать JSON-объект и получить ключи (GPIO) и соответствующие значения (состояния GPIO). В каждой итерации мы сохраняем GPIO в переменную gpioPin и его соответствующее состояние в переменную state. Затем мы вызываем функцию digitalWrite() для обновления его состояния.
// Iterate through JSON object
for (JsonPair kv : doc.as<JsonObject>()) {
int gpioPin = atoi(kv.key().c_str()); // Convert key (e.g., "12") to int
bool state = kv.value().as<bool>();
digitalWrite(gpioPin, state ? HIGH : LOW);
}
Это проходит через все ключи и значения, позволяя нам обновить все GPIO.
Если RTDB.type() равен 4 или 1, это означает, что мы вставили в базу данных логическое или целочисленное значение. В этом случае мы получаем путь базы данных, который соответствует номеру GPIO, и вставленные данные, которые соответствуют состоянию GPIO.
if (RTDB.type() == 4 || RTDB.type() == 1){
// get the GPIO number
int GPIO_number = RTDB.dataPath().substring(1).toInt();
bool state = RTDB.to<bool>();
После получения этих данных мы можем обновить состояние GPIO в соответствии с изменениями в базе данных.
digitalWrite(GPIO_number, state);
Демонстрация
После вставки всех необходимых учётных данных загрузите код на вашу плату.
После загрузки откройте Serial Monitor на скорости 115200 бод и перезагрузите плату. Вы должны увидеть что-то вроде показанного ниже.
Как видите, при первом запуске ESP получает JSON-объект со всеми состояниями GPIO.
{
"12": 0,
"13": 0,
"14": 0
}
Затем перейдите в Firebase Realtime Database в консоли Firebase. Вручную измените состояния GPIO (0 или 1). После ввода нового значения нажмите Enter.
Сразу после этого вы увидите в Serial Monitor, что ESP32 обнаружил изменения.
И он обновит состояния GPIO и зажжёт светодиоды практически мгновенно.
Затем, если вы перезагрузите плату (нажмите кнопку RST или отключите и подключите питание снова), при перезапуске она получит последние состояния GPIO из базы данных и сразу обновит их.
Развитие проекта — Добавление дополнительных плат
Вы можете развить этот проект далее и добавить больше плат. Для этого создайте новые узлы базы данных для второй платы. Вы можете добавить платы ESP32 или ESP8266.
Вы можете скачать следующий JSON-файл и импортировать его в вашу базу данных, и он создаст узлы для двух плат:
После загрузки JSON-файла база данных будет выглядеть следующим образом:
Теперь вы можете загрузить тот же код на новую плату (он совместим с ESP32 и ESP8266). Но не забудьте изменить путь прослушивания. Он должен быть:
String listenerPath = "board2/outputs/digital/";
Теперь вы можете управлять обеими платами, изменяя состояния GPIO в базе данных.
В Части 2 мы создадим веб-приложение Firebase, чтобы у вас был удобный интерфейс для управления вашими GPIO из любой точки мира без необходимости использовать консоль Firebase и вручную изменять базу данных:
Заключение
В этом руководстве вы узнали, как использовать Firebase Realtime Database для сохранения состояний GPIO ESP. Вы также научились программировать ESP32 для прослушивания изменений базы данных. Всякий раз, когда обнаруживается изменение, мы обновляем соответствующие состояния GPIO. Вы можете изменить код так, чтобы ESP прослушивал любые другие данные, сохранённые в базе данных, а не только состояния GPIO. Поскольку к Firebase Realtime Database можно получить доступ из любой точки мира, вы можете управлять своими платами из любой точки мира. Это отлично подходит для IoT-проектов.
В Части 2 мы создадим веб-приложение для управления вашими GPIO из любой точки мира, без необходимости входить вручную в консоль Firebase:
Узнайте больше об ESP32 с нашими ресурсами:
Примечание
Данная статья является переводом материала с сайта Random Nerd Tutorials.