ESP32/ESP8266: Веб-приложение Firebase для отображения показаний датчиков (с аутентификацией)
В этом руководстве вы создадите веб-приложение Firebase для отображения показаний датчиков, сохранённых в Firebase Realtime Database. Веб-страница с показаниями датчиков защищена аутентификацией с использованием email и пароля. Вы узнаете, как отображать данные из базы данных и как добавить аутентификацию в ваше веб-приложение.
Обновлено 30 апреля 2025 года
Эта статья является Частью 2 предыдущего руководства: ESP32/ESP8266 Firebase: отправка показаний датчика BME280 в Realtime Database. Сначала выполните это руководство, прежде чем продолжить.
Обзор проекта
В этом руководстве (Часть 2) вы создадите веб-приложение для отображения показаний датчиков, сохранённых в Firebase Realtime Database (прочитайте предыдущее руководство).
Следующая диаграмма показывает общий обзор проекта, который мы будем создавать — программирование ESP32/ESP8266 и настройка проекта Firebase были выполнены в Части 1.
Firebase размещает ваше веб-приложение на глобальном CDN с помощью Firebase Hosting и предоставляет SSL-сертификат. Вы можете получить доступ к вашему веб-приложению из любой точки мира, используя доменное имя, сгенерированное Firebase.
При первом доступе к веб-приложению вам необходимо пройти аутентификацию с авторизованным адресом электронной почты и паролем. Вы уже настроили этого пользователя и метод аутентификации в Части 1.
После аутентификации вы можете получить доступ к веб-странице, которая показывает показания датчиков, сохранённые в базе данных реального времени. База данных реального времени была настроена в Части 1.
После входа в систему вы можете выйти в любое время. При следующем доступе к приложению вам нужно будет снова войти в систему.
Предварительные требования
Перед тем как начать создание веб-приложения Firebase, необходимо проверить следующие предварительные требования.
Создание проекта Firebase
Вы должны были выполнить следующее руководство:
ESP32/ESP8266 должен выполнять код, предоставленный в этом руководстве. База данных реального времени и аутентификация также должны быть настроены, как показано в руководстве.
Установка необходимого программного обеспечения
Перед началом работы необходимо установить необходимое программное обеспечение для создания веб-приложения Firebase. Вот список программного обеспечения, которое необходимо установить (нажмите на ссылки для получения инструкций):
1) Добавление приложения в ваш проект Firebase
1) Перейдите в консоль вашего проекта Firebase и добавьте приложение в проект, нажав кнопку +Add app.
2) Выберите значок веб-приложения.
3) Дайте вашему приложению имя. Затем установите флажок рядом с Also set up Firebase Hosting for this App. Нажмите Register app.
4) Затем скопируйте объект firebaseConfig и сохраните его, потому что он понадобится вам позже.
После этого вы также можете получить доступ к объекту firebaseConfig, если перейдёте в настройки проекта в консоли Firebase.
5) Нажмите Next на последующих шагах и, наконец, Continue to console.
2) Настройка проекта веб-приложения Firebase (VS Code)
Следуйте следующим шагам для создания проекта веб-приложения Firebase с использованием VS Code.
1) Создание папки проекта
1) Создайте папку на вашем компьютере, где вы хотите сохранить проект Firebase — например, Firebase-Project на рабочем столе.
2) Откройте VS Code. Перейдите в File > Open Folder… и выберите папку, которую вы только что создали.
3) Перейдите в Terminal > New Terminal. Должно открыться новое окно терминала с путём к вашему проекту.
2) Вход в Firebase
4) В предыдущем окне терминала введите следующее:
firebase login
5) Вас спросят, хотите ли вы собирать информацию об использовании CLI и отчёты об ошибках. Введите «n» и нажмите Enter, чтобы отказать.
Примечание: Если вы уже вошли в систему, будет показано сообщение: «Already logged in as user@gmail.com».
6) После этого откроется новое окно в вашем браузере для входа в вашу учётную запись Firebase.
7) Разрешите Firebase CLI доступ к вашей учётной записи Google.
8) После этого вход через Firebase CLI должен быть успешным. Вы можете закрыть окно браузера.
3) Инициализация проекта Firebase для веб-приложения
9) После успешного входа выполните следующую команду для запуска каталога проекта Firebase в текущей папке.
firebase init
10) Вас спросят, хотите ли вы инициализировать проект Firebase в текущем каталоге. Введите Y и нажмите Enter.
11) Затем используйте стрелки вверх и вниз и клавишу пробела для выбора опций. Выберите следующие опции:
Realtime Database: Configure security rules file for Realtime Database and (optionally) provision default instance.
Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
Выбранные опции будут отмечены зелёной звёздочкой. Затем нажмите Enter.
12) Выберите опцию «Use an existing project» — она должна быть выделена синим цветом — затем нажмите Enter.
13) После этого выберите проект Firebase для этого каталога — это должен быть проект, созданный в предыдущем руководстве. В моём случае он называется esp-project. Затем нажмите Enter.
14) Затем выберите опции хостинга, как показано ниже:
What do you want to use as your public directory? Нажмите Enter, чтобы выбрать public.
Configure as a single-page app (rewrite urls to /index.html)? No
Set up automatic builds and deploys with GitHub? No
15) Нажмите Enter на следующем вопросе, чтобы выбрать файл правил безопасности базы данных по умолчанию: «What file should be used for Realtime Database Security Rules?»
16) Проект Firebase теперь должен быть успешно инициализирован. Обратите внимание, что VS Code создал несколько важных файлов в папке вашего проекта.
Файл index.html содержит некоторый HTML-текст для создания веб-страницы. Пока оставьте HTML-текст по умолчанию. Идея состоит в том, чтобы заменить его своим собственным HTML-текстом для создания пользовательской веб-страницы для ваших нужд. Мы сделаем это позже в этом руководстве.
17) Чтобы проверить, всё ли прошло как ожидалось, выполните следующую команду в окне терминала VS Code.
firebase deploy
Вы должны получить сообщение Deploy complete! и URL-адрес консоли проекта и URL-адрес хостинга.
18) Скопируйте URL-адрес хостинга и вставьте его в окно веб-браузера. Вы должны увидеть следующую веб-страницу. Вы можете получить доступ к этой веб-странице из любой точки мира.
Веб-страница, которую вы видели ранее, создана с помощью HTML-файла, размещённого в папке public вашего проекта Firebase. Изменяя содержимое этого файла, вы можете создать своё собственное веб-приложение. Это то, что мы собираемся сделать в следующем разделе.
3) Создание веб-приложения Firebase
Теперь, когда вы создали проект приложения Firebase в VS Code, следуйте следующим шагам для настройки приложения для отображения показаний датчиков на защищённой входом веб-странице.
index.html
Скопируйте следующее в ваш файл index.html. Этот HTML-файл создаёт простую веб-страницу, которая отображает показания, сохранённые в Realtime Database, созданной в предыдущем проекте.
Если вы не аутентифицированы, отображается форма входа. Когда вы аутентифицируетесь с авторизованным email пользователя и соответствующим паролем, отображается пользовательский интерфейс с показаниями датчиков.
<!-- Complete Project Details at: https://RandomNerdTutorials.com/esp32-esp8266-firebase-web-app-sensor/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ESP IoT Firebase App</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<!--TOP BAR-->
<div class="topnav">
<h1>Sensor Readings App <i class="fas fa-clipboard-list"></i></h1>
</div>
<!--AUTHENTICATION BAR (USER DETAILS/LOGOUT BUTTON)-->
<div id="authentication-bar" style="display: none;">
<p><span id="authentication-status">User logged in</span>
<span id="user-details">USEREMAIL</span>
<a href="#" id="logout-link">(logout)</a>
</p>
</div>
<!--LOGIN FORM-->
<form id="login-form" style="display: none;">
<div class="form-elements-container">
<label for="input-email"><b>Email</b></label>
<input type="text" placeholder="Enter Username" id="input-email" required>
<label for="input-password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" id="input-password" required>
<button type="submit" id="login-button">Login</button>
<p id="error-message" style="color:red;"></p>
</div>
</form>
<!--CONTENT (SENSOR READINGS)-->
<div class="content-sign-in" id="content-sign-in" style="display: none;">
<div class="cards">
<!--TEMPERATURE-->
<div class="card">
<p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p>
<p><span class="reading"><span id="temp"></span> °C</span></p>
</div>
<!--HUMIDITY-->
<div class="card">
<p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p>
<p><span class="reading"><span id="hum"></span> %</span></p>
</div>
<!--PRESSURE-->
<div class="card">
<p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE</p>
<p><span class="reading"><span id="pres"></span> hPa</span></p>
</div>
</div>
</div>
<script type="module" src="scripts/auth.js"></script>
<script type="module" src="scripts/index.js"></script>
</body>
</html>
Как это работает
Давайте кратко рассмотрим HTML-файл, или перейдите к следующему разделу.
В <head> HTML-файла мы должны добавить все необходимые метаданные.
Заголовок веб-страницы — ESP Firebase App, но вы можете изменить его в следующей строке.
<title>ESP Firebase App</title>
Следующая строка позволяет нам использовать иконки fontawesome:
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
Следующая строка включает favicon на нашу веб-страницу.
<link rel="icon" type="image/png" href="favicon.png">
Наконец, ссылка на внешний файл style.css для форматирования HTML-страницы.
<link rel="stylesheet" type="text/css" href="style.css">
Мы закончили с метаданными. Теперь давайте перейдём к частям HTML, которые видны пользователю — перейдите между тегами <body> и </body>.
Мы создаём верхнюю панель «навигации» с названием нашего приложения и маленькой иконкой из fontawesome.
<div class="topnav">
<h1>Sensor Readings App <i class="fas fa-clipboard-list"></i></h1>
</div>
Следующие строки создают панель с данными аутентифицированного пользователя (email). Также отображается ссылка для выхода из системы.
<div id="authentication-bar" style="display: none;">
<p><span id="authentication-status">User logged in</span>
<span id="user-details">USEREMAIL</span>
<a href="/" id="logout-link">(logout)</a>
</p>
</div>
Сначала мы устанавливаем стиль отображения всех элементов в none. Мы будем скрывать и показывать контент в зависимости от того, аутентифицирован пользователь или нет — мы будем обрабатывать это с помощью JavaScript.
Далее, следующие строки создают форму входа с полем ввода для email и полем ввода для пароля:
<form id="login-form" style="display: none;">
<div class="form-elements-container">
<label for="input-email"><b>Email</b></label>
<input type="text" placeholder="Enter Username" id="input-email" required>
<label for="input-password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" id="input-password" required>
<button type="submit" id="login-button">Login</button>
<p id="error-message" style="color:red;"></p>
</div>
</form>
Внутри формы также есть параграф для отображения сообщения об ошибке, если вход не удастся.
<p id="error-message" style="color:red;"></p>
Наконец, мы создаём сетку для отображения показаний датчиков.
<!--CONTENT (SENSOR READINGS)-->
<div class="content-sign-in" id="content-sign-in" style="display: none;">
<div class="cards">
<!--TEMPERATURE-->
<div class="card">
<p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE</p>
<p><span class="reading"><span id="temp"></span> °C</span></p>
</div>
<!--HUMIDITY-->
<div class="card">
<p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY</p>
<p><span class="reading"><span id="hum"></span> %</span></p>
</div>
<!--PRESSURE-->
<div class="card">
<p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE</p>
<p><span class="reading"><span id="pres"></span> hPa</span></p>
</div>
</div>
</div>
Места, где мы будем вставлять показания датчиков, имеют теги <span> с определёнными идентификаторами, чтобы мы могли обращаться к этим HTML-элементам с помощью JavaScript и вставлять показания датчиков, сохранённые в базе данных.
температура: id = «temp»
влажность: id = «hum»
давление: id = «pres»
Наконец, нам нужно добавить ссылки на внешние файлы JavaScript. Для нашего приложения мы создадим два файла JavaScript: auth.js (который обрабатывает всё, связанное с аутентификацией) и index.js, который обрабатывает всё, связанное с пользовательским интерфейсом. Мы создадим эти файлы внутри папки scripts внутри папки public нашего приложения.
<script src="scripts/auth.js"></script>
<script src="scripts/index.js"></script>
Сохраните HTML-файл.
style.css
Внутри папки public создайте файл с именем style.css. Чтобы создать файл, выберите папку public, а затем нажмите на значок +file в верхней части проводника файлов. Назовите его style.css.
Затем скопируйте следующее в файл style.css.
html {
font-family: Verdana, Geneva, Tahoma, sans-serif;
display: inline-block;
text-align: center;
}
p {
font-size: 1.2rem;
}
body {
margin: 0;
}
.topnav {
overflow: hidden;
background-color: #049faa;
color: white;
font-size: 1rem;
padding: 10px;
}
#authentication-bar{
background-color:mintcream;
padding-top: 10px;
padding-bottom: 10px;
}
#user-details{
color: cadetblue;
}
.content {
padding: 20px;
}
.card {
background-color: white;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
padding: 5%;
}
.cards {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.reading {
font-size: 1.4rem;
}
button {
background-color: #049faa;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
border-radius: 4px;
}
button:hover {
opacity: 0.8;
}
.form-elements-container{
padding: 16px;
width: 250px;
margin: 0 auto;
}
input[type=text], input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
CSS-файл включает несколько простых стилей, чтобы наша веб-страница выглядела лучше. Мы не будем обсуждать, как работает CSS, в этом руководстве.
Файлы JavaScript
Мы создадим два файла JavaScript (auth.js и index.js) внутри папки scripts внутри папки public.
Выберите папку public, затем нажмите на значок +folder, чтобы создать новую папку. Назовите новую папку scripts.
Затем выберите папку scripts и нажмите на значок +file. Создайте файл с именем auth.js. Затем повторите предыдущие шаги, чтобы создать index.js.
Следующее изображение показывает, как должна выглядеть структура папок вашего проекта веб-приложения.
auth.js
Теперь давайте реализуем вход пользователя с использованием аутентификации Firebase. Мы реализуем вход с помощью email и пароля.
Скопируйте следующее в файл auth.js, который вы создали ранее.
import { auth } from "./index.js";
import { signInWithEmailAndPassword, signOut, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-auth.js";
document.addEventListener("DOMContentLoaded", () => {
// Listen for auth status changes
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("User logged in:", user.email);
setupUI(user);
} else {
console.log("User logged out");
setupUI(null);
}
});
// Login
const loginForm = document.querySelector('#login-form');
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const email = loginForm['input-email'].value;
const password = loginForm['input-password'].value;
try {
await signInWithEmailAndPassword(auth, email, password);
loginForm.reset();
console.log("Logged in:", email);
} catch (error) {
document.getElementById("error-message").innerHTML = error.message;
console.error("Login error:", error.message);
}
});
// Logout
const logoutLink = document.querySelector('#logout-link');
logoutLink.addEventListener('click', async (e) => {
e.preventDefault();
try {
await signOut(auth);
console.log("User signed out");
} catch (error) {
console.error("Logout error:", error.message);
}
});
});
Затем сохраните файл. Этот файл заботится обо всём, что связано с входом и выходом пользователя. Продолжайте чтение, чтобы узнать, как работает код, или перейдите к следующему разделу.
Импорт модулей
Мы начинаем с импорта необходимых модулей. Мы импортируем переменную аутентификации auth из файла index.js (мы рассмотрим его далее), которая необходима для проверки, вошёл ли пользователь в систему или нет.
import { auth } from "./index.js";
Мы также импортируем все необходимые модули Firebase.
import { signInWithEmailAndPassword, signOut, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-auth.js";
Вход (Login)
Следующие строки отвечают за вход пользователя в систему.
// Login
const loginForm = document.querySelector('#login-form');
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const email = loginForm['input-email'].value;
const password = loginForm['input-password'].value;
try {
await signInWithEmailAndPassword(auth, email, password);
loginForm.reset();
console.log("Logged in:", email);
} catch (error) {
document.getElementById("error-message").innerHTML = error.message;
console.error("Login error:", error.message);
}
});
Мы создаём переменную, которая ссылается на HTML-элемент формы входа, называемую loginForm.
const loginForm = document.querySelector('#login-form');
Если вы вернётесь к файлу index.html, вы увидите, что форма имеет id login-form.
Мы добавляем обработчик событий типа submit к форме. Это означает, что последующие инструкции будут выполняться всякий раз, когда форма отправляется.
loginForm.addEventListener('submit', (e) => {
Вы можете получить отправленные данные следующим образом.
const email = loginForm['input-email'].value;
const password = loginForm['input-password'].value;
Если вы вернётесь к HTML-файлу, вы увидите, что поля ввода содержат следующие идентификаторы: input-email и input-password для email и пароля соответственно.
Теперь, когда у нас есть введённые email и пароль, мы можем попытаться войти в Firebase. Для этого передайте адрес электронной почты и пароль пользователя в следующий метод: signInWithEmailAndPassword:
try {
await signInWithEmailAndPassword(auth, email, password);
После входа мы сбрасываем форму и выводим email пользователя в консоль.
loginForm.reset();
console.log("Logged in:", email);
В случае ошибки при входе мы перехватываем сообщение об ошибке и отображаем его в HTML-элементе error-message (параграф под формой).
} catch (error) {
document.getElementById("error-message").innerHTML = error.message;
console.error("Login error:", error.message);
}
Выход (Logout)
Следующий фрагмент отвечает за выход пользователя из системы.
// Logout
const logoutLink = document.querySelector('#logout-link');
logoutLink.addEventListener('click', async (e) => {
e.preventDefault();
try {
await signOut(auth);
console.log("User signed out");
} catch (error) {
console.error("Logout error:", error.message);
}
});
Когда пользователь вошёл в систему, ссылка для выхода видна на панели аутентификации. Эта ссылка имеет id logout-link (см. HTML-файл). Итак, сначала мы создаём переменную с именем logout, которая ссылается на ссылку выхода.
const logout = document.querySelector('#logout-link');
Затем мы добавляем обработчик событий типа click. Это означает, что последующие инструкции будут выполняться всякий раз, когда вы нажимаете на ссылку выхода.
logout.addEventListener('click', (e) => {
Когда кнопка нажата, мы выводим пользователя из системы с помощью метода signOut.
try {
await signOut(auth);
console.log("User signed out");
} catch (error) {
console.error("Logout error:", error.message);
}
Изменения состояния аутентификации (Auth State Changes)
Для отслеживания состояния аутентификации пользователя — чтобы знать, вошёл ли пользователь в систему или вышел, существует метод onAuthStateChanged, который позволяет получать событие всякий раз, когда состояние аутентификации изменяется.
document.addEventListener("DOMContentLoaded", () => {
// Listen for auth status changes
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("User logged in:", user.email);
setupUI(user);
} else {
console.log("User logged out");
setupUI(null);
}
});
Если возвращённый пользователь равен null, пользователь в данный момент вышел из системы. В противном случае он в данный момент вошёл в систему.
В обоих сценариях мы выводим текущее состояние пользователя в консоль и вызываем функцию setupUI(). Мы ещё не создали эту функцию (мы создадим её в следующем разделе), но она будет отвечать за обработку пользовательского интерфейса в соответствии с состоянием аутентификации.
Когда пользователь вошёл в систему, мы передаём пользователя в качестве аргумента функции setupUI(). В этом случае мы отобразим полный пользовательский интерфейс для показа показаний датчиков, как вы увидите позже.
if (user) {
console.log("User logged in:", user.email);
setupUI(user);
Если пользователь вышел из системы, мы вызываем функцию setupUI() с аргументом null. В этом сценарии мы просто отобразим сообщение о том, что пользователь вышел из системы и не имеет доступа к интерфейсу (как мы увидим позже).
} else {
console.log("User logged out");
setupUI(null);
}
index.js
Файл index.js обрабатывает пользовательский интерфейс — он показывает правильный контент в зависимости от статуса аутентификации пользователя. Когда пользователь вошёл в систему, этот файл получает новые показания из базы данных всякий раз, когда происходит изменение.
Скопируйте следующее в файл index.js.
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-app.js";
import { getAuth } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-auth.js";
import { getDatabase, ref, onValue } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-database.js";
// Firebase configuration
const firebaseConfig = {
apiKey: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
authDomain: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
databaseURL: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
projectId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
storageBucket: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
messagingSenderId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
appId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const database = getDatabase(app);
// Export auth for use in auth.js
export { auth };
// UI Elements
const loginElement = document.querySelector('#login-form');
const contentElement = document.querySelector("#content-sign-in");
const userDetailsElement = document.querySelector('#user-details');
const authBarElement = document.querySelector("#authentication-bar");
const tempElement = document.getElementById("temp");
const humElement = document.getElementById("hum");
const presElement = document.getElementById("pres");
// Manage Login/Logout UI
const setupUI = (user) => {
if (user) {
// Toggle UI elements
loginElement.style.display = 'none';
contentElement.style.display = 'block';
authBarElement.style.display = 'block';
userDetailsElement.style.display = 'block';
userDetailsElement.innerHTML = user.email;
// Database paths
const uid = user.uid;
const dbPathTemp = `UsersData/${uid}/temperature`;
const dbPathHum = `UsersData/${uid}/humidity`;
const dbPathPres = `UsersData/${uid}/pressure`;
// Database references
const dbRefTemp = ref(database, dbPathTemp);
const dbRefHum = ref(database, dbPathHum);
const dbRefPres = ref(database, dbPathPres);
// Update page with new readings
onValue(dbRefTemp, (snap) => {
tempElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
onValue(dbRefHum, (snap) => {
humElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
onValue(dbRefPres, (snap) => {
presElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
} else {
// Toggle UI elements
loginElement.style.display = 'block';
authBarElement.style.display = 'none';
userDetailsElement.style.display = 'none';
contentElement.style.display = 'none';
}
};
// Expose setupUI to global scope for auth.js
window.setupUI = setupUI;
Продолжайте чтение, чтобы узнать, как работает код, или перейдите к следующему разделу.
Импорт модулей Firebase
Мы начинаем с импорта необходимых модулей Firebase.
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-app.js";
import { getAuth } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-auth.js";
import { getDatabase, ref, onValue } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-database.js";
Объект конфигурации Firebase
Измените следующие строки, вставив ваш объект конфигурации Firebase, который вы получили на предыдущих шагах.
const firebaseConfig = {
apiKey: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
authDomain: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
databaseURL: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
projectId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
storageBucket: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
messagingSenderId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION",
appId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION"
};
Инициализация приложения Firebase
Следующая строка инициализирует приложение Firebase с использованием предоставленного объекта firebaseConfig.
const app = initializeApp(firebaseConfig);
Затем создайте экземпляр аутентификации (auth), привязанный к инициализированному приложению Firebase (app). Функция getAuth из модуля Firebase Auth настраивает службу аутентификации для управления пользователями (вход, выход и т.д.).
const auth = getAuth(app);
Создайте экземпляр Firebase Realtime Database с именем database, привязанный к вашему приложению Firebase (app).
const database = getDatabase(app);
Затем мы экспортируем экземпляр auth, чтобы его можно было импортировать и использовать в других файлах JavaScript (в auth.js, как мы видели ранее).
export { auth };
Получение HTML-элементов
Создайте переменные для ссылки на несколько элементов пользовательского интерфейса по их идентификаторам. Для идентификации этих элементов мы рекомендуем вам посмотреть предоставленный HTML-файл и найти элементы с указанными идентификаторами.
// UI Elements
const loginElement = document.querySelector('#login-form');
const contentElement = document.querySelector("#content-sign-in");
const userDetailsElement = document.querySelector('#user-details');
const authBarElement = document.querySelector("#authentication-bar");
const tempElement = document.getElementById("temp");
const humElement = document.getElementById("hum");
const presElement = document.getElementById("pres");
loginElement соответствует форме входа. contentElement соответствует разделу веб-страницы, который виден, когда пользователь вошёл в систему (показывает показания датчиков). userDetailsElement соответствует разделу, который будет отображать email вошедшего пользователя. authBarElement соответствует панели аутентификации, которая показывает текущий статус пользователя, email аутентифицированного пользователя и ссылку для выхода.
Функция setupUI()
Затем мы создаём функцию setupUI(), которая будет обрабатывать пользовательский интерфейс в соответствии с состоянием аутентификации пользователя.
В файле auth.js мы вызывали функцию setupUI() с аргументом user setupUI(user), если пользователь вошёл в систему; или функцию с аргументом null, когда пользователь вышел из системы.
Итак, давайте проверим, что происходит, когда пользователь вошёл в систему.
if (user) {
Мы определяем, какие части пользовательского интерфейса должны быть видимыми или невидимыми. Когда пользователь вошёл в систему, мы хотим скрыть форму входа. Чтобы скрыть элемент, мы можем установить стиль отображения в none.
loginElement.style.display = 'none';
Мы показываем панель аутентификации (которая показывает данные пользователя и ссылку для выхода). Для этого мы можем установить стиль отображения в block. Мы также хотим, чтобы основной контент веб-страницы с показаниями датчиков был видимым.
contentElement.style.display = 'block';
authBarElement.style.display ='block';
Наконец, мы можем получить email вошедшего пользователя с помощью user.email и отобразить его в разделе userDetailsElement следующим образом:
userDetailsElement.innerHTML = user.email;
UID пользователя и пути базы данных
После того как у нас есть вошедший пользователь, мы можем получить его UID с помощью user.uid.
const uid = user.uid;
После получения UID пользователя мы создаём переменные для ссылки на пути базы данных, где мы сохраняем данные.
const dbPathTemp = `UsersData/${uid}/temperature`;
const dbPathHum = `UsersData/${uid}/humidity`;
const dbPathPres = `UsersData/${uid}/pressure`;
Затем мы создаём ссылки на базу данных по этим путям.
// Database references
const dbRefTemp = ref(database, dbPathTemp);
const dbRefHum = ref(database, dbPathHum);
const dbRefPres = ref(database, dbPathPres);
Отображение показаний датчиков
Следующие строки получают новые показания датчиков всякий раз, когда в базе данных происходит изменение, и обновляют соответствующие HTML-элементы новыми значениями. Также выполняется форматирование значений до двух десятичных знаков или возвращается N/A, если значение отсутствует.
// Update page with new readings
onValue(dbRefTemp, (snap) => {
tempElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
onValue(dbRefHum, (snap) => {
humElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
onValue(dbRefPres, (snap) => {
presElement.innerText = snap.val()?.toFixed(2) ?? "N/A";
});
Интерфейс при выходе из системы
Следующий фрагмент обрабатывает пользовательский интерфейс, когда пользователь выходит из системы. Мы хотим скрыть панель аутентификации и основной контент веб-страницы (показания датчиков) и показать форму входа.
} else {
// Toggle UI elements
loginElement.style.display = 'block';
authBarElement.style.display = 'none';
userDetailsElement.style.display = 'none';
contentElement.style.display = 'none';
}
Глобальный доступ к функции setupUI
Наконец, следующая строка делает функцию setupUI глобально доступной, присваивая её объекту window (объект window — это глобальный объект в браузере, доступный из любого файла JavaScript). По сути, это гарантирует, что другой файл JavaScript (auth.js) может использовать функцию setupUI для обновления пользовательского интерфейса при входе или выходе пользователя из системы.
window.setupUI = setupUI;
Файл favicon
Для отображения favicon в вашем веб-приложении вам нужно переместить изображение, которое вы хотите использовать в качестве favicon, в папку public. Изображение должно называться favicon.png. Вы можете просто перетащить файл favicon с вашего компьютера в папку public в VS Code.
Мы используем следующий значок в качестве favicon для нашего веб-приложения:
Развёртывание вашего приложения
После сохранения файлов HTML, CSS и JavaScript разверните приложение в VS Code, выполнив следующую команду в окне терминала.
firebase deploy
Терминал должен отобразить что-то подобное:
Firebase предлагает бесплатную услугу хостинга для обслуживания ваших ресурсов и веб-приложений. Затем вы можете получить доступ к вашему веб-приложению из любой точки мира.
Вы можете использовать URL-адрес хостинга для доступа к вашему веб-приложению из любой точки мира.
Демонстрация
Поздравляем! Вы успешно развернули ваше приложение. Теперь оно размещено на глобальном CDN с помощью Firebase Hosting. Вы можете получить доступ к вашему веб-приложению из любой точки мира по URL-адресу хостинга. В моём случае это https://esp-firebase-demo.web.app.
Веб-приложение является адаптивным, и вы можете получить к нему доступ с помощью смартфона, компьютера или планшета.
Устранение неполадок: если вы не видите веб-страницу веб-приложения, вам может потребоваться выполнить жёсткое обновление веб-браузера для очистки кэша.
Введите email и пароль авторизованного пользователя, которого вы добавили в методы аутентификации Firebase. После этого вы сможете получить доступ к последним показаниям датчиков.
Перейдите на вкладку Hosting в консоли Firebase вашего проекта. Вы можете увидеть домены вашего приложения, историю развёртывания и даже откатить приложение к предыдущим версиям.
Заключение
В этом руководстве вы узнали, как создать веб-приложение Firebase с аутентификацией входа/выхода, которое отображает показания датчиков. Показания датчиков сохраняются в базе данных реального времени. База данных защищена с помощью правил базы данных (которые вы уже настроили в предыдущем руководстве).
Вы можете применить полученные здесь знания для отображения любого другого типа данных, и вы можете изменять файлы в папке public, чтобы добавлять различные функции и возможности в ваш проект.
Если вы хотите узнать больше о Firebase, мы рекомендуем ознакомиться с нашей электронной книгой, посвящённой исключительно этой теме:
У нас есть другие ресурсы, связанные с ESP32 и ESP8266, которые могут вам понравиться:
Источник: :doc:`ESP32/ESP8266: Firebase Web App to Display Sensor Readings (with Authentication) <../esp32-esp8266-firebase-web-app-sensor/index>` (Random Nerd Tutorials)