Contrôlez les GPIO ESP32/ESP8266 depuis n’importe où (Firebase Web App)

Contrôlez les GPIO ESP32/ESP8266 depuis n'importe où (Firebase Web App)

Dans ce guide, vous allez créer une application Web Firebase pour contrôler les GPIO ESP32 ou ESP8266 de n’importe où. L’accès à l’application Web est protégé par une authentification par e-mail et mot de passe. Les états GPIO sont enregistrés dans la base de données en temps réel Firebase. L’application Web écrit dans la base de données pour modifier les états GPIO et les cartes ESP écoutent les modifications de la base de données pour mettre à jour les états GPIO en conséquence.

Contrôlez les GPIO ESP32 ou ESP8266 NodeMCU depuis Anywhere Firebase Web App

Cet article est la partie 2 d’un tutoriel précédent. Vous devez suivre l’un des didacticiels suivants avant de continuer :

Aperçu du projet

Dans ce didacticiel (Partie 2), vous allez créer une application Web pour contrôler les GPIO ESP32 ou ESP8266 de n’importe où. Dans un didacticiel précédent, vous avez appris à configurer l’ESP32 ou l’ESP8266 pour écouter les modifications de la base de données et mettre à jour ses GPIO en conséquence. Vous avez modifié manuellement les états GPIO sur la base de données en temps réel à l’aide de la console Firebase. Vous allez maintenant créer votre propre application Web, hébergée sur Firebase, pour contrôler vos tableaux où que vous soyez.

Le diagramme suivant montre un aperçu de haut niveau du projet que nous allons construire. La programmation de l’ESP32/ESP8266 et la configuration du projet Firebase ont été effectuées dans la partie 1 :

Firebase Web App contrôle ESP32 ESP8266 Sorties de n'importe où
  • Firebase héberge votre application Web sur un CDN mondial à l’aide de Firebase Hosting et fournit un certificat SSL. Vous pouvez accéder à votre application Web de n’importe où en utilisant le nom de domaine généré par Firebase.
  • Lorsque vous accédez pour la première fois à l’application Web, vous devez vous authentifier avec une adresse e-mail et un mot de passe autorisés. Vous avez déjà configuré cet utilisateur et la méthode d’authentification dans la partie 1.
  • Après l’authentification, vous pouvez accéder à une page d’application Web qui affiche plusieurs boutons pour modifier les états GPIO sur la base de données.
  • L’ESP32 ou l’ESP8266 écoute les modifications de la base de données. Lorsque vous cliquez sur les boutons, les états GPIO changent sur la base de données et l’ESP met à jour les états en conséquence.
  • L’application Web indique également l’état actuel des GPIO.
  • À titre d’exemple, nous contrôlerons trois GPIO (12, 13 et 14). Comme mentionné dans le tutoriel précédent, vous pouvez ajouter/supprimer plus de GPIO et de cartes ou contrôler d’autres GPIO.
  • Une fois connecté, vous pouvez vous déconnecter à tout moment. La prochaine fois que vous accéderez à l’application, vous devrez vous reconnecter.

La capture d’écran suivante montre à quoi ressemble la page Web sur un navigateur Web d’ordinateur.

Contrôlez les GPIO ESP depuis Anywhere Web App

Conditions préalables

Avant de commencer à créer l’application Web Firebase, vous devez vérifier les prérequis suivants.

Créer un projet Firebase

Vous devriez d’abord avoir suivi celui des tutoriels suivants :

L’ESP32/ESP8266 doit exécuter le code fourni dans ce tutoriel. La base de données en temps réel et l’authentification doivent également être configurées comme indiqué dans le didacticiel.

Installer le logiciel requis

Avant de commencer, vous devez installer le logiciel requis pour créer l’application Web Firebase. Voici une liste des logiciels que vous devez installer (cliquez sur les liens pour obtenir des instructions) :


1) Ajoutez une application à votre projet Firebase

1) Accédez à la console de votre projet Firebase et ajoutez une application à votre projet en cliquant sur le bouton + Ajouter une application.

Firebase Ajouter une application au projet

2) Sélectionnez l’icône de l’application Web.

Firebase Ajouter une application Web au projet

3) Donnez un nom à votre application. Ensuite, cochez la case à côté de √ Configurer également l’hébergement Firebase pour cette application. Cliquez sur Enregistrer l’application.

Firebase Ajouter une application Web à l'hébergement de projet

4) Ensuite, copiez l’objet firebaseConfig et enregistrez-le car vous en aurez besoin plus tard.

sauvegarde de la copie de la configuration de l'objet firebaseConfig

Après cela, vous pouvez également accéder à l’objet firebaseConfig si vous accédez aux paramètres de votre projet dans votre console Firebase.

5) Cliquez sur Suivant dans les étapes suivantes, et enfin sur Continuer vers la console.


2) Configuration d’un projet d’application Web Firebase (code VS)

Suivez les étapes suivantes pour créer un projet d’application Web Firebase à l’aide de VS Code.

1) Création d’un dossier de projet

1) Créez un dossier sur votre ordinateur dans lequel vous souhaitez enregistrer votre projet Firebase, par exemple, Firebase-Project sur le bureau.

2) Ouvrez le code VS. Allez dans Fichier > Ouvrir le dossier… et sélectionnez le dossier que vous venez de créer.

3) Allez dans Terminal > Nouveau terminal. Une nouvelle fenêtre Terminal devrait s’ouvrir sur le chemin de votre projet.

Installer les outils Firebase 2

2) Connexion Firebase

4) Dans la fenêtre Terminal précédente, tapez ce qui suit :

firebase login

5) Il vous sera demandé de collecter des informations sur l’utilisation de la CLI et les rapports d’erreurs. Entrez « n » et appuyez sur Entrée pour refuser.

Connexion Firebase VS Code Terminal Fenêtre

Remarque : Si vous êtes déjà connecté, un message indiquant : « Déjà connecté en tant que [email protected]”.

6) Après cela, une nouvelle fenêtre apparaîtra sur votre navigateur pour vous connecter à votre compte Firebase.

Se connecter au compte Firebase

7) Autorisez Firebase CLI à accéder à votre compte Google.

Connexion au compte Firebase autoriser Firebase CLI

8) Après cela, la connexion Firebase CLI devrait réussir. Vous pouvez fermer la fenêtre du navigateur.

Connexion au compte Firebase autoriser la connexion CLI Firebase réussie

3) Initialisation du projet Web App Firebase

9) Après vous être connecté avec succès, exécutez la commande suivante pour démarrer un répertoire de projet Firebase dans le dossier actuel.

firebase init

10) Il vous sera demandé si vous souhaitez initialiser un projet Firebase dans le répertoire actuel. Entrez Y et appuyez sur Entrée.

Connexion au compte Firebase autoriser Firebase CLI firebase init

11) Ensuite, utilisez les flèches haut et bas et la touche Espace pour sélectionner les options. Sélectionnez les options suivantes :

  • Base de données en temps réel : configurez le fichier de règles de sécurité pour la base de données en temps réel et (éventuellement) provisionnez l’instance par défaut.
  • Hébergement : configurez les fichiers pour l’hébergement Firebase et (éventuellement) configurez les déploiements d’action GitHub

Les options sélectionnées s’afficheront avec un astérisque vert. Ensuite, appuyez sur Entrée.

Connectez-vous au compte Firebase pour autoriser le répertoire de configuration de la CLI Firebase

12) Sélectionnez l’option « Utiliser un projet existant » – il doit être surligné en bleu – puis appuyez sur Entrée.

Configuration du projet Firebase VS Code

13) Après cela, sélectionnez le projet Firebase pour ce répertoire – il devrait s’agir du projet créé dans la partie 1. Dans mon cas, il s’appelle esp-firebase-demo. Appuyez ensuite sur Entrée.

Firebase Project VS Code créer un projet

14) Appuyez sur Entrée à la question suivante pour sélectionner le fichier de règles de sécurité de la base de données par défaut : « Quel fichier doit être utilisé pour les règles de sécurité de la base de données en temps réel ? »

15) Ensuite, sélectionnez les options d’hébergement comme indiqué ci-dessous :

  • Que voulez-vous utiliser comme répertoire public ? Appuyez sur Entrée pour sélectionner public.
  • Configurer en tant qu’application d’une seule page (réécrire les URL dans /index.html) ? Non
  • Configurer des builds et des déploiements automatiques avec GitHub ? Non
Initialisation Firebase terminée

16) Le projet Firebase devrait maintenant être initialisé avec succès. Notez que le code VS a créé des fichiers essentiels dans votre dossier de projet.

Fichiers de projet Firebase créés avec succès

Le fichier index.html contient du texte HTML pour créer une page Web. Pour l’instant, laissez le texte HTML par défaut. L’idée est de le remplacer par votre propre texte HTML pour créer une page Web personnalisée selon vos besoins. Nous le ferons plus tard dans ce tutoriel.

17) Pour vérifier si tout s’est passé comme prévu, exécutez la commande suivante dans la fenêtre VS Code Terminal.

firebase deploy
Premier test de déploiement de l'application Firebase

Vous devriez obtenir un déploiement complet ! message et une URL vers la console de projet et l’URL d’hébergement.

18) Copiez l’URL d’hébergement et collez-la dans une fenêtre de navigateur Web. Vous devriez voir la page Web suivante. Vous pouvez accéder à cette page Web de n’importe où dans le monde.

Configuration de l'hébergement de la page de test Firebase terminée

La page Web que vous avez vue précédemment est construite avec le fichier HTML placé dans le dossier public de votre projet Firebase. En modifiant le contenu de ce fichier, vous pouvez créer votre propre application Web. C’est ce que nous allons faire dans la section suivante.


3) Créer une application Web Firebase

Maintenant que vous avez créé une application de projet Firebase avec succès sur VS Code, suivez les étapes suivantes pour personnaliser l’application afin d’afficher les lectures des capteurs sur une page Web protégée par connexion.

index.html

Copiez ce qui suit dans votre fichier index.html. Ce fichier HTML crée une page Web simple avec des boutons ON et OFF pour contrôler les GPIO 12, 13 et 14.

Si vous n’êtes pas authentifié, il affiche un formulaire de connexion. Lorsque vous vous authentifiez avec un e-mail d’utilisateur autorisé et un mot de passe correspondant, il affiche l’interface utilisateur avec les boutons.

<!DOCTYPE html>
<!-- Complete Project Details at: https://Raspberryme.com/ -->
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ESP IoT Firebase App</title>

    <!-- update the version number as needed -->
    <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 web app's Firebase configuration
      const firebaseConfig = {
        apiKey: "",
        authDomain: "",
        databaseURL: "",
        projectId: "",
        storageBucket: "",
        messagingSenderId: "",
        appId: ""
      };

      // Initialize firebase
      firebase.initializeApp(firebaseConfig);

      // Make auth and database references
      const auth = firebase.auth();
      const db = firebase.database();

    </script>
    <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="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/favicon.png">
    <link rel="stylesheet" type="text/css" href="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/style.css">
</head>

<body>
  <!--TOP BAR-->
  <div class="topnav">
    <h1>ESP GPIO Control <i class="fas fa-lightbulb"></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="https://www.raspberryme.com/" 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="card-grid">
      <!--CARD FOR GPIO 12-->
      <div class="card">
        <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 12</p>
        <p>
          <button class="button-on" id="btn1On">ON</button>
          <button class="button-off" id="btn1Off">OFF</button>
        </p>
        <p class="state">State:<span id="state1"></span></p>
      </div>

      <!--CARD FOR GPIO 13-->
      <div class="card">
        <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 13</p>
        <p>
          <button class="button-on" id="btn2On">ON</button>
          <button class="button-off" id="btn2Off">OFF</button>
        </p>
        <p class="state">State:<span id="state2"></span></p>
      </div>

      <!--CARD FOR GPIO 14-->
      <div class="card">
        <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 14</p>
        <p>
          <button class="button-on" id="btn3On">ON</button>
          <button class="button-off" id="btn3Off">OFF</button>
        </p>
        <p class="state">State:<span id="state3"></span></p>
      </div>
    </div>
  </div>
    <script src="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/scripts/auth.js"></script>
    <script src="scripts/index.js"></script>
  </body>
</html>

Afficher le code brut

Vous devez modifier le code avec votre propre objet firebaseConfig, celui que vous avez dans cette étape.

Comment ça fonctionne

Examinons rapidement le fichier HTML ou passons à la section suivante.

Dans le du fichier HTML, nous devons ajouter toutes les métadonnées requises.

Le titre de la page Web est ESP Firebase App, mais vous pouvez le modifier dans la ligne suivante.

<title>ESP Firebase App</title>

Vous devez ajouter la ligne suivante pour pouvoir utiliser Firebase avec votre application.

<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>

Vous devez également ajouter tous les produits Firebase que vous souhaitez utiliser. Dans cet exemple, nous utilisons la base de données en temps réel et l’authentification.

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

Ensuite, remplacez l’objet firebaseConfig par celui que vous avez obtenu de cette étape.

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"
};

Enfin, Firebase est initialisé et nous créons deux variables globales db et auth qui font référence à l’authentification Firebase et à la base de données en temps réel Firebase.

// Initialize firebase
firebase.initializeApp(firebaseConfig);
      
// Make auth and database references
const auth = firebase.auth();
const db = firebase.database();

La ligne suivante nous permet d’utiliser icônes géniales:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

La suivante comprend une favicon sur notre page Internet.

<link rel="icon" type="image/png" href="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/favicon.png">

Enfin, référencez un fichier style.css externe pour formater la page HTML.

<link rel="stylesheet" type="text/css" href="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/style.css">

Nous en avons fini avec les métadonnées. Passons maintenant aux parties HTML qui sont visibles par l’utilisateur — allez entre les balises et .

Nous créons une barre de « navigation » supérieure avec le nom de notre application et une petite icône de fontawesome.

<!--TOP BAR-->
<div class="topnav">
  <h1>ESP GPIO Control <i class="fas fa-lightbulb"></i></h1>
</div>

Les lignes suivantes créent une barre avec les détails de l’utilisateur authentifié (email). Il affiche également un lien de déconnexion pour déconnecter l’utilisateur.

<div id="authentication-bar" style="display: none;">
  <p><span id="authentication-status">User logged in</span>
     <span id="user-details">USEREMAIL</span>
     <a href="https://www.raspberryme.com/" id="logout-link">(logout)</a>
  </p>
</div>

Tout d’abord, nous définissons le style d’affichage de tous les éléments sur aucun. Nous masquerons et afficherons le contenu selon que l’utilisateur est authentifié ou non. Nous nous occuperons de cela à l’aide de JavaScript.

Ensuite, les lignes suivantes créent le formulaire de connexion avec un champ de saisie pour l’e-mail et un champ de saisie pour le mot de passe :

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

À l’intérieur du formulaire, il y a aussi un paragraphe pour afficher un message d’erreur si la connexion échoue.

<p id="error-message" style="color:red;"></p>

Enfin, nous créons une grille pour afficher différentes cartes pour les GPIO.

<div class="content-sign-in" id="content-sign-in" style="display: none;">
  <div class="card-grid">

Par exemple, les lignes suivantes créent une carte pour GPIO 12 :

<!--CARD FOR GPIO 12-->
<div class="card">
  <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 12</p>
  <p>
    <button class="button-on" id="btn1On">ON</button>
    <button class="button-off" id="btn1Off">OFF</button>
  </p>
  <p class="state">State:<span id="state1"></span></p>
</div>

Les boutons ont des identifiants spécifiques afin que nous puissions nous y référer ultérieurement dans les fichiers Javascript. Il existe également une balise span avec un identifiant spécifique pour insérer l’état GPIO.

La création des cartes pour les autres GPIO est similaire :

<!--CARD FOR GPIO 13-->
<div class="card">
  <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 13</p>
  <p>
    <button class="button-on" id="btn2On">ON</button>
    <button class="button-off" id="btn2Off">OFF</button>
  </p>
  <p class="state">State:<span id="state2"></span></p>
</div>

<!--CARD FOR GPIO 14-->
<div class="card">
  <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 14</p>
  <p>
    <button class="button-on" id="btn3On">ON</button>
    <button class="button-off" id="btn3Off">OFF</button>
  </p>
  <p class="state">State:<span id="state3"></span></p>
</div>

Il est important de garder à l’esprit les identifiants de chacun de ces éléments, afin qu’il soit plus facile de les identifier sur le fichier JavaScript. Vous pouvez utiliser tout autre identifiant pertinent pour votre projet.

GPIO 12 GPIO 13 GPIO 14
Bouton MARCHE btn1On btn2On btn3On
Bouton ARRÊT btn1Off btn2Off btn3Off
État état1 état2 état3

Enfin, nous devons ajouter des références aux fichiers JavaScript externes. Pour notre application, nous allons créer deux fichiers JavaScript : auth.js (qui gère tout ce qui concerne l’authentification) et index.js qui gère tout ce qui concerne l’interface utilisateur. Nous allons créer ces fichiers dans un dossier appelé scripts dans le dossier public de notre application.

<script src="https://www.raspberryme.com/control-esp-gpios-firebase-web-app/scripts/auth.js"></script>
<script src="scripts/index.js"></script>

Après avoir apporté les modifications nécessaires (insertion de votre objet firebaseConfig), vous pouvez enregistrer le fichier HTML.

style.css

Dans le dossier public, créez un fichier appelé style.css. Pour créer le fichier, sélectionnez le dossier public, puis cliquez sur l’icône +fichier en haut de l’explorateur de fichiers. Appelez-le style.css.

Créer un fichier CSS VS Code

Ensuite, copiez ce qui suit dans le fichier style.css

html {
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    display: inline-block;
    text-align: center;
}
h1 {
    font-size: 1.8rem;
    color: white;
}
.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;
}

body {
    margin: 0;
}

.card-grid {
    max-width: 800px;
    margin: 0 auto;
    display: grid;
    grid-gap: 2rem;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
    background-color: white;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}

.card-title {
    font-size: 1.2rem;
    color: #034078
}
.state {
    color:#1282A2;
}
button {
    background-color: #049faa;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
    border-radius: 4px;
}
.button-on {
    background-color:#034078;
}
.button-on:hover {
    background-color: #1282A2;
}
.button-off {
    background-color:#858585;
}
.button-off:hover {
    background-color: #252524;
}

.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;
}

Afficher le code brut

Le fichier CSS comprend quelques styles simples pour améliorer l’apparence de notre page Web. Nous n’aborderons pas le fonctionnement de CSS dans ce didacticiel. Vous pouvez facilement modifier le fichier CSS pour changer les couleurs et la taille de la police, par exemple.

Fichiers JavaScript

Nous allons créer deux fichiers JavaScript (auth.js et index.js) dans un dossier scripts à l’intérieur du dossier public.

  • Sélectionnez le dossier public, puis cliquez sur l’icône +dossier pour créer un nouveau dossier. Appelez les scripts dans ce nouveau dossier.
  • Ensuite, sélectionnez le dossier des scripts et cliquez sur l’icône +fichier. Créez un fichier appelé auth.js. Ensuite, répétez les étapes précédentes pour créer un fichier index.js.

L’image suivante montre à quoi devrait ressembler la structure de dossiers de votre projet d’application Web.

Structure du fichier du dossier Firebase Project VS Code

auth.js

Mettons maintenant en œuvre la connexion des utilisateurs à l’aide de l’authentification Firebase. Nous mettrons en œuvre la connexion à l’aide d’un e-mail et d’un mot de passe.

Copiez ce qui suit dans le fichier auth.js que vous avez créé précédemment.

document.addEventListener("DOMContentLoaded", function(){

    // listen for auth status changes
    auth.onAuthStateChanged(user => {
        if (user) {
            console.log("user logged in");
            console.log(user);
            setupUI(user);
        } 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();
    });
    
});

Afficher le code brut

Ensuite, enregistrez le fichier. Ce fichier prend en charge tout ce qui concerne la connexion et la déconnexion de l’utilisateur. Continuez à lire pour savoir comment fonctionne le code ou passez à la section suivante.

Connexion

Les lignes suivantes sont responsables de la connexion de l’utilisateur.

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

Nous créons une variable qui fait référence à l’élément HTML du formulaire de connexion appelé loginForm.

const loginForm = document.querySelector('#login-form');

Si vous revenez au fichier index.html, vous pouvez voir que le formulaire a l’identifiant login-form.

Nous ajoutons un écouteur d’événement de type submit au formulaire. Cela signifie que les instructions suivantes s’exécuteront chaque fois que le formulaire sera soumis.

loginForm.addEventListener('submit', (e) => {

Vous pouvez obtenir les données soumises comme suit.

const email = loginForm['input-email'].value;
const password = loginForm['input-password'].value;

Si vous revenez au fichier HTML, vous verrez que les champs de saisie contiennent les identifiants suivants : input-email et input-password pour l’e-mail et le mot de passe, respectivement.

Maintenant que nous avons inséré l’e-mail et le mot de passe, nous pouvons essayer de nous connecter à Firebase. Pour ce faire, transmettez l’adresse e-mail et le mot de passe de l’utilisateur à la méthode suivante : signInWithEmailAndPassword :

auth.signInWithEmailAndPassword(email, password).then((cred) => {

Après la connexion, nous réinitialisons le formulaire et imprimons l’e-mail de l’utilisateur dans la console.

auth.signInWithEmailAndPassword(email, password).then((cred) => {
  // close the login modal & reset form
  loginForm.reset();
  console.log(email);
})

En cas d’erreur de connexion, nous interceptons le message d’erreur et l’affichons sur l’élément HTML message d’erreur (un paragraphe sous le formulaire).

.catch((error) =>{
  const errorCode = error.code;
  const errorMessage = error.message;
  document.getElementById("error-message").innerHTML = errorMessage;
  console.log(errorMessage);
});

Se déconnecter

L’extrait de code suivant est responsable de la déconnexion de l’utilisateur.

const logout = document.querySelector('#logout-link');
logout.addEventListener('click', (e) => {
  e.preventDefault();
  auth.signOut();
});

Lorsque l’utilisateur est connecté, un lien de déconnexion est visible dans la barre d’authentification. Ce lien a l’identifiant de lien de déconnexion (voir sur le fichier HTML). Donc, d’abord, nous créons une variable appelée logout qui fait référence au lien de déconnexion.

const logout = document.querySelector('#logout-link');

Ensuite, nous ajoutons un écouteur d’événement de type click. Cela signifie que les instructions suivantes s’exécuteront chaque fois que vous cliquerez sur le lien de déconnexion.

logout.addEventListener('click', (e) => {

Lorsque le bouton est cliqué, nous déconnectons l’utilisateur en utilisant la méthode signOut.

auth.signOut();

Changements d’état d’authentification

Pour garder une trace de l’état d’authentification de l’utilisateur – pour savoir si l’utilisateur est connecté ou déconnecté, il existe une méthode appelée onAuthSateChanged qui vous permet de recevoir un événement chaque fois que l’état d’authentification change.

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

Si l’utilisateur renvoyé est nul, l’utilisateur est actuellement déconnecté. Sinon, il est actuellement connecté.

Dans les deux scénarios, nous imprimons l’état actuel de l’utilisateur sur la console et appelons la fonction setupUI(). Nous n’avons pas encore créé cette fonction (nous la créerons dans la section suivante), mais elle sera chargée de gérer l’interface utilisateur en fonction de l’état d’authentification.

Lorsque l’utilisateur est connecté, nous passons l’utilisateur comme argument à la fonction setupUI(). Dans ce cas, nous afficherons l’interface utilisateur complète pour montrer les boutons permettant de contrôler les GPIO, comme vous le verrez plus tard.

if (user) {
  console.log("user logged in");
  console.log(user);
  setupUI(user);

Si l’utilisateur est déconnecté, nous appelons la fonction setupUI() sans aucun argument. Dans ce scénario, nous afficherons simplement un message informant que l’utilisateur est déconnecté et n’a pas accès à l’interface (comme nous le verrons plus tard).

} else {
  console.log("user logged out");
  setupUI();
}

index.js

Le fichier index.js gère l’interface utilisateur – il affiche le bon contenu en fonction du statut d’authentification de l’utilisateur. Lorsque l’utilisateur est connecté, il obtient les états GPIO de la base de données et met à jour les états GPIO sur l’interface. Ensuite, il change les états chaque fois que vous appuyez sur les boutons.

Copiez ce qui suit dans le fichier index.js.

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

// Elements for GPIO states
const stateElement1 = document.getElementById("state1");
const stateElement2 = document.getElementById("state2");
const stateElement3 = document.getElementById("state3");

// Button Elements
const btn1On = document.getElementById('btn1On');
const btn1Off = document.getElementById('btn1Off');
const btn2On = document.getElementById('btn2On');
const btn2Off = document.getElementById('btn2Off');
const btn3On = document.getElementById('btn3On');
const btn3Off = document.getElementById('btn3Off');

// Database path for GPIO states
var dbPathOutput1 = 'board1/outputs/digital/12';
var dbPathOutput2 = 'board1/outputs/digital/13';
var dbPathOutput3 = 'board1/outputs/digital/14';

// Database references
var dbRefOutput1 = firebase.database().ref().child(dbPathOutput1);
var dbRefOutput2 = firebase.database().ref().child(dbPathOutput2);
var dbRefOutput3 = firebase.database().ref().child(dbPathOutput3);

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

    //Update states depending on the database value
    dbRefOutput1.on('value', snap => {
        if(snap.val()==1) {
            stateElement1.innerText="ON";
        }
        else{
            stateElement1.innerText="OFF";
        }
    });
    dbRefOutput2.on('value', snap => {
        if(snap.val()==1) {
            stateElement2.innerText="ON";
        }
        else{
            stateElement2.innerText="OFF";
        }
    });
    dbRefOutput3.on('value', snap => {
        if(snap.val()==1) {
            stateElement3.innerText="ON";
        }
        else{
            stateElement3.innerText="OFF";
        }
    });

    // Update database uppon button click
    btn1On.onclick = () =>{
        dbRefOutput1.set(1);
    }
    btn1Off.onclick = () =>{
        dbRefOutput1.set(0);
    }

    btn2On.onclick = () =>{
        dbRefOutput2.set(1);
    }
    btn2Off.onclick = () =>{
        dbRefOutput2.set(0);
    }

    btn3On.onclick = () =>{
        dbRefOutput3.set(1);
    }
    btn3Off.onclick = () =>{
        dbRefOutput3.set(0);
    }

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

Afficher le code brut

Continuez à lire pour savoir comment fonctionne le code ou passez à la section suivante.

Obtenir des éléments HTML

Tout d’abord, nous créons des variables pour faire référence à plusieurs éléments de l’interface utilisateur en faisant référence à leurs identifiants. Pour identifier ces éléments, nous vous recommandons de consulter le fichier HTML fourni et de rechercher les éléments avec les identifiants référencés.

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

Le loginElement correspond au formulaire de connexion. Le contentElement correspond à la section de la page Web qui est visible lorsque l’utilisateur est connecté (qui affiche les lectures des capteurs). L’élément userDetailsElement correspond à une section qui affichera l’email de l’utilisateur connecté. L’auhtBarElement correspond à la barre d’authentification qui affiche l’état actuel de l’utilisateur, l’e-mail de l’utilisateur authentifié et le lien de déconnexion.

Ce qui suit crée des variables pour faire référence aux boutons en tant qu’états GPIO sur l’interface :

// Elements for GPIO states
const stateElement1 = document.getElementById("state1");
const stateElement2 = document.getElementById("state2");
const stateElement3 = document.getElementById("state3");

// Button Elements
const btn1On = document.getElementById('btn1On');
const btn1Off = document.getElementById('btn1Off');
const btn2On = document.getElementById('btn2On');
const btn2Off = document.getElementById('btn2Off');
const btn3On = document.getElementById('btn3On');
const btn3Off = document.getElementById('btn3Off');

Chemins et références de base de données

Ensuite, nous devons créer des chemins de base de données vers lesquels les états GPIO sont enregistrés :

// Database path for GPIO states
var dbPathOutput1 = 'board1/outputs/digital/12';
var dbPathOutput2 = 'board1/outputs/digital/13';
var dbPathOutput3 = 'board1/outputs/digital/14';

Pour pouvoir interagir avec la base de données sur ces chemins, nous devons créer des références de base de données en utilisant ces chemins :

// Database references
var dbRefOutput1 = firebase.database().ref().child(dbPathOutput1);
var dbRefOutput2 = firebase.database().ref().child(dbPathOutput2);
var dbRefOutput3 = firebase.database().ref().child(dbPathOutput3);

Fonction sertupUI()

Ensuite, nous créons la fonction setupUI () qui gérera l’interface utilisateur en fonction de l’état de l’authentification de l’utilisateur.

Dans le fichier auth.js, nous avons appelé la fonction setupUI() avec l’argument utilisateur setupUI(user) si l’utilisateur est connecté ; ou la fonction sans argument setupUI() lorsque l’utilisateur est déconnecté.

Alors, vérifions ce qui se passe lorsque l’utilisateur est connecté.

if (user) {

Nous montrons la barre d’authentification (qui affiche les détails de l’utilisateur et le lien de déconnexion). Pour ce faire, nous pouvons définir son style d’affichage sur bloquer. Nous voulons également que le contenu principal de la page Web avec les lectures des capteurs soit visible.

contentElement.style.display = 'block';
authBarElement.style.display ='block';

Enfin, nous pouvons obtenir l’e-mail de l’utilisateur connecté avec user.email et l’afficher dans la section userDetailsElement comme suit :

userDetailsElement.innerHTML = user.email;

Obtenir les états GPIO

Les lignes suivantes obtiennent les états GPIO chaque fois qu’il y a un changement dans la base de données et mettent à jour les éléments HTML correspondants avec les nouvelles valeurs.

//Update states depending on the database value
dbRefOutput1.on('value', snap => {
  if(snap.val()==1) {
    stateElement1.innerText="ON";
  }
  else{
    stateElement1.innerText="OFF";
  }
});
dbRefOutput2.on('value', snap => {
  if(snap.val()==1) {
    stateElement2.innerText="ON";
  }
  else{
    stateElement2.innerText="OFF";
  }
});
dbRefOutput3.on('value', snap => {
  if(snap.val()==1) {
    stateElement3.innerText="ON";
  }
  else{
    stateElement3.innerText="OFF";
  }
});

Événements de bouton

Ensuite, nous ajoutons des événements aux boutons pour écrire 1 ou 0 dans le chemin de la base de données correspondant en fonction du bouton qui a été pressé.

// Update database upon button click
btn1On.onclick = () =>{
  dbRefOutput1.set(1);
}
btn1Off.onclick = () =>{
  dbRefOutput1.set(0);
}

btn2On.onclick = () =>{
  dbRefOutput2.set(1);
}
btn2Off.onclick = () =>{
  dbRefOutput2.set(0);
}

btn3On.onclick = () =>{
  dbRefOutput3.set(1);
}
btn3Off.onclick = () =>{
  dbRefOutput3.set(0);
}

Interface utilisateur déconnecté

L’extrait de code suivant gère l’interface utilisateur lorsque l’utilisateur se déconnecte. Nous souhaitons masquer la barre d’authentification et le contenu principal de la page Web (états GPIO et boutons correspondants) et afficher le formulaire de connexion.

} else{
  // toggle UI elements
  loginElement.style.display = 'block';
  authBarElement.style.display ='none';
  contentElement.style.display = 'none';
}

Fichier d’icône de favori

Pour afficher un favicon dans votre application Web, vous devez déplacer l’image que vous souhaitez utiliser comme favicon dans le dossier public. L’image doit s’appeler favicon.png. Vous pouvez simplement faire glisser le fichier favicon de votre ordinateur dans le dossier public de VS Code.

Nous utilisons l’icône suivante comme favicon pour notre application Web :

Déployez votre application

Après avoir enregistré les fichiers HTML, CSS et JavaScript, déployez votre application sur VS Code en exécutant la commande suivante dans la fenêtre Terminal.

firebase deploy

Le terminal devrait afficher quelque chose comme suit :

ESP32 ESP8266 Déployer l'application Web Firebase

Firebase propose un service d’hébergement gratuit pour servir vos actifs et vos applications Web. Ensuite, vous pouvez accéder à votre application Web de n’importe où.

Vous pouvez utiliser l’URL d’hébergement fournie pour accéder à votre application Web de n’importe où.

Manifestation

Toutes nos félicitations! Vous avez déployé votre application avec succès. Il est maintenant hébergé sur un CDN mondial utilisant l’hébergement Firebase. Vous pouvez accéder à votre application Web de n’importe où sur l’URL d’hébergement fournie. Dans mon cas, c’est https://esp-firebase-demo.web.app.

Firebase Web App Control ESP32 ESP8266 GPIOs de n'importe où avec authentification

L’application Web est réactive et vous pouvez y accéder à l’aide de votre smartphone, ordinateur ou tablette.

Insérez l’e-mail et le mot de passe de l’utilisateur autorisé que vous avez ajouté dans les méthodes d’authentification Firebase. Après cela, vous pouvez accéder au tableau de bord pour contrôler les GPIO ESP32 ou ESP8266.

Accédez à l’onglet Hébergement de la console Firebase de votre projet. Vous pouvez voir les domaines de votre application, déployer l’historique et même revenir aux versions précédentes de votre application.

Historique et domaines de déploiement de l'application Web Firebase

Conclusion

Dans ce didacticiel, vous avez appris à créer une application Web Firebase avec authentification de connexion/déconnexion pour contrôler les GPIO ESP32 ou ESP8266 de n’importe où. Les états GPIO sont enregistrés sur la base de données en temps réel et l’ESP écoute tous les changements qui se produisent dans la base de données pour mettre à jour les GPIO immédiatement. Vous pouvez facilement ajouter plus de GPIO ou plus de cartes à ce projet.

La base de données est protégée à l’aide de règles de base de données. Seuls les utilisateurs authentifiés autorisés peuvent accéder à l’application Web pour contrôler les GPIO.

Vous pouvez combiner ce projet avec d’autres projets ESP32/ESP8266 Firebase que nous avons publiés et ajouter plus de fonctionnalités à votre application.

Si vous souhaitez en savoir plus sur Firebase, nous vous recommandons de jeter un œil à notre nouvel eBook, exclusivement dédié à ce sujet :

Nous avons d’autres ressources liées à ESP32 et ESP8266 qui pourraient vous plaire :

Merci d’avoir lu.

Cette vidéo vous emmène dans l’histoire de Raspberry Pi :

YouTube video