In this project, you’ll create a Firebase Web App that displays all the sensor readings saved on the Firebase Realtime Database. We’ll create a web interface with gauges, charts, and a table to display all your data records. We’ll also add a button that allows you to delete all data from the database and checkboxes to customize the user interface. This web application will be protected with authentication (using email and password) and all the data is restricted to the user using database rules.
This project is Part 2 of the following tutorial (there is a version for ESP32 and a version for ESP8266):
You must follow one of those tutorials first, before proceeding
Here’s a summary of the web app features:
- login with email and password
- displays time of the last update
- cards to display the last sensor readings
- gauges to display the last sensor readings
- charts that display data history with timestamps
- select how many readings to display on charts
- checkboxes to enable/disable the different display options
- table that displays all readings saved on the database
- button to delete database data
Project Overview
In this tutorial (Part 2), you’ll create a web app to display the sensor readings logged with timestamps on the Firebase Realtime Database (read this previous tutorial – ESP32 version / ESP8266 version).
The following video shows the web app project we’ll build—programming the ESP32/ESP8266 and setting up the Firebase Project was done in Part 1 (ESP32 Part 1; ESP8266 Part 1).
- Firebase hosts your web app over a global CDN using Firebase Hosting and provides an SSL certificate. You can access your web app from anywhere using the Firebase-generated domain name.
- When you first access the web app, you need to authenticate with an authorized email address and password. You already set up that user and the authentication method in Part 1.
- After authentication, you can access a web app page that shows the sensor readings. The sensor readings are displayed in cards, gauges, charts and table. You can select how many readings you want to show on the charts and you can also choose how you can view your data.
- There is a button to show/hide all readings saved on the database on a table with timestamps.
- There’s also a Delete button that allows you to delete all data from the database.
- All the data is restricted using database rules.
Prerequisites
Before start creating the Firebase Web App, you need to check the following prerequisites:
Creating a Firebase Project
You should have followed one of the next tutorials first:
The ESP32/ESP8266 must be running the code provided in that tutorial. The realtime database and authentication must be set up also as shown in the tutorial.
Install Required Software
Before getting started you need to install the required software to create the Firebase Web App. Here’s a list of the software you need to install (click on the links for instructions):
1) Add an App to Your Firebase Project
1) Go to your Firebase project Console and add an app to your project by clicking on the +Add app button.
2) Select the web app icon.
3) Give your app a name. Then, check the box next to √ Also set up Firebase Hosting for this App. Click Register app.
4) Then, copy the firebaseConfig object and save it because you’ll need it later.
After this, you can also access the firebaseConfig object if you go to your Project settings in your Firebase console.
5) Click Next on the proceeding steps, and finally on Continue to console.
2) Setting Up a Firebase Web App Project (VS Code)
Follow the next steps to create a Firebase Web App Project using VS Code.
1) Creating a Project Folder
1) Create a folder on your computer where you want to save your Firebase project—for example, Firebase-Project on the Desktop.
2) Open VS Code. Go to File > Open Folder… and select the folder you’ve just created.
3) Go to Terminal > New Terminal. A new Terminal window should open on your project path.
2) Firebase Login
4) On the previous Terminal window, type the following:
firebase login
5) You’ll be asked to collect CLI usage and error reporting information. Enter “n” and press Enter to deny.
Note: If you are already logged in, it will show a message saying: “Already logged in as [email protected]”.
6) After this, it will pop up a new window on your browser to login into your firebase account.
7) Allow Firebase CLI to access your google account.
8) After this, Firebase CLI login should be successful. You can close the browser window.
3) Initializing Web App Firebase Project
9) After successfully login in, run the following command to start a Firebase project directory in the current folder.
firebase init
10) You’ll be asked if you want to initialize a Firebase project in the current directory. Enter Y and hit Enter.
11) Then, use up and down arrows and the Space key to select the options. Select the following options:
- 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
The selected options will show up with a green asterisk. Then, hit Enter.
12) Select the option “Use an existing project”—it should be highlighted in blue—then, hit Enter.
13) After that, select the Firebase project for this directory—it should be the project created in this previous tutorial. In my case, it is called esp-firebase-demo. Then hit Enter.
14) Press Enter on the following question to select the default database security rules file: “What file should be used for Realtime Database Security Rules?“
15) Then, select the hosting options as shown below:
- What do you want to use as your public directory? Hit Enter to select public.
- Configure as a single-page app (rewrite urls to /index.html)? No
- Set up automatic builds and deploys with GitHub? No
16) The Firebase project should now be initialized successfully. Notice that VS code created some essential files under your project folder.
The index.html file contains some HTML text to build a web page. For now, leave the default HTML text. The idea is to replace that with your own HTML text to build a custom web page for your needs. We’ll do that later in this tutorial.
17) To check if everything went as expected, run the following command on the VS Code Terminal window.
firebase deploy
You should get a Deploy complete! message and an URL to the Project Console and the Hosting URL.
18) Copy the hosting URL and paste it into a web browser window. You should see the following web page. You can access that web page from anywhere in the world.
The web page you’ve seen previously is built with the HTML file placed in the public folder of your Firebase project. By changing the content of that file, you can create your own web app. That’s what we’re going to do in the next section.
3) Creating Firebase Web App
Now that you’ve created a Firebase project app successfully on VS Code, follow the next steps to customize the app to display the sensor readings on a login-protected web page.
index.html
Copy the following to your index.html file (it is inside the public folder).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ESP Datalogging Firebase App</title>
<!-- include Firebase SDK -->
<script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js"></script>
<!-- include only the Firebase features as you need -->
<script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-database.js"></script>
<script>
// Replace with your app config object
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
firebase.initializeApp(firebaseConfig);
// Make auth and database references
const auth = firebase.auth();
const db = firebase.database();
</script>
<!-- include highchartsjs to build the charts-->
<script src="https://code.highcharts.com/highcharts.js"></script>
<!-- include to use jquery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!--include icons from fontawesome-->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<!-- include Gauges Javascript library-->
<script src="https://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>
<!--reference for favicon-->
<link rel="icon" type="image/png" href="favicon.png">
<!--reference a stylesheet-->
<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;">
<!--LAST UPDATE-->
<p><span class ="date-time">Last update: <span id="lastUpdate"></span></span></p>
<p>
Cards: <input type="checkbox" id="cards-checkbox" name="cards-checkbox" checked>
Gauges: <input type="checkbox" id="gauges-checkbox" name="gauges-checkbox" checked>
Charts: <input type="checkbox" id="charts-checkbox" name="charts-checkbox" unchecked>
</p>
<div id="cards-div">
<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>
<!--GAUGES-->
<div id ="gauges-div">
<div class="cards">
<!--TEMPERATURE-->
<div class="card">
<canvas id="gauge-temperature"></canvas>
</div>
<!--HUMIDITY-->
<div class="card">
<canvas id="gauge-humidity"></canvas>
</div>
</div>
</div>
<!--CHARTS-->
<div id="charts-div" style="display:none">
<!--SET NUMBER OF READINGS INPUT FIELD-->
<div>
<p> Number of readings: <input type="number" id="charts-range"></p>
</div>
<!--TEMPERATURE-CHART-->
<div class="cards">
<div class="card">
<p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> TEMPERATURE CHART</p>
<div id="chart-temperature" class="chart-container"></div>
</div>
</div>
<!--HUMIDITY-CHART-->
<div class="cards">
<div class="card">
<p><i class="fas fa-tint" style="color:#00add6;"></i> HUMIDITY CHART</p>
<div id="chart-humidity" class="chart-container"></div>
</div>
</div>
<!--PRESSURE-CHART-->
<div class="cards">
<div class="card">
<p><i class="fas fa-angle-double-down" style="color:#e1e437;"></i> PRESSURE CHART</p>
<div id="chart-pressure" class="chart-container"></div>
</div>
</div>
</div>
<!--BUTTONS TO HANDLE DATA-->
<p>
<!--View data button-->
<button id="view-data-button">View all data</button>
<!--Hide data button-->
<button id="hide-data-button" style= "display:none;">Hide data</button>
<!--Delete data button-->
<button id="delete-button" class="deletebtn">Delete data</button>
</p>
<!--Modal to delete data-->
<div id="delete-modal" class="modal" sytle="display:none">
<span onclick = "document.getElementById('delete-modal').style.display='none'" class="close" title="Close Modal">×</span>
<form id= "delete-data-form" class="modal-content" action="/">
<div class="container">
<h1>Delete Data</h1>
<p>Are you sure you want to delete all data from database?</p>
<div class="clearfix">
<button type="button" onclick="document.getElementById('delete-modal').style.display='none'" class="cancelbtn">Cancel</button>
<button type="submit" onclick="document.getElementById('delete-modal').style.display='none'" class="deletebtn">Delete</button>
</div>
</div>
</form>
</div>
<!--TABLE WITH ALL DATA-->
<div class ="cards">
<div class="card" id="table-container" style= "display:none;">
<table id="readings-table">
<tr id="theader">
<th>Timestamp</th>
<th>Temp (ºC)</th>
<th>Hum (%)</th>
<th>Pres (hPa)</th>
</tr>
<tbody id="tbody">
</tbody>
</table>
<p><button id="load-data" style= "display:none;">More results...</button></p>
</div>
</div>
</div>
<!--INCLUDE JS FILES-->
<script src="scripts/auth.js"></script>
<script src="scripts/charts-definition.js"></script>
<script src="scripts/gauges-definition.js"></script>
<script src="scripts/index.js"></script>
</body>
</html>
Important: you need to modify the code with your own firebaseConfig object—the one you’ve got in this step.
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"
};
style.css
Inside the public folder create a file called style.css. To create the file, select the public folder, and then click on the +file icon at the top of the File Explorer. Call it style.css.
Then, copy the following to the style.css file
html {
font-family: Verdana, Geneva, Tahoma, sans-serif;
display: inline-block;
text-align: center;
}
body {
margin: 0;
width: 100%;
}
.topnav {
overflow: hidden;
background-color: #049faa;
color: white;
font-size: 1rem;
padding: 5px;
}
#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;
margin-bottom: 10px;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 2fr));
}
.reading {
color: #193036;
}
.date-time{
font-size: 0.8rem;
color: #1282A2;
}
button {
background-color: #049faa;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
border-radius: 4px;
}
button:hover {
opacity: 0.8;
}
.deletebtn{
background-color: #c52c2c;
}
.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;
}
table {
width: 100%;
text-align: center;
font-size: 0.8rem;
}
tr, td {
padding: 0.25rem;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
tr:hover {
background-color: #ddd;
}
th {
position: sticky;
top: 0;
background-color: #50b8b4;
color: white;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: #474e5d;
padding-top: 50px;
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 5% auto 15% auto; /* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
}
/* Style the horizontal ruler */
hr {
border: 1px solid #f1f1f1;
margin-bottom: 25px;
}
/* The Modal Close Button (x) */
.close {
position: absolute;
right: 35px;
top: 15px;
font-size: 40px;
font-weight: bold;
color: #f1f1f1;
}
.close:hover,
.close:focus {
color: #f44336;
cursor: pointer;
}
/* Clear floats */
.clearfix::after {
content: "";
clear: both;
display: table;
}
/* Change styles for cancel button and delete button on extra small screens */
@media screen and (max-width: 300px) {
.cancelbtn, .deletebtn {
width: 100%;
}
}
The CSS file includes some simple styles to make our webpage look better. We won’t discuss how CSS works in this tutorial.
JavaScript Files
We’ll create four JavaScript files (auth.js, index.js, charts-definition.js, and gauges-definition.js) inside a scripts folder inside the public folder.
- Select the public folder, then click on the +folder icon to create a new folder. Call scripts to that new folder.
- Then, select the scripts folder and click on the +file icon. Create a file called auth.js. Then, repeat the previous steps to create the index.js, charts-definition.js, and gauges-definition.js files.
The following image shows what your web app project folder structure should look like.
auth.js
Copy the following to the auth.js file you created previously.
document.addEventListener("DOMContentLoaded", function(){
// listen for auth status changes
auth.onAuthStateChanged(user => {
if (user) {
console.log("user logged in");
console.log(user);
setupUI(user);
var uid = user.uid;
console.log(uid);
} else {
console.log("user logged out");
setupUI();
}
});
// login
const loginForm = document.querySelector('#login-form');
loginForm.addEventListener('submit', (e) => {
e.preventDefault();
// get user info
const email = loginForm['input-email'].value;
const password = loginForm['input-password'].value;
// log the user in
auth.signInWithEmailAndPassword(email, password).then((cred) => {
// close the login modal & reset form
loginForm.reset();
console.log(email);
})
.catch((error) =>{
const errorCode = error.code;
const errorMessage = error.message;
document.getElementById("error-message").innerHTML = errorMessage;
console.log(errorMessage);
});
});
// logout
const logout = document.querySelector('#logout-link');
logout.addEventListener('click', (e) => {
e.preventDefault();
auth.signOut();
});
});
Then, save the file. This file takes care of everything related to the login and logout of the user.
index.js
The index.js file handles the UI—it shows the right content depending on the user authentication status. When the user is logged in, this file gets new readings from the database whenever there’s a change and displays them in the right places.
Copy the following to the index.js file.
// convert epochtime to JavaScripte Date object
function epochToJsDate(epochTime){
return new Date(epochTime*1000);
}
// convert time to human-readable format YYYY/MM/DD HH:MM:SS
function epochToDateTime(epochTime){
var epochDate = new Date(epochToJsDate(epochTime));
var dateTime = epochDate.getFullYear() + "/" +
("00" + (epochDate.getMonth() + 1)).slice(-2) + "/" +
("00" + epochDate.getDate()).slice(-2) + " " +
("00" + epochDate.getHours()).slice(-2) + ":" +
("00" + epochDate.getMinutes()).slice(-2) + ":" +
("00" + epochDate.getSeconds()).slice(-2);
return dateTime;
}
// function to plot values on charts
function plotValues(chart, timestamp, value){
var x = epochToJsDate(timestamp).getTime();
var y = Number (value);
if(chart.series[0].data.length > 40) {
chart.series[0].addPoint([x, y], true, true, true);
} else {
chart.series[0].addPoint([x, y], true, false, true);
}
}
// DOM 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 deleteButtonElement = document.getElementById('delete-button');
const deleteModalElement = document.getElementById('delete-modal');
const deleteDataFormElement = document.querySelector('#delete-data-form');
const viewDataButtonElement = document.getElementById('view-data-button');
const hideDataButtonElement = document.getElementById('hide-data-button');
const tableContainerElement = document.querySelector('#table-container');
const chartsRangeInputElement = document.getElementById('charts-range');
const loadDataButtonElement = document.getElementById('load-data');
const cardsCheckboxElement = document.querySelector('input[name=cards-checkbox]');
const gaugesCheckboxElement = document.querySelector('input[name=gauges-checkbox]');
const chartsCheckboxElement = document.querySelector('input[name=charts-checkbox]');
// DOM elements for sensor readings
const cardsReadingsElement = document.querySelector("#cards-div");
const gaugesReadingsElement = document.querySelector("#gauges-div");
const chartsDivElement = document.querySelector('#charts-div');
const tempElement = document.getElementById("temp");
const humElement = document.getElementById("hum");
const presElement = document.getElementById("pres");
const updateElement = document.getElementById("lastUpdate")
// 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;
// get user UID to get data from database
var uid = user.uid;
console.log(uid);
// Database paths (with user UID)
var dbPath = 'UsersData/' + uid.toString() + '/readings';
var chartPath = 'UsersData/' + uid.toString() + '/charts/range';
// Database references
var dbRef = firebase.database().ref(dbPath);
var chartRef = firebase.database().ref(chartPath);
// CHARTS
// Number of readings to plot on charts
var chartRange = 0;
// Get number of readings to plot saved on database (runs when the page first loads and whenever there's a change in the database)
chartRef.on('value', snapshot =>{
chartRange = Number(snapshot.val());
console.log(chartRange);
// Delete all data from charts to update with new values when a new range is selected
chartT.destroy();
chartH.destroy();
chartP.destroy();
// Render new charts to display new range of data
chartT = createTemperatureChart();
chartH = createHumidityChart();
chartP = createPressureChart();
// Update the charts with the new range
// Get the latest readings and plot them on charts (the number of plotted readings corresponds to the chartRange value)
dbRef.orderByKey().limitToLast(chartRange).on('child_added', snapshot =>{
var jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
// Save values on variables
var temperature = jsonData.temperature;
var humidity = jsonData.humidity;
var pressure = jsonData.pressure;
var timestamp = jsonData.timestamp;
// Plot the values on the charts
plotValues(chartT, timestamp, temperature);
plotValues(chartH, timestamp, humidity);
plotValues(chartP, timestamp, pressure);
});
});
// Update database with new range (input field)
chartsRangeInputElement.onchange = () =>{
chartRef.set(chartsRangeInputElement.value);
};
//CHECKBOXES
// Checbox (cards for sensor readings)
cardsCheckboxElement.addEventListener('change', (e) =>{
if (cardsCheckboxElement.checked) {
cardsReadingsElement.style.display = 'block';
}
else{
cardsReadingsElement.style.display = 'none';
}
});
// Checbox (gauges for sensor readings)
gaugesCheckboxElement.addEventListener('change', (e) =>{
if (gaugesCheckboxElement.checked) {
gaugesReadingsElement.style.display = 'block';
}
else{
gaugesReadingsElement.style.display = 'none';
}
});
// Checbox (charta for sensor readings)
chartsCheckboxElement.addEventListener('change', (e) =>{
if (chartsCheckboxElement.checked) {
chartsDivElement.style.display = 'block';
}
else{
chartsDivElement.style.display = 'none';
}
});
// CARDS
// Get the latest readings and display on cards
dbRef.orderByKey().limitToLast(1).on('child_added', snapshot =>{
var jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
var temperature = jsonData.temperature;
var humidity = jsonData.humidity;
var pressure = jsonData.pressure;
var timestamp = jsonData.timestamp;
// Update DOM elements
tempElement.innerHTML = temperature;
humElement.innerHTML = humidity;
presElement.innerHTML = pressure;
updateElement.innerHTML = epochToDateTime(timestamp);
});
// GAUGES
// Get the latest readings and display on gauges
dbRef.orderByKey().limitToLast(1).on('child_added', snapshot =>{
var jsonData = snapshot.toJSON(); // example: {temperature: 25.02, humidity: 50.20, pressure: 1008.48, timestamp:1641317355}
var temperature = jsonData.temperature;
var humidity = jsonData.humidity;
var pressure = jsonData.pressure;
var timestamp = jsonData.timestamp;
// Update DOM elements
var gaugeT = createTemperatureGauge();
var gaugeH = createHumidityGauge();
gaugeT.draw();
gaugeH.draw();
gaugeT.value = temperature;
gaugeH.value = humidity;
updateElement.innerHTML = epochToDateTime(timestamp);
});
// DELETE DATA
// Add event listener to open modal when click on "Delete Data" button
deleteButtonElement.addEventListener('click', e =>{
console.log("Remove data");
e.preventDefault;
deleteModalElement.style.display="block";
});
// Add event listener when delete form is submited
deleteDataFormElement.addEventListener('submit', (e) => {
// delete data (readings)
dbRef.remove();
});
// TABLE
var lastReadingTimestamp; //saves last timestamp displayed on the table
// Function that creates the table with the first 100 readings
function createTable(){
// append all data to the table
var firstRun = true;
dbRef.orderByKey().limitToLast(100).on('child_added', function(snapshot) {
if (snapshot.exists()) {
var jsonData = snapshot.toJSON();
console.log(jsonData);
var temperature = jsonData.temperature;
var humidity = jsonData.humidity;
var pressure = jsonData.pressure;
var timestamp = jsonData.timestamp;
var content = '';
content += '<tr>';
content += '<td>' + epochToDateTime(timestamp) + '</td>';
content += '<td>' + temperature + '</td>';
content += '<td>' + humidity + '</td>';
content += '<td>' + pressure + '</td>';
content += '</tr>';
$('#tbody').prepend(content);
// Save lastReadingTimestamp --> corresponds to the first timestamp on the returned snapshot data
if (firstRun){
lastReadingTimestamp = timestamp;
firstRun=false;
console.log(lastReadingTimestamp);
}
}
});
};
// append readings to table (after pressing More results... button)
function appendToTable(){
var dataList = []; // saves list of readings returned by the snapshot (oldest-->newest)
var reversedList = []; // the same as previous, but reversed (newest--> oldest)
console.log("APEND");
dbRef.orderByKey().limitToLast(100).endAt(lastReadingTimestamp).once('value', function(snapshot) {
// convert the snapshot to JSON
if (snapshot.exists()) {
snapshot.forEach(element => {
var jsonData = element.toJSON();
dataList.push(jsonData); // create a list with all data
});
lastReadingTimestamp = dataList[0].timestamp; //oldest timestamp corresponds to the first on the list (oldest --> newest)
reversedList = dataList.reverse(); // reverse the order of the list (newest data --> oldest data)
var firstTime = true;
// loop through all elements of the list and append to table (newest elements first)
reversedList.forEach(element =>{
if (firstTime){ // ignore first reading (it's already on the table from the previous query)
firstTime = false;
}
else{
var temperature = element.temperature;
var humidity = element.humidity;
var pressure = element.pressure;
var timestamp = element.timestamp;
var content = '';
content += '<tr>';
content += '<td>' + epochToDateTime(timestamp) + '</td>';
content += '<td>' + temperature + '</td>';
content += '<td>' + humidity + '</td>';
content += '<td>' + pressure + '</td>';
content += '</tr>';
$('#tbody').append(content);
}
});
}
});
}
viewDataButtonElement.addEventListener('click', (e) =>{
// Toggle DOM elements
tableContainerElement.style.display = 'block';
viewDataButtonElement.style.display ='none';
hideDataButtonElement.style.display ='inline-block';
loadDataButtonElement.style.display = 'inline-block'
createTable();
});
loadDataButtonElement.addEventListener('click', (e) => {
appendToTable();
});
hideDataButtonElement.addEventListener('click', (e) => {
tableContainerElement.style.display = 'none';
viewDataButtonElement.style.display = 'inline-block';
hideDataButtonElement.style.display = 'none';
});
// IF USER IS LOGGED OUT
} else{
// toggle UI elements
loginElement.style.display = 'block';
authBarElement.style.display ='none';
userDetailsElement.style.display ='none';
contentElement.style.display = 'none';
}
}
charts-definition.js
Copy the following to the charts-definition.js file. This file creates the different charts using the highcharts javascript library.
// Create the charts when the web page loads
window.addEventListener('load', onload);
function onload(event){
chartT = createTemperatureChart();
chartH = createHumidityChart();
chartP = createPressureChart();
}
// Create Temperature Chart
function createTemperatureChart() {
var chart = new Highcharts.Chart({
chart:{
renderTo:'chart-temperature',
type: 'spline'
},
series: [
{
name: 'BME280'
}
],
title: {
text: undefined
},
plotOptions: {
line: {
animation: false,
dataLabels: {
enabled: true
}
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: {
text: 'Temperature Celsius Degrees'
}
},
credits: {
enabled: false
}
});
return chart;
}
// Create Humidity Chart
function createHumidityChart(){
var chart = new Highcharts.Chart({
chart:{
renderTo:'chart-humidity',
type: 'spline'
},
series: [{
name: 'BME280'
}],
title: {
text: undefined
},
plotOptions: {
line: {
animation: false,
dataLabels: {
enabled: true
}
},
series: {
color: '#50b8b4'
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: {
text: 'Humidity (%)'
}
},
credits: {
enabled: false
}
});
return chart;
}
// Create Pressure Chart
function createPressureChart() {
var chart = new Highcharts.Chart({
chart:{
renderTo:'chart-pressure',
type: 'spline'
},
series: [{
name: 'BME280'
}],
title: {
text: undefined
},
plotOptions: {
line: {
animation: false,
dataLabels: {
enabled: true
}
},
series: {
color: '#A62639'
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: {
text: 'Pressure (hPa)'
}
},
credits: {
enabled: false
}
});
return chart;
}
gauges-definition.js
In our web app, we’ll display a gauge for the temperature and another for the humidity. The gauges-definition.js file contains functions to create the gauges.
// Create Temperature Gauge
function createTemperatureGauge() {
var gauge = new LinearGauge({
renderTo: 'gauge-temperature',
width: 120,
height: 400,
units: "Temperature C",
minValue: 0,
startAngle: 90,
ticksAngle: 180,
maxValue: 40,
colorValueBoxRect: "#049faa",
colorValueBoxRectEnd: "#049faa",
colorValueBoxBackground: "#f1fbfc",
valueDec: 2,
valueInt: 2,
majorTicks: [
"0",
"5",
"10",
"15",
"20",
"25",
"30",
"35",
"40"
],
minorTicks: 4,
strokeTicks: true,
highlights: [
{
"from": 30,
"to": 40,
"color": "rgba(200, 50, 50, .75)"
}
],
colorPlate: "#fff",
colorBarProgress: "#CC2936",
colorBarProgressEnd: "#049faa",
borderShadowWidth: 0,
borders: false,
needleType: "arrow",
needleWidth: 2,
needleCircleSize: 7,
needleCircleOuter: true,
needleCircleInner: false,
animationDuration: 1500,
animationRule: "linear",
barWidth: 10,
});
return gauge;
}
// Create Humidity Gauge
function createHumidityGauge(){
var gauge = new RadialGauge({
renderTo: 'gauge-humidity',
width: 300,
height: 300,
units: "Humidity (%)",
minValue: 0,
maxValue: 100,
colorValueBoxRect: "#049faa",
colorValueBoxRectEnd: "#049faa",
colorValueBoxBackground: "#f1fbfc",
valueInt: 2,
majorTicks: [
"0",
"20",
"40",
"60",
"80",
"100"
],
minorTicks: 4,
strokeTicks: true,
highlights: [
{
"from": 80,
"to": 100,
"color": "#03C0C1"
}
],
colorPlate: "#fff",
borderShadowWidth: 0,
borders: false,
needleType: "line",
colorNeedle: "#007F80",
colorNeedleEnd: "#007F80",
needleWidth: 2,
needleCircleSize: 3,
colorNeedleCircleOuter: "#007F80",
needleCircleOuter: true,
needleCircleInner: false,
animationDuration: 1500,
animationRule: "linear"
});
return gauge;
}
Favicon File
To display a favicon in your web app, you need to move the picture you want to use as favicon to the public folder. The picture should be called favicon.png. You can simply drag the favicon file from your computer into the public folder in VS Code.
We’re using the following icon as a favicon for our web app:
Deploy your App
After saving the HTML, CSS, and JavaScript files, deploy your app on VS Code by running the following command on the Terminal window.
firebase deploy
The Terminal should display something as follows:
Firebase offers a free hosting service to serve your assets and web apps. Then, you can access your web app from anywhere.
You can use the Hosting URL provided to access your web app from anywhere.
Demonstration
Congratulations! You successfully deployed your app. It is now hosted on a global CDN using Firebase hosting. You can access your web app from anywhere on the Hosting URL provided. In my case, it is https://esp-firebase-demo.web.app.
The web app is responsive, and you can access it using your smartphone, computer, or tablet.
When you first access the web app, you’ll see a form to insert the email username and password.
Insert the email and password of the authorized user you added in the Firebase Authentication methods. If the form doesn’t show up at first, refresh the web page. After that, you can access the web page with the readings.
The readings are displayed in cards, gauges, charts, and a table. You can also select which interfaces you want to see by checking/unchecking the checkboxes.
You can also check the readings displayed on charts. You can select the charts range, but keep in mind that selecting more than 30 readings will take some time.
Finally, if you want to see all the readings. You can open the readings table. At the end of the table, there’s a button to load more readings until all readings are displayed.
There is also a button to delete all data if you want to remove all readings from the database.
Here’s a video showing how the web app works.
Wrapping Up
In this tutorial, you created a Firebase Web App with login/logout authentication that displays sensor readings in many different ways. The sensor readings are saved on the realtime database. The database is protected using database rules (that you’ve already set up in a previous tutorial).
You can apply what you learned here to display any other type of data, and you can change the files in the public folder to add different functionalities and features to your project.
We didn’t explain how the javascript files work because the project is quite long. However, if there is enough interest in this subject, we can split this application into smaller projects so that you understand how to handle data using queries and how to display it in different ways. Let us know what you think in the comments below.
If you want to learn more about Firebase, we recommend taking a look at our new eBook, exclusively dedicated to this subject:
We have other resources related to ESP32 and ESP8266 that you may like:
Thanks for reading.
It will work with hostinger host instead firebase?
No.
this project is just for firebase.
Do the graphs move as the readings are taken becuase it is not obvious in the video? Thank you for this effort.
Yes.
Nice project! One minor issue is that each time we have an update of data, the values of the gauges (arrows of gauges) go first to 0 and after to the right value.
Also, the time in the charts is 2 hours behind. I tried to change the js file and the parameters of ntp server, but still having this issue.
Do you have maybe an example of Modbus RTU communication? For example: communication with HMI – reading of digital outputs, temperature measurement…
This is great work! Thank you for putting it all together. It appears to be well-informed and well-researched.
Thank you 🙂
When I go to the app URL I don’t see the login screen, just the Heading Sensor Readings App.
Hi.
Refresh the web page and see if the login screen shows up.
Open the Javascript console and check if there are any error messages.
Regards,
Sara
Sara, I did try refreshing the web page. I will go through it again today and double check everything.
Redid everything and cleared the browser cache, all working, thanks.
Great!
Hi,
Having the same problem as Michael Walton I refreshed the web page.
Helas no difference.
How do I open the Javascript console in Google Chrome ?
Thank you in advance.
P.s. where can I find documentation if I want to alter the scripts in case I only want to upload less data to firebase and display them ?
Greetings,
René.
Hi.
Hard refresh your web browser and clear the cache.
To open the console: CTRL+SHIFT+J.
Firebase documentation: https://firebase.google.com/docs/database/admin/retrieve-data#section-queries
I hope this helps.
Regards.
Sara
Thank you Sara for your quick reply.
The information from the console:
auth.js:1 Failed to load resource: the server responded with a status of 404 ()
test-1-30f43.firebaseapp.com/:1 [DOM] Input elements should have autocomplete attributes (suggested: “current-password”): (More info: https://goo.gl/9p2vKq)
highcharts.src.js:226 Highcharts warning: Consider including the “accessibility.js” module to make your chart more usable for people with disabilities. Set the “accessibility.enabled” option to false to remove this warning. See https://www.highcharts.com/docs/accessibility/accessibility-module.
(anoniem) @ highcharts.src.js:226
I checkt the login settings in firebase -> Authentication -> sign-in method.
It is set to Email/password.
What do I have to change and where ?
Greetings,
René.
Hi.
I think you forgot to include the auth.js file in your application.
Regards
Sara
Hi Sara,
I found it, there was a typo in the name of the auth-file.
“auith.js”
Ordered new contact lenses.
Sorry to have bordered you with such a stupid mistake.
Eveyithing works fine, nice project, thank you.
Regards,
René.
Good Afternoon,
thank you for your new project.
I was able to show with almost no problems.
But I have a problem with the time between the read sensor time (e.g. 17:30:54) and the time in the chart display (15:30:54), i.e. a time difference of two hours.
In which file can I set my time zone?
Kind Regards
Juergen
Hi.
The timestamp you get on the Arduino IDE, is it correct?
You can compare it with the current epoch time here: https://www.epochconverter.com/
Are you using ESP32 or ESP8266?
Regards,
Sara
Good Morning,
thank you for your answer.
I think the timestamp is correct:
My timestamp = 1645346615 –> Sun Feb 20 10:43:35 2022 (localtime), GMT = 8:43:35.
The localtime is correct.
I use the ESP32.
I think there is a difference between localtime and GMT.
My home is in Nelspruit, ZA.
Kind Regards
Juergen
Good Afternoon,
the timestamp in index.js is also ok:
timestamp: 1645352195 index.js:104:17 (console.log(“timestamp: ” + timestamp);) added
Sun Feb 20 2022 12:16:36 GMT+0200 (Südafrikanische Time).
In the charts: 10:15
Kind Regards
Juergen
Good Afternoon,
I have the following line in the index.js file in the plotValues function:
var x = (epochToJsDate(timestamp).getTime()) + 7200000;
changed –> the time in the charts is displayed correctly for my time zone.
7200000 = 2 * 60 * 60 * 1000, hourminuteseconds*1000.
Kind Regards
Juergen
Great!
Necesitas definir tu zona horaria. Yo coloqué el siguiente código en el archivo charts-definitio.js, dentro de la función que crea el gráfico:
Highcharts.setOptions({
time: {
timezone: ‘America/Caracas’
}
});
Adicionalmente, necesitas agregar las siguientes lineas en el archivo index.html:
https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js
https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js
Puedes revisar la documentación de moment
Thanks for sharing that.
Or you can add:
useUTC: false
in the chart properties. Check it here: https://api.highcharts.com/highcharts/time.useUTC
Here’s an example in this discussion: https://www.highcharts.com/forum/viewtopic.php?t=46034
Regards,
Sara
Hi,
Thanks for this great tutorial. Is it possible to organize 20 to 30 devices in the same app?
Hi.
Yes, you just need to make sure that those devices login as an authorized user.
Then, you can organize your database in a different way to organize the data by device.
Regards,
Sara
Very good project. I have almost no knowledge about Firebase and java scripts, so I had to copy everything from this web. Now I try to learn what is doing what.
I see the first part that is collecting data and writhing to the database is the easy part and the part I know about. To be able to store the data and see it form the rest of the world has been my dream for several years. Thank you. Now I feel it is within reach to make data collection from my boat, cottage and house. The next will be to turn on heat on the cottage from my phone.
The chart is not working for me. I have tryed with 5 readings, but no result. Is it only me, or is this a common problem?
Hi.
Please open the javascript console and check if there are any errors in the web browser.
Regards,
Sara
Hello Svein,
I have the same problem. Using the shift+ctl+J function in the browser I found out, that the var chartRange contains 0. This is not accepted by the function limitToLast. Something seems to be wrong around the databasepath
var chartRef = firebase.database().ref(chartPath);
I keep on searching. Please let me know, if or how You solved the problem.
regards Ulli
Hi Svein,
for me the problem was solved, when I entered a number in the “number of readings” field. I simply had forgotten to do this. Now everything works fine!
Regards Ulli
Great project, worked first time. I immediately started to add more sensors, charts and gauges.
That’s great!
Hello
I like your tutorials and have usually no problem with them because they are well detailed.
But this time, I have no success with the latest tutorial.
Following the first part of the Firebase tutorial (ESP32 Data Logging to Firebase Realtime Database), I can read the values given by the sensor on the browser page, but the second part (ESP32/ESP8266: Firebase Data Logging Web App (Gauges, Charts, and Table)) does not show any values for the sensor nor time stamps or something in the “Last update” field on the browser page.
I must have missed something but was not able to find what it is . . . .
Any ideas?
Buenas tardes @paseo
Estoy en tu misma situación, alguna idea en el foro??
Hi. What is exactly the issue?
Read all the comments to check if any answers your question.
Regards.
Sara
Uncaught ReferenceError: chartT is not defined
at index.js:86:9
at o (Reference.ts:253:16)
at za.onValue (EventRegistration.ts:56:27)
at Reference_impl.ts:850:30
at Be (util.ts:546:5)
at EventQueue.ts:160:7
at ha (EventQueue.ts:128:9)
at la (EventQueue.ts:108:3)
at ga (Repo.ts:406:3)
at tn.a.server_ [as onDataUpdate_] (Repo.ts:256:9)
util.ts:556 Uncaught ReferenceError: chartT is not defined
at index.js:86:9
at o (Reference.ts:253:16)
at za.onValue (EventRegistration.ts:56:27)
at Reference_impl.ts:850:30
at Be (util.ts:546:5)
at EventQueue.ts:160:7
at ha (EventQueue.ts:128:9)
at la (EventQueue.ts:108:3)
at ba (Repo.ts:541:3)
at as (Reference_impl.ts:677:3)
Sorry for this long text, but maybe someone can see what is wrong.
chartT is not defined.
This might be a clue?
Hi.
Make sure you’ve created all the necessary Javascript files and in the right place.
Hard refresh your web browser after deploying your app.
Regards,
Sara
My problem is solved now. I followed the tutorial “ESP32 Data Logging to Firebase Realtime Database” a couple of days after it was published on the Random Nerd web site. But I found that the main.ccp file has been modified in the mean time by addition of #include “time.h”, several tempPath, time stamp, etc. . . . When using this modified main.ccp file, everything is now working.
As with Juergen above, when looking at the readings, the time stamp in the readings is correct, but the time shown on the charts is one hour less (= GMT, I live in a GMT+1 zone). Could it be that the firebase server (the one assigned to me is Europe-west1) is using GMT as basis, not taking account of the timestamp sent to it? How can I modify this to have the correct time on the charts?
Hi.
I accidentally deleted your next comment.
Were you able to solve the issue after following Juergen’s suggestion?
Regards.
Sara
Yes, solved.
Thank you.
Is there an easy way to show more than one value on a chart? I have adjusted the programme to read three DS18B20 sensors and would like to display all three temperatures on one graph. I am guessing it is something to do with the plotValues function in index.js?
Great project – I’m new to VS and Firebase. It’s all working for me except gauges. I realized that my gauges-definition.js file is missing from Firebase, but running “Firebase deploy” again in VS doesn’t seem to upload the missing file. Any suggestions or hints? Thanks.
Hi.
Make sure your charts-definition.js file is located in the scripts folder.
Hard refresh your web browser after deploying.
Regards,
Sara
When you say “Hard refresh” – is this simply closing the tab in the browser and re-opening? Do I need to close the browser and all the tabs? reboot the PC?
I am also trying to find why the temperature is showing “76.9 C” – where should I change to show Fahrenheit?
Hi.
A hard refresh clears your browser cache for a specific page, which forces it to load the most recent version of that page. This could include new scripts, styles or features.
If you’re using google chrome:
Windows users: hold down Ctrl and then press F5 on your keyboard
Mac users: hold down Cmd and Shift and then press R on your keyboard
To show in Fahrenheit, you need to do the conversion on the code before sending the data to the database.
Regards,
Sara
Is there an easy way to show multiple lines on one chart. I have modified the programme to sense 3 x DS18B20 and want to show them on one graph? I am guessing the plotValues function in index.js will need modifying.
I have now worked it out. Added extra names in charts-definition and changed plotValues function to plot the other lines.
Great!
Could you give more details? Or give the examples of what you modified? Thank you.
In charts-definition.js
// Create Temperature Chart
function createTemperatureChart() {
var chart = new Highcharts.Chart({
chart:{
renderTo:’chart-temperature’,
type: ‘spline’
},
series: [
{
name: ‘DS18B20 2’,
marker: {
symbol: ‘square’
}
},
{
name: ‘DS18B20 3’,
marker: {
symbol: ‘diamond’
}
},
{name: ‘DS18B20 1’,
marker: {
symbol: ‘triangle’
}
}
],
title: {
text: undefined
},
plotOptions: {
line: {
animation: false,
dataLabels: {
enabled: true
}
}
},
xAxis: {
type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: {
text: ‘Temperature (°C)’
}
},
credits: {
enabled: false
}
});
return chart;
In index.js I have added a function to plot multiple values.
/ function to plot multiple values on charts
function plotValuesMulti(chart, timestamp, value1, value2, value3){
var x = epochToJsDate(timestamp).getTime();
var y = Number (value1);
var y2 = Number (value2);
var y3 = Number (value3);
if(chart.series[0].data.length > 40) {
chart.series[0].addPoint([x, y], true, true, true);
chart.series[1].addPoint ([x, y2], true, true, true);
chart.series[2].addPoint ([x, y3], true, true, true);
} else {
chart.series[0].addPoint([x, y], true, false, true);
chart.series[1].addPoint ([x, y2], true, false, true);
chart.series[2].addPoint ([x, y3], true, false, true);
}
}
Call the function with
plotValuesMulti(chartT, timestamp, temperature, humidity, pressure);
Although the variables are called temperature, humidity and pressure, they are in fact all temperature readings as I haven’t got round to changing the actual database yet.
Thank you, you have shown me the way . . .
Thanks Mike for sharing, that’s exactly what I needed /was wanting to display too. (without having to do the homework : )
Can you show sample?
Hi Sara
Another great article, however there is no explanation of the code, I can see that would have made for a much longer article however.
I am also not able to get the charts to work, I see a problem with index.js line 72
var chartPath = ‘UsersData/’ + uid.toString() + ‘/charts/range’; as this isn’t my path, I changed it to …+’/readings’; but still no go. The error is
util.ts:556 Uncaught Error: limitToLast: First argument must be a positive integer.
Ie it is not getting a valid chartRange, probably coz it is not seeing any data.
What am I doing wrong?
I am really pleased to get the data into the cards and gauges, I have been trying for some time with no success until you published this article!
Regards
Bruce
Hi.
Insert a number in the “Number of readings” field, like 30 for example.
After that, the chart should load.
As I explained in the Wrapping Up section, the project is quite long. I’m able to write explanations about each section of the code in different tutorials if there is enough interest in these subjects.
Regards,
Sara
Hello Sara,
nice project, many thanks for your effort. I am not proficient at Java at all.
I am seeing an issue with large data points. When “Number of readings” is 50 or more, the entire things fails. Any idea why?
Werry nice, is it possible for you to ad the funktion to set alarms wen reading sensors?
Like, if a battery is charging and getting to hot.. a alarm goes off with sound and perhaps red flaching display?
Many thanks, best regards
/fredde
Hi.
You can add that feature, but I don’t have any tutorials about that.
Regards,
Sara
Nice write up. My first time with Firebase and it all worked as it should (almost)
When I have run the code, I dont get any gauges. I note that in you instructions you create a gauges.definition.js file. But in the code its referenced as scripts/gauges-definition.js NOTE the hyphen- vs the dot. This causes “createTemperatureGauge is not defined” exception. I fixed the mistake, but Im still unable to see the gauges. EDIT – a hard refresh after deploy fixed the issue (ctrl + shift + R)
Hi.
The file should be called gauges-definition.js. There was a typo in the tutorial. It is fixed now.
After changing javascript files always hard refresh your web browser.
Regards.
Sara
Buenas tardes
Desde España
Felicitaros, por vuestro inmenso trabajo.
Acabo de realizar este proyecto muy ilusionado, pero la parte de web no me funciona, no me muestra los datos en la app. Lo he realizado 4 veces siempre con el mismo resultado.
Me podeis ayudar
GRACIA
Jesús Cuesta
Hola.
Tu tienes que completar esto projeto en primero lugar: https://randomnerdtutorials.com/esp8266-data-logging-firebase-realtime-database/
Regards
Sara
Hola Sara
Este proyecto es lo primero que realice y funciona correctamente esta enviando los datos y generando la tabla de los mismos.
El problema es que cuando realice el 2º proyecto tal y como te he comentado, no me muestra ningún dato de los que estan almacenados.
No encuentro el problema, me puede ayudar?
Saludos cordiales
Hola.
Open your javascript console on your web browser and tell me if there are any errors.
Additionally, double-check that you’re saving all the required javascript files on the scripts folder.
Regards.
Sara
P.S. I can read and understand Spanish, but I can only write the basics.
341 / 5.000
Resultados de traducción
Hi Sara
There was an error on my part in the code that entered it wrong and now it shows me the temperature and the values in the table.
But I get 4 errors in the javascript console and it doesn’t show me the graphics, nor the widgets.
I am attaching the errors.
esp-cascosta-termico.web.app/:198
GET https://esp-cascosta-termico.web.app/scripts/gauges-definition.js net::ERR_ABORTED 404
esp-cascosta-termico.web.app/:198
GET https://esp-cascosta-termico.web.app/scripts/gauges-definition.js net::ERR_ABORTED 404
Reference_impl.ts:2020 Uncaught Error: limitToLast: First argument must be a positive integer.
at Reference_impl.ts:2020:11
at Cu.limitToLast (Reference.ts:400:59)
at index.js:95:28
at o (Reference.ts:253:16)
at za.onValue (EventRegistration.ts:56:27)
at Reference_impl.ts:850:30
at Be (util.ts:546:5)
at EventQueue.ts:160:7
at ha (EventQueue.ts:128:9)
at la (EventQueue.ts:108:3)
2
util.ts:556 Uncaught ReferenceError: createTemperatureGauge is not defined
at index.js:167:22
at o (Reference.ts:253:16)
at za.onValue (EventRegistration.ts:56:27)
at Reference_impl.ts:924:30
at Be (util.ts:546:5)
at EventQueue.ts:160:7
at ha (EventQueue.ts:128:9)
at la (EventQueue.ts:108:3)
at ga (Repo.ts:406:3)
at tn.a.server_ [as onDataUpdate_] (Repo.ts:256:9)
I await your news.
P.S. I’m glad you understand Spanish
Hola Sara
Ha habido un error por mi parte en el código que lo introducido mal y ahora me muestra la temperatura y los valores en la tabla.
Pero me salen 2 errores en la consola de javascript y no me muestra los gráficos, tampoco los widgets.
Te adjunto los errores.
Quedo a la espera de tus noticias.
PD. Me alegra que entiendas el español
Hi.
I’m following your issue via email now.
Regards,
Sara
Good project — a very complex one (6 different files to create and understand, in 4 different languages, and dealing with where everything goes). There are 2 parts to this immense project: creating the code, and knowing the procedures for getting that code where it needs to live (ESP32 and the cloud). The code part is understandable at a high level, assuming one has gone through other eBooks like the webservers one, and the firebase one. The procedure is strung out over many pages and I found it hard to create a similar but different project “from scratch” – i.e. not so much the code writing part, but the procedural part. I wrote up a 3 page procedure that I’d like to share (but can’t figure out how to get a pdf into a gist; maybe there’s another way)
Hi Joe.
I already answered your question in the forum.
To share a PDF, you can upload it to google drive and then share a link to the file, for example.
Regards,
Sara
Hi Sara
Many thanks, I got the charts going, my error.
I would for one be interested in more on the code for these examples and maybe more on different charting etc.
Thanks
Bruce
Great.
Thanks for your feedback.
Regards,
Sara
hai Sara
thanks for great tutorials….
why my ESP8266 can’t conect to firebase,
i was make correct setup with my credential :
// Insert Firebase project API Key
#define API_KEY “******”
// Insert Authorized Email and Corresponding Password
#define USER_EMAIL “”
#define USER_PASSWORD “”
// Insert RTDB URLefine the RTDB URL
#define DATABASE_URL “***”
but this is error from serial print after conected to wifi, like this :
06:56:40.573 -> Token info: type = id token, status = on request
06:56:47.799 -> Token info: type = id token, status = error
06:56:47.799 -> Token error: code: -1, message: connection refused
06:56:47.799 -> Getting User UID
06:56:47.799 -> ……………………………………….
Hi.
Did you follow the first part of the project exactly as described?
https://randomnerdtutorials.com/esp8266-data-logging-firebase-realtime-database/
Regards,
Sara
Here is a 3 page procedure I wrote up for starting a Firebase project from scratch (it doesn’t go into the code, but rather addresses only the many steps required to get a project to deploy and work). The link to the pdf in Google Docs is:
https://drive.google.com/file/d/1C0H5D2Bu6t0ycY-FhOwtGpKL4IFVFwW_/view?usp=sharing
I wrote a 3 page procedure for creating a Firebase project from scratch, and the pdf is found in the Google Docs link below. This procedure does not address code details, but rather just the ton of steps needed to properly deploy the project and have it work. Good luck 🙂
https://drive.google.com/file/d/1C0H5D2Bu6t0ycY-FhOwtGpKL4IFVFwW_/view?usp=sharing
sorry … wrong link: here’s the proper on –
https://drive.google.com/file/d/1exO6uwPi7OEUu2UVyr_WEqRzG2jQAP9l/view?usp=sharing
Hi.
Wow. Your document looks great. It contains a great summary of all the important steps to create a Firebase project with the ESP32 and ESP8266.
Thank you so much for sharing this.
I’m sure this will be helpful for many of our readers.
Regards,
Sra
Hi Joe, I can’t access the link. Can you resend the link?
Thank you
I too cannot access the file, “Sorry, the file you have requested does not exist.” Is the link dead? I’d love to see it
15-03-2022
Hello dear Mr Randomnerst,
I want to show you courtesy and decency and I am grateful that I have come to understand the Web App development around the esp8266 and esp32.
I’ve known you for quite some time, and ran into you again on the side of my mobile phone.
I will join the Randomnerst community from now on and next week I will buy a book and then take a course with you.
I am proud of you…
My thanks is great
Mr: A.Olieberg from the Netherlands
That’s great!
Thank you so much for your support.
Regards,
Sara
Hi Sara, I am able to upload my sensor readings to FireBase and get them displayed on the cards. But I couldnt get the Gauges update in realtime. Is there a way that I can share you the code and get it fixed?
Hi.
What is the error that you’re getting?
Open the JavaScript console and check if you’re getting any specific errors.
Regards,
Sara
Good morning
thank you for your new project.
This is a very cool project. I have done it too. thank you.
Solid tutorial. Works like a champ on a laptop but no joy on an Android device, all devices are quite new (S-21 phone). All I get is the top line banner “Sensor Readings App”. Tried refreshing, then reloading the page but again no joy. Tried resizing the screen as well. Might something be missing from the Android device? As I said works great from my laptop.
Hi.
I found the issue.
Basically, you need to make sure that index.js is fully loaded before auth.js.
So, auth.js will only run after everything has been loaded. I wrapped all auth.js content inside:
document.addEventListener(“DOMContentLoaded”, function(){
});
The auth.js file will be fixed in a few minutes.
Let me know if this fixes the issue.
Regards,
Sara
Hi Sara,
I have the same issue but the modification of auth.js does not work for me. Any ideas?
Regards,
Stephan
Hi.
Make sure you saved the file and deployed the app again.
Then, add refresh your web browser so that it starts using the newest js file.
Regards,
Sara
Thanks Sara! It was due to the browser cache… sorry.
Regards
Stephan
That was the fix. I re-deployed the modified auth.js and all is goodness and light. Thanks!
Good day.
My sensor readings doesn’t display the value from my realtime database.
Hi.
Open the web browser console and check if there are any errors.
Additionally, make sure you hard refresh your web browser for any changes to take effect.
Regards,
Sara
How to run it? It seems like i’ll be redirected to my project overview.
What do you mean?
To open the JavaScript console, Press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) .
Regards,
Sara
is there a function that gets the value from Firebase when it changed?
Hi.
Yes.
We’ll publish a tutorial about that soon.
Meanwhile, you can take a look at this example: https://github.com/mobizt/Firebase-ESP-Client/blob/main/examples/RTDB/DataChangesListener/Callback/Callback.ino
REgards,
Sara
Hi Sara,
I have integrated an BH1750 into Your project; if interested, I can send You the modified files all together.
Just one problem: I am living in a GMT+2h Zone, but the Website shows (correct) GMT time which ist transferred from the ESP 32. Can You give me a hint how to change the ESP Code to send the correct timestamp for my City (GMT +2h)
Regards, Stephan
Hi. Are you referring to the time on the charts?
To adjust the time, add the following when defining a chart:
var chart = new Highcharts.Chart({
time:{
useUTC: false
},
chart:{ (…)
Regards,
Sara
How would one have multiple device send data to the firebase database? There is a lot of information going the other way, database push to many devices, but none for this scenario.
Found the answer to this question in the Firebase Project Docs. They call this multi-tenancy and strongly discourage it as it can lead to serious configuration, privacy and authentication issues.
Hi.
Can you share the link to that documentation you just mentioned?
Regards,
Sara
Her you go:
https://firebase.google.com/docs/projects/learn-more#multi-tenancy
Thanks.
I don’t think that documentation means what you mentioned.
Basically, you can associate multiple apps with the same Firebase Project, but that’s discouraged (at least it was what I understood).
But, in this scenario, we always use the same app, and the same database for multiple ESP32 clients that would be publishing the same kind of data and would be controlled using the same app.
So, you can easily connect multiple ESP boards. Just make sure each board publishes to a different database node.
Regards,
Sara
I can’t access; can you authorize me ?
thanks.
Hi.
What do you mean?
Regards,
Sara
I can’t access to it:
https://drive.google.com/file/d/1exO6uwPi7OEUu2UVyr_WEqRzG2jQAP9l/view?usp=sharing
Gracias Sara por ese aporte tan maravilloso. Todo se encuentra perfectamente bien explicado y siguiendo los pasos pude hacer funcionar la aplicación.
Sólo dos detalles se me presentaron, uno con la zona horaria en el gráfico. El cual logré corregir según menciono en uno de mis comentarios realizados.
Por otro lado, un segundo detalle que tengo días tratando y no he podido resolver. Se trata que cuando se muestra la tabla de las lecturas, haciendo clic en el botón respectivo, el último valor se duplica cuando se hace una actualización de una nueva lectura.
Sabes algo de ese error y como se podría resolver ?
Hi.
Can you better explain the issue? I’m not sure I understood…
Regards,
Sara
Gracias por responder…
En el siguiente enlace puedes ver un video del error que se presenta en la carga de datos desde Firebase. Ocurre cuando se muestra y se oculta la tabla con los registros de las lecturas.
https://youtu.be/xm_GJfEerqc
Eureka !!! … Problema resuelto !!!
var tableChildAddedListener = null;
// Function that creates the table with the first 100 readings
function createTable() {
// append all data to the table
var firstRun = true;
$('#tbody').empty();
if (tableChildAddedListener != null) {
dbRef.off('child_added', tableChildAddedListener);
}
tableChildAddedListener = dbRef.orderByKey().limitToLast(10).on('child_added', (snapshot) =>
…
Cada vez que se presiona el botón de “View all data” se agrega con el “.on” nuevamente el Listener al evento “child_added”. Eso hace que se repita el registro nuevo. Por lo tanto, lo que hago es eliminar con el “.off” el Listener antes de agregarlo.
Me ayudó mucho el siguiente enlace:
https://stackoverflow.com/questions/51902759/remove-off-for-firebase-listeners
Hi Sara,
I’ve just completed installing the Sensor Readings App, you guys and gal’s did a great job putting it together.
I had the advantage of having completed the project in the Firebase Web App book some time ago which gave me an understanding of Firebase.
Ever since completing the Web App I took an interest in html and css and I would love to get an understanding of how the js files work in the sensor app and hopefully enough people are showing an interest to make it worthwhile putting out a “how it works tutorial” on the subject using this project.
Thanks again for your excellent work that gives me so much enjoyment.
That’s great!
I’m glad you enjoyed the tutorial and the eBook.
Thank you so much for your feedback.
Regards,
Sara
Hi Sarah, no doubt it was a great project, which required you to do lots of hard work. appreciated!
I need one help, can you please tell me how to increase the speed of data uploading?
I need 2 data points on chart in one second.
Thanks
Hi Sara,
I’ve just got back to this great app after some time and noticed that my chart time is showing actual GMT. I live in a GMT+12 zone it was probably like this when I originally got it going and I didn’t notice but who knows I played around with it after I originally installed it.
I see your reply from 22nd April to a similar issue as follows:
var chart = new Highcharts.Chart({
time:{
useUTC: false
},
chart:{ (…)
Would I replace the above with useGMT:false ?
Regards
Mike
Hi.
No.
Use
time:{
useUTC: false
},
It will show your local time.
Regards,
Sara
Thanks Sara, works no bother, silly me.
Regards
Mike
Hi Sara
Thanks for another great tutorial
Could you maybe look into how to integrate this with Google assistant so that it all can be voice controlled Would be great if I can voice request some room temperature and then switch on heater or aircon based on the answer
Thanks
Sarah,
Thanks for your meticulous work, this is fabulous. Modified to track on/off times of my water heater. I am a huge fan of randomnerd.
Thank you so much!
Any hint on how to change the temperature gauge from Celsius to Fahrenheit?
I did change the scale bar values, but display still displaying as Celsius.
Hi.
Are you logging your temperature in F or C?
If you want to display the temperature in F, it is better to save the temperature in F on the database.
Convert the temperature in the Arduino code.
Regards,
Sara
Hi Sara,
I have the all the temperature converted to F and saved to Firebase. Webpage displays all temperature in F. My problem is that the temperature gauge. I am trying to display the value corresponding to the scale gauge, but i am a little off. Do you know that variable need to change, so the gauge will display properly?
r/
-leon
Hi.
In the gauges-definition.js file, check the settings of the temperature gauge.
You’ll need to change the minValue and maxValue to redefine the gauge range.
I hope this helps.
regards,
Sara
Thanks it worked. Changes on gauges-definition.js were:
minValue: 32
maxValue: 100
majorTicks: [“32″,”40″,”50″,”60″,”70″,”80″,”90″,”100”, ]
and highlights: [ “from”: 85, “to”: 100, …
Great!
This is absolutely great work. Thanks a lot for sharing – I now understand a lot better about how everything is connected and should be advancing my projects way faster now.
Cheers!
That’s great!
Thanks for following our work.
Regards,
Sara
This worked without any problems. Definitely an opus major from you. It also helped me to expand my view on Firebase. Definitely a lot more versatile than I initially thought.
I made slight additions to your work: Added a checkbox to show/hide the password. Added Fahrenheit and mmHg to the Celsius and hPa scales (calculated in JS, did not want to mess with your JSON yet) added a tad more color to the gauges, added a pressure gauge, all small stuff actually coz your design is pretty near perfect. I may try another gauge library as i am looking for a slightly different appearance, but again. that is just dabbling in the margin. Anyway, great work, saves me a lot of time. If I had done it all myself, it would have taken me much longer and I would probably have chosen a slightly different way to persist the data for the graphs, but the way you do it is in fact more flexible and as said, expanded my view on Firebase.
That’s great!
Thanks. I’m really glad you found this tutorial helpful and that you learned a lot from it. That’s our goal with all our tutorials.
Regards,
Sara
Though initially I experienced no problems with this project, last 2 days, I do have a problem. I do not expect you to have the answer, but I am sharing it here, wondering if other users had this as well.
Suddenly the page with the web-app has become incredibly slow. It loads the sensor values correctly, it loads the gauges, but then does take a loooong time to set the needles right and if I click the ‘charts’ tick-box, the page basically freezes. Happens on various browsers, on tablest, PC and phone and even on another network, and then occasionally, it works like it should again
As i made some additions to the app, this morning i started from scratch again, new app, using your exact files….same problem.
in another firebase webapp that does not load gauges or charts, I have no problems at all.
If the problem was only in loading the charts, I’d suspect the highcharts link maybe being overburdened, but the delay seems to start with the sensor values needing to be put in the gauges. Odd, very odd.
Initially I got the impression that maybe it had to do with the number of datetime records stored, but that doesn’t seem to be it.
I will look into it a bit further, but was wondering if other people experienced similar issues.
Still a great project though
Interesting, the problem seems to be the highcharts link. If I temporarily comment that out, everything works again, no unresponsive app, and clicking the charts tickbox gives immediate response in loading the placeholders (not the graphs itself ofcourse).
What exactly is causing this is a bit of a mystery still. Might still be a Firebase hick-up as I can also see that regularly it cannot find my favicon.
OK, well, more sleuth work to do this weekend. When they said computers would give us more free time, it was a lie 🙂
OK, think, I found it: It is definitely Highcharts and probably it can’t handle many datapoints. When I delete all points it immediately seems to work properly again. I gather points every 10 minutes, so after a day that should be 168 datapoints. That is not humungus and one would expect that the problem only arises once one wants to draw the graphics itself, but apparently something happens before that already. I will have to go to the code a bit deeper (as if i haven’t yet :-)) to see if there is anyway to solve it such that at least the delay only happens once you actually wants to show the graphs, not during loading of the of the app itself. Oh well….a challenge
Hi.
Thanks for investigating that issue.
Then, let us know if you find something.
Regards,
Sara
Yes, i think I did find it and it is kinda dumb. The amount of points to be shown in the graphs is stored in the RTDB (in the range or readings field I think it was). What i think happened is that at one time or another i entered a ‘big’ number (say 200), so that was stored. When i later reloaded the page that number caused the loading problems, but because on reload the webapp doesnt show that number, nor the graphs, the few times i did manage to reload, I did not notice that high number and immediately got stuck again when ticking the ‘charts’ tickbox. Only when i finally took a look at the RTDB did I think, perhaps that number should be a bit lower.
No problems since.
One could consider putting a limit on the inputbox, but that is a limitation. And the charts will load say 150 points without too much complaining…..but if you then reload the webpage that’s when the problems start.
Well, i just see it as having learned again.
Hi again.
Yes, I think it’s probably because of that.
You need to add a small number.
I think it worked fine whenever I tested with 50 data points.
Regards,
Sara
Hi Ed, Sara, All,
Seems I have the same issue. my web app page works fine when I create new fresh one. When I get readings of day or two worth, the web app page loads up for ever, doesn’t even let me to choose the charts. This is with clearing cache, brows data, etc
I suspect it has something with amount of reading/ logs. Could you please guide me how to fix the issue.
Very nice project, I learned a lot, but it works responsive only for a day or two.
I am dealing with Firebase IT crowd atm, in case its something slows the web app on their side.
May Thanks
Stef
Hi.
I think it has to do with the way we load the data on the JavaScript side.
It goes through a loop through all the data to display it on the web page.
Probably there are other methods to do display the data via JavaScript, but at the moment I don’t think I know how to fix the issue.
A quick “fix” is to increase the delay time between readings and delete the data periodically, but that’s not ideal.
Regards,
Sara
Hi Sara.
Thanks for the code.
Just wanted to know if I can connect more than one esp32/esp8266 to the same database. For example, temperature and vibration readings using separate esp32/esp8266, sending the sensor readings to firebase database.
Hi.
Yes, you can have multiple board interacting with the same database.
Just make sure you use a different path for each board so that the readings don’t overwrite each other.
Regards,
Sara
Hi. I have a ml model to detect changes in temperature, humidity and pressure. Is it possible to integrate this beautiful web app and firebase RTDB with an ml model to detect changes. If it’s possible how can its be done.
Thank you.
I set my NTP to GMT+7 (Bangkok, Hanoi, Jakarta), but the time display on the chart still shows GMT 0, how do i change it?
I have changed the :
var x = (epochToJsDate(timestamp).getTime() + 25200);
but still unchanged
Hi.
Please check the comment by Guillermo Rivas.
The answer is there.
Or add:
useUTC: false
in the chart properties. Check it here: https://api.highcharts.com/highcharts/time.useUTC
Here’s an example in this discussion: https://www.highcharts.com/forum/viewtopic.php?t=46034
Regards,
Sara
Not sure if I have words enough to credit all these excellent tutorials and code samples that I’ve gone through on this website. And everything is so well described and code samples actually just works!
I’m so thankful! You guys have save me hundred of hours. I will buy some of your E-books or just donate something to at least give something back.
P.s.
Got this little awesome beauty the other day, “FireBeetle Esp32-E”. Have you ever tested that one? It’s supposed to be supercheap on amps in deep sleep.
Yet again,
Thank you!
/Anders
Hi Anders.
Thanks for your nice words.
I haven’t tested that board.
Usually, all boards advertise super low power consumption in deep sleep. But the reality usually is very different. But I haven’t experimented with that board.
Then let me know your findings.
Regards,
Sara
I have used the Firebeetle ESP32 – E for ESPNOW projects and it does have very low power consumption in sleep mode. There is a track to cut to enable very low power mode.
A bit disappointed on Firebase itself. If you track like 500 records it just hangs. So what’s the point? Excellent sample code here to make it work, but is it really usable in RL?
It’s just a (very slow) mongodb more or less.
Is it possible to export the data into csv format? which part of the program do i need to add? where can I learn this?
The sensor readings go to the database but they dont display on the web app. May I know where the problem would be?
Hi.
On your web app, open the Javascript console and check if there are any errors that might point out where the issue is.
Regards,
Sara
Hi, may i know how to change from test mode to locked mode and how to write firebase rules for locked mode ?
Hola Sara, excelente proyecto, me parece bárbaro la integración del desarrollo web con el mundo iot, quiero hacer una pregunta, hay posibilidad de hacerlo más automático al proyecto. Osea desde la app crear un user y password y que el esp32 tome esos datos y recién ahí empezar a enviar la data, osea, que el user y pass no sea hardcodeado por nosotros sino por medio de la app. Y la otra siguiendo con firebase, con que frecuencia es recomendable el envío y actualización de los datos en la database realtime para que Google no empieze a cobrar por el uso. Ya que en la parte 1 hablas de aumentar el tiempo de escritura, creo que es por eso. Pero de cuánto sería ese tiempo para un proyecto online 24 hours. Gracias de antemano por responder y ojalá puedas ahondar más en este proyecto ya que es súper escalable.
Hello Rui and Sara.
This is probably one of the best internet pages on electronics projects that I have been able to see in the entire internet, I congratulate you for your excellent work.
I already did all the steps and configurations and everything is working in an extraordinary way, your tutorials were a perfect guide to set up my project. However, there is only one thing that did not go well. On the main page the time of the readings appear fine, with my local time, even in the tables they also displayed with my local time, however in the graphs the hours appear with GMT time, which with my country, Colombia, gives a difference of + 5 hours. How could I fix that little detail?
Thanks in advance for your help.
Hi.
Thanks for your feedback.
You can add:
useUTC: false
in the chart properties. Check it here: https://api.highcharts.com/highcharts/time.useUTC
Here’s an example in this discussion: https://www.highcharts.com/forum/viewtopic.php?t=46034
I hope this helps.
Regards,
Sara
Nice project!
One minor issue is that each time we have an update of data, the values of the gauges (arrows of gauges) go first to 0 and after to the updated value. For example if the temperature was 23 and the new reading (update) is 25, the arrow goes from 23 to 0 and then goes to 25, instead of going from 23 to 25 immediately. Could we do something about that?
Also, although the “Last update: 2023/05/14 11:38:33” shows the right time, instead the time in the charts is 2 hours behind (it shows: 09:38:33) I tried to change the js file and the parameters of ntp server, but still having this issue. Any solution?
Thank you in advance.
Hi.
To solve the issue with the gauges you need to set the useUTC property to false.
See an example here: https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/time/useutc-false/
Regards,
Sara
nice project,
what if I want to add a function so that I can calculate the average, max, min value every day ?
Saludos, excelente proyecto y muy educativo. Tengo dos consultas:
Si he realizado ya un proyecto con Arduino UNO, al querer implementar el ESP32, para realizar las mismas funciones que con el Arduino UNO, lectura de sensores y demás. Podrían trabajar juntos, o tendría que utilizar uno y dejar el otro de lado.
Estos valores que aparecen en las tablas, ¿también pueden ser visualizados dentro de Firebase (todos)?.
Hi.
You can use both boards, but it will be easier to just use the ESP32.
Otherwise, you’ll need to implement a communication between both boards.
You can access all readings on the Firebase console, on the database tab.
Regards,
Sara
i do all the steps exactly same as you shown but still i can only see just the heading. no login form or any other data.
here are the error showing me on console:
(index):34 Uncaught ReferenceError: firebase is not defined
at (index):34:1
(anonymous) @ (index):34
auth.js:3 Uncaught ReferenceError: auth is not defined
at HTMLDocument. (auth.js:3:5)
Try to hard refresh your web browser.
Additionally, make sure all files are located on the correct folder.
Regards,
Sara
I did the hard refresh and double check the folders, but still showing same error
THANK YOU for such a great website/tutorials.
I have the web page working but now am trying to understand where I need to modify to apply to my use case.
My temperatures need to show in Fahrenheit ?
I want to use a different ESP8266 sensor and thus change all references to HUMIDITY to pH. I have the data in the firebase database but am trying to figure out how to make the changes.
I also would like to add additional data points.
Hi.
If you would like to show temperature in Fahrenheit, you can do it on the Arduino sketch before sending the data to the database or on the Javascript.
In my opnion, it’s better to do that in the Arduino IDE so that all your database shows temperatures in Fahrenheit.
If you’re using a BME280 like us, you just need to do the conversion:
tempF = temperature *9/5 + 32;
Regards
Sara
Saludos,
He realizado todos los pasos, pero no me muestran los valores en la Web, pero en Firebase. Haciéndo la primera parte, sin graficos ni cartas, todo correcto. Pero al implementarle los graficos y demas, ya no me manda los valores. ¿Que podría ser?, tal vez haya algún correo donde pueda comunicarme.
This was an awesome tutorial Sara, very well explained and the html/js code is very detailed. Reasonably quickly, I was able to adapt this and include a page navigation footer (as used on many apps) that help navigate the different screens.
The Highcharts graph lag is where I am at at the moment. If we are to use this foundation as Blynk alternative, which I think it very well good be, we need to find a solution to reduce the time it takes to display many data points.
Thank you
Andrew
Hello,
thanks a lot for this very nice tutorial. I was able to reproduce your example and make it to work, then I tried to adapt it to my project.
Now I have the bad feeling that Firebase is really full of bugs, might be it is my mistake:
– Especially if you put too much delay during firebase RTDB writes (like 1 minute), it stop working after a while, with a timeout error message, obviously the link to Firebase is closed
– if you try to execute firebaseInit() without a proper Web connection, your ESP32 is stuck forever with ‘token…’ error messages.
– when you deploy your web app (through VS code), it might take a very long time to have the app updated on the web browser. Worse, I got strange behavior like ‘index.html’ was up to date but ‘index.js’ was several releases late….. weird, I had to place a version number, visible in a displayed field, in each file, to understand which versions I was using.
At some point, I had 3 browsers (Chrome, Firefox & Edge) looking at the app web page and they could display 3 different versions (a refresh doesn’t fix that, sometimes closing and opening the browser forces an update)
– overall, I do not understand how you can efficiently debug all this firebase development, for me, it has been very painful.
– I do not understand how you can rely on such a system for an important application.
Thanks anyway for your excellent work,
Jef
Hi.
To make sure your web browser is displaying the latest app version, you need to hard refresh your web browser for it to display the latest version.
Learn more here: contractsafe.com/support/how-to-clear-your-browser-cache-and-hard-refresh
Regards,
Sara
Additional point:
I am using the “Firebase Arduino Client For Arduino Devices” by Mobizt at rev 4.4.8 (latest)
The readme suggest to rather use AsyncFirebaseClient ?
I might give it a try
Hi.
Then, let me know if that new version works well.
Regards,
Sara
Dear sara, i have followed all the way this project step by step and i can see the esp32 logging info on my real time database console. but my web app isnt showing me any data on the page. on temperature humidity and pressure everything is blank. even the last update: as well.
i dont know what i did wrong and what can i do to fix it.
Hi.
When you open your web app on the browser, open the javascript console and check if you have any error that might help you figure out what is wrong.
Regards,
Sara
Hello, I have a similar problem. The readings in the realtime database are good but in the web app all the values appear has “undefined” except for the timestamp, that is the only value that is showing. I checked the javascript console and there is no error. I need your help please.
Hi.
Did you change anything on the code?
Regards,
Sara
Yes, I changed the humidity variable for heartbeat. I will rechecked the index.js.
Hi sir,
Great tutorial. Can I use multiple esp32/esp8266 devices to log data to this web app at the same time, and if yes what I need to do for that? How many number of readings (or how many days reading) history are stored in this setup?
Please reply.
Hi.
Yes.
You can use multiple boards, you just need to upload the same code to all boards.
However, if you want to identify each board, it’s better to publish each board on a specific path.
Regards,
Sara
How do I can identify which board is which? How can I publish each board on specific path? Sorry I couldn’t understand, I am a newbie to programming, I am more a hardware guy. Please help.
Hi.
You need to go back to this tutorial to understand: https://randomnerdtutorials.com/esp32-data-logging-firebase-realtime-database/
Check the path that the board is publishing the data:https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2021/12/Firebase-BME280-datalogging-database.png
You would have to adjust the path for each board. Something like:
Board1: UsersData/>user_uid>/board1/temperature
For board 2:
Board1: UsersData/>user_uid>/board2/temperature
And so on…
I hope this helps.
Regards,
Sara
Hello, I am based on your code to make mine. Could you help me with some questions? It’s for my electronic engineering thesis.
Yes, if I can help.
Regards,
Sara
Is there a way for several ESP32’s to connect to this one app and display readings on separate tabs? For example: a multi-zone heating/cooling in a home where the home would be the main page and each zone would be displayed/controlled from a separate tab.
Hello Sara,
A very nice project you got here though I followed every step but I keep seeing this problem on my web application that tells me to “update the version number as needed”. Where did I could I have possible gone wrong cause i can’t see any values I got from the realtime database on the web application.
Well it is okay, as I figured out what my problem was.
Hi, the esp32 is uploading the json objects to the realtime database. The html webpage is loading, however, there is no data being displayed.
Hard refreshes have been done, with no errors in the console.
No code has been changed.
Using a windows machine.
Any ideas?
Thanks