ESP32: Логирование данных в Firebase Realtime Database

В этом руководстве вы узнаете, как логировать данные с ESP32 в Firebase Realtime Database с метками времени (логирование данных), чтобы у вас была история ваших данных. В качестве примера мы будем логировать температуру, влажность и давление с датчика BME280, а метки времени будем получать с NTP-сервера. Затем вы сможете получить доступ к данным через консоль Firebase или создать веб-приложение для отображения результатов (смотрите этот урок).

ESP32 логирование данных в Firebase Realtime Database

Обновлено 12 мая 2025 года

Часть 2: ESP32/ESP8266: Веб-приложение Firebase для логирования данных (индикаторы, графики и таблица)

Другие руководства по Firebase с ESP32/ESP8266, которые могут вас заинтересовать:

Что такое Firebase?

Логотип Firebase

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

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

Следующая диаграмма показывает общий обзор проекта, который мы создадим.

ESP32 с BME280 логирование данных Firebase
  1. ESP32 аутентифицируется как пользователь с email и паролем (этот пользователь должен быть настроен в методах аутентификации Firebase);

  2. После аутентификации ESP получает UID пользователя;

  3. База данных защищена правилами безопасности. Пользователь может получить доступ только к узлам базы данных под узлом со своим UID. После получения UID пользователя ESP может публиковать данные в базу данных;

  4. ESP32 получает температуру, влажность и давление с датчика BME280.

  5. Он получает epoch time сразу после получения показаний (метка времени).

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

  7. Новые показания добавляются в базу данных периодически. У вас будет запись всех показаний в Firebase Realtime Database.

Вот основные шаги для выполнения этого проекта:

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

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

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

  4. Настройка Realtime Database

  5. Настройка правил безопасности базы данных

  6. Логирование данных ESP32 (Firebase Realtime Database)

Вы можете продолжить с проектом Firebase из этого предыдущего руководства или создать новый проект. Если вы используете проект Firebase из предыдущего руководства, вы можете перейти к разделу 4) Настройка Realtime Database, так как методы аутентификации уже настроены.

Подготовка Arduino IDE

Для этого руководства мы будем программировать плату ESP32 с использованием ядра Arduino. Поэтому убедитесь, что у вас установлен аддон ESP32 в Arduino IDE:

Если вы хотите программировать платы ESP32/ESP8266 с помощью VS Code с расширениями pioarduino или PlatformIO, следуйте этим руководствам:

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

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

  1. Перейдите в Firebase и войдите с помощью аккаунта Google.

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

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

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

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

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

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

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

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

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

«Большинству приложений необходимо знать личность пользователя. Другими словами, это отвечает за вход в систему и идентификацию пользователей (в данном случае 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.

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

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

Firebase создаёт уникальный UID для каждого зарегистрированного пользователя. UID пользователя позволяет нам идентифицировать пользователя и отслеживать его для предоставления или отказа в доступе к проекту или базе данных. Также есть столбец, который регистрирует дату последнего входа. На данный момент он пуст, так как мы ещё не входили с этим пользователем.

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

Для взаимодействия с вашим проектом Firebase через платы ESP32 или ESP8266 вам необходимо получить API-ключ проекта. Следуйте инструкциям ниже, чтобы получить API-ключ вашего проекта.

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

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

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

4) Настройка Realtime Database

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

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

Создание базы данных проекта Firebase

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

Настройка расположения Firebase Realtime Database

3) Настройте правила безопасности для вашей базы данных. Вы можете выбрать Start in test mode. Мы изменим правила базы данных через мгновение.

Firebase Realtime Database запуск в тестовом режиме

4) Ваша база данных теперь создана. Вам нужно скопировать и сохранить URL базы данных – он выделен на следующем изображении – так как он понадобится вам позже в коде ESP32/ESP8266.

URL Firebase Realtime Database

5) Настройка правил безопасности базы данных

Теперь давайте настроим правила базы данных. На вкладке Realtime Database выберите вкладку Rules вверху. Затем нажмите Edit rules, скопируйте следующие правила и нажмите Publish.

// These rules grant access to a node matching the authenticated
// user's ID from the Firebase auth token
{
  "rules": {
    "UsersData": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}
Настройка правил Firebase Realtime Database

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

Например, представьте, что UID нашего пользователя – RjO3taAzMMXBB2Xmir2LQ. С нашими правилами безопасности он может читать и записывать данные в базу данных по узлу UsersData/RjO3taAzMMXBB2Xmir2LQ.

6) Логирование данных ESP32 (Firebase Realtime Database)

В этом разделе мы запрограммируем плату ESP32 для выполнения следующих задач:

  1. Аутентификация как пользователь с email и паролем (пользователь, которого вы настроили в этом разделе);

  2. Получение показаний BME280: температура, влажность и давление;

  3. Получение epoch time (метки времени) с NTP-сервера;

  4. Отправка показаний датчика и метки времени в базу данных реального времени как авторизованный пользователь.

Необходимые компоненты

Для этого проекта вам понадобятся следующие компоненты*:

* вы также можете протестировать проект со случайными значениями вместо показаний датчика, или использовать любой другой датчик, с которым вы знакомы.

Схема подключения

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

Мы будем использовать I2C-связь с модулем датчика BME280. Для этого подключите датчик к стандартным пинам ESP32: SCL (GPIO 22) и SDA (GPIO 21), как показано на следующей схеме.

Узнайте больше об I2C с ESP32: ESP32 I2C Communication: Set Pins, Multiple Bus Interfaces and Peripherals (Arduino IDE).

Схема подключения ESP32 BME280 температура влажность давление

Не знакомы с BME280 для ESP32? Прочитайте этот урок: ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity).

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

Для этого проекта вам необходимо установить следующие библиотеки:

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

Следуйте инструкциям ниже, если вы используете VS Code с расширением PlatformIO или pioarduino.

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

Нажмите на иконку PIO Home и выберите вкладку Libraries. Найдите «FirebaseClient». Выберите Firebase Client Library от Mobitz.

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

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

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

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

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

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

На вкладке Libraries найдите BME280. Выберите библиотеку Adafruit BME280.

Поиск библиотеки BME280 в PlatformIO VS Code

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

PlatformIO VS Code добавление библиотеки в проект

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

monitor_speed = 115200

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

Следуйте этому разделу, если вы используете Arduino IDE.

Вам необходимо установить следующие библиотеки:

Перейдите в Sketch > Include Library > Manage Libraries, найдите названия библиотек и установите их.

Установка Firebase Client Library в Arduino IDE

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

Код логирования данных – Firebase Realtime Database

Скопируйте следующий код в Arduino IDE или в файл main.cpp, если вы используете VS Code.

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

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at our blog: https://RandomNerdTutorials.com/esp32-data-logging-firebase-realtime-database/
  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.
*/
#define ENABLE_USER_AUTH
#define ENABLE_DATABASE

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "time.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);

// 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

// Variable to save USER UID
String uid;

// Database main path (to be updated in setup with the user UID)
String databasePath;
// Database child nodes
String tempPath = "/temperature";
String humPath = "/humidity";
String presPath = "/pressure";
String timePath = "/timestamp";

// Parent Node (to be updated in every loop)
String parentPath;

int timestamp;

const char* ntpServer = "pool.ntp.org";

// BME280 sensor
Adafruit_BME280 bme; // I2C
float temperature;
float humidity;
float pressure;

// Create JSON objects for storing data
object_t jsonData, obj1, obj2, obj3, obj4;
JsonWriter writer;

// Initialize BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

// Initialize WiFi
void initWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

// Function that gets current epoch time
unsigned long getTime() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    //Serial.println("Failed to obtain time");
    return(0);
  }
  time(&now);
  return now;
}

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

  initBME();
  initWiFi();
  configTime(0, 0, ntpServer);

  // 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;

      uid = app.getUid().c_str();

      // Update database path
      databasePath = "/UsersData/" + uid + "/readings";

      //Get current timestamp
      timestamp = getTime();
      Serial.print ("time: ");
      Serial.println (timestamp);

      parentPath= databasePath + "/" + String(timestamp);

      // Get sensor readings
      temperature = bme.readTemperature();
      humidity = bme.readHumidity();
      pressure = bme.readPressure()/100.0;

      // Create a JSON object with the data
      writer.create(obj1, tempPath, temperature);
      writer.create(obj2, humPath, humidity);
      writer.create(obj3, presPath, pressure);
      writer.create(obj4, timePath, timestamp);
      writer.join(jsonData, 4, obj1, obj2, obj3, obj4);

      Database.set<object_t>(aClient, parentPath, jsonData, processData, "RTDB_Send_Data");
    }
  }
}

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

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

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

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

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

Сначала подключите необходимые библиотеки.

#include <Arduino.h>
#if defined(ESP32)
    #include <WiFi.h>
#elif defined(ESP8266)
    #include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <FirebaseClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "time.h"

Сетевые учётные данные

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

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

API-ключ проекта Firebase, пользователь Firebase и URL базы данных

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

#define Web_API_KEY "REPLACE_WITH_YOUR_PROJECT_API_KEY"

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

// Insert Authorized Email and Corresponding Password
#define USER_EMAIL "REPLACE_WITH_THE_USER_EMAIL"
#define USER_PASSWORD "REPLACE_WITH_THE_USER_PASSWORD"

Вставьте URL вашей базы данных в следующую строку:

// Insert RTDB URLefine the RTDB URL
#define DATABASE_URL "REPLACE_WITH_YOUR_DATABASE_URL"

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

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

UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS);

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

FirebaseApp app;

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

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

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

RealtimeDatabase Database;

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

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

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

Создайте переменную для сохранения UID пользователя. Переменная uid будет использоваться для сохранения UID пользователя. Мы можем получить UID пользователя после аутентификации.

// Variable to save USER UID
String uid;

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

// Database main path (to be updated in setup with the user UID)
String databasePath;
// Database child nodes
String tempPath = "/temperature";
String humPath = "/humidity";
String presPath = "/pressure";
String timePath = "/timestamp";

// Parent Node (to be updated in every loop)
String parentPath;

Мы создаём переменную для сохранения метки времени и ещё одну для сохранения NTP-сервера.

int timestamp;

const char* ntpServer = "pool.ntp.org";

Переменные BME280

Затем создайте объект Adafruit_BME280 с именем bme. Это автоматически создаёт объект датчика на стандартных пинах I2C ESP32 или ESP8266.

Adafruit_BME280 bme; // I2C

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

float temperature;
float humidity;
float pressure;

Переменные JSON

Мы отправим все данные в базу данных в виде JSON-объекта. Библиотека FirebaseClient имеет собственные методы для работы с JSON. Вы должны использовать их вместо других JSON-библиотек. Для этого нам нужно создать четыре объекта jsonData: obj1, obj2, obj3 и obj4.

object_t jsonData, obj1, obj2, obj3, obj4;

Затем нам нужно создать экземпляр класса JsonWriter, в данном случае с именем writer, который предоставляет методы для создания и объединения JSON-объектов для Firebase.

JsonWriter writer;

Чтобы узнать больше, мы рекомендуем прочитать этот раздел документации об объекте JsonWriter.

initBME()

Функция initBME() инициализирует датчик BME280. Мы вызовем её позже в setup().

// Initialize BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  Serial.print("BME280 Initialized with success");
}

initWiFi()

Функция initWiFi() подключит ESP32 к вашей локальной сети, используя SSID и пароль, определённые ранее.

// Initialize WiFi
void initWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

getTime()

Функция getTime() возвращает текущее epoch time.

// Function that gets current epoch time
unsigned long getTime() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    //Serial.println("Failed to obtain time");
    return(0);
  }
  time(&now);
  return now;
}

Чтобы узнать больше о получении epoch time с платой ESP32, вы можете ознакомиться со следующим руководством:

setup()

В setup() инициализируйте Serial Monitor, датчик BME280, WiFi и настройте NTP-сервер.

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

    initBME();
    initWiFi();
    configTime(0, 0, ntpServer);

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

ssl_client.setInsecure();
#if defined(ESP32)
  ssl_client.setConnectionTimeout(1000);
  ssl_client.setHandshakeTimeout(5);
#elif defined(ESP8266)
  ssl_client.setTimeout(1000); // Set connection timeout
  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);

loop()

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

void loop(){
  app.loop();

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

if (app.ready()){

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

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

После успешной аутентификации мы получим UID пользователя и сохраним его в переменной uid. Затем мы обновим путь базы данных на UsersData/<USER_UID>.

uid = app.getUid().c_str();

Переменная databasePath сохраняет основной путь базы данных, который теперь можно обновить с помощью UID пользователя.

// Update database path
databasePath = "/UsersData/" + uid;

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

//Get current timestamp
timestamp = getTime();
Serial.print ("time: ");
Serial.println (timestamp);

parentPath= databasePath + "/" + String(timestamp);

Чтобы лучше понять, как мы организуем наши данные, вот диаграмма.

Firebase BME280 база данных логирования

Может показаться избыточным сохранять метку времени дважды (в родительском узле и дочернем узле), однако наличие всех данных на одном уровне иерархии упростит задачу в будущем, если мы захотим создать веб-приложение для отображения данных.

После получения метки времени и обновления всех узлов базы данных с UID пользователя и соответствующей меткой времени мы можем получить показания с датчика BME280.

// Get sensor readings
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure()/100.0;

Создание JSON-объектов

Мы отправим все показания и соответствующие метки времени в базу данных реального времени одновременно, создав JSON-объект, содержащий значения этих переменных. Библиотека FirebaseClient имеет собственные методы для работы с JSON. Мы будем использовать их для отправки данных в формате JSON в базу данных.

Мы используем метод create() объекта writer для создания JSON-объекта с ключом (узлом) и соответствующим значением (показаниями датчика).

Например, следующая строка создаёт JSON-объект с tempPath в качестве ключа и temperature в качестве значения. Результат сохраняется в obj1.

writer.create(obj1, tempPath, temperature);

Пример вывода в данном случае будет:

obj1 = {"UserData/<user_udi>/timestamp/temperature": 23.5}

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

writer.create(obj2, humPath, humidity);
writer.create(obj3, presPath, pressure);
writer.create(obj4, timePath, timestamp);

Затем мы используем метод join() объекта writer для объединения четырёх JSON-объектов (obj1, obj2, obj3, obj4) в единую JSON-структуру, сохранённую в jsonData. Число 4 указывает количество объединяемых объектов.

writer.join(jsonData, 4, obj1, obj2, obj3, obj4);

Отправка JSON-объекта

Наконец, мы можем отправить JSON-объект в базу данных с помощью метода set() объекта базы данных. Мы уже объяснили, как это работает, в предыдущем руководстве.

Database.set<object_t>(aClient, parentPath, jsonData, processData, "RTDB_Send_Data");

Здесь используется SSL-клиент aClient и отправляется переменная jsonData по пути parentPath в базу данных. Результаты этой операции будут обработаны в функции processData. Последний параметр RTDB_Send_Data идентифицирует эту задачу.

Наконец, функция 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. Не забудьте вставить ваши сетевые учётные данные, API-ключ проекта, URL базы данных, email пользователя и соответствующий пароль.

После загрузки кода нажмите кнопку RST на плате, чтобы начать выполнение кода. Он должен аутентифицироваться в Firebase, получить UID пользователя и сразу начать отправку новых показаний в базу данных.

Откройте Serial Monitor со скоростью 115200 бод и проверьте, что всё работает как ожидалось.

ESP32 отправка JSON Firebase Serial Monitor

Дополнительно перейдите в Realtime Database в интерфейсе вашего проекта Firebase и проверьте, что новые показания сохраняются. Обратите внимание, что данные сохраняются под узлом с собственным UID пользователя – это способ ограничить доступ к базе данных.

Логирование данных Firebase Realtime Database

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

Заключение

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

Вы можете использовать другие методы, предоставляемые библиотекой FirebaseClient, для логирования ваших данных, и вы можете организовать вашу базу данных по-разному. Мы организовали базу данных таким образом, который удобен для другого проекта, который мы скоро опубликуем.

В ЧАСТИ 2 мы создадим веб-приложение Firebase для отображения всех сохранённых данных в таблице и последних показаний на графиках.

Надеемся, что это руководство было для вас полезным.

Если вам нравятся проекты с Firebase, ознакомьтесь с нашей новой электронной книгой. Мы уверены, что она вам понравится:

Узнайте больше об ESP32 с нашими ресурсами:

Спасибо за чтение.


Источник: ESP32 Data Logging to Firebase Realtime Database