!
$
{
[
o
*
]
>

NOUS LES DEVS

Projet buzzer

Lever la maintenance d'un site en pressant un buzzer

Niveau : débutant(e)
</> </> </>

Un vieux projet

Cela fait déjà maintenant quelques années qu’Aurélien Luiselli, le COO de la boîte (#binsfeld) me challenge sur pas mal de défis techniques. Il y a une vieille idée qu’on avait évoquée il y a quelques années, qui était de pouvoir mettre en ligne un site web avec une sorte de buzzer. Le genre de projet que je sais être capable de faire mais que je n’ai jamais réalisé because j’ai 14.000 autres side projects sur le feu et que… ben voilà quoi.

Vendredi, nous avons eu la visite d’Aurélien qui était en proie à avoir une discussion technique sur n’importe quel sujet, et c’est celui-ci qui est ressorti. L’idée que, pour un évènement, on prépare un buzzer pour un client afin qu’il mette en ligne son site web en appuyant dessus. Lever une page comming soon en conférence de presse avec une simple pression sur un buzzer et sans l’intervention d’un développeur. Le genre de conversation qu’on peut avoir le vendredi soir avant de finir la semaine et qui te met une idée à la con dans le cerveau avant de partir en week-end.

challenge-accepted

Interrupteur

La partie centrale de ce projet est le buzzer. Le truc, c’est que je n’en n’ai pas. Mais j’ai quelques composants électriques comme des interrupteurs et selon moi, c’est physiquement ce qui se rapproche le plus d’un buzzer.

interrupteur

Arduino

Comme je trouvais le défi un peu trop simple, j’ai pris la décision de construire un buzzer de 0 à partir d’un interrupteur. Heureusement pour moi, j’avais en ma possession un starter kit Arduino et je me dis que ça fera l’affaire pour prototyper et réaliser un buzzer fait maison et que ça sera sans doute dix fois plus enrichissant (spoiler alerte : ce fut le cas).

starter_kit_arduino

Schéma électrique

Il m’a fallu une petite demi-heure pour mettre les fils sur le board vu que dans le principe c’est relativement simple. Je vais détailler chaque point du schéma électrique pour que tu puisses comprendre et voici à quoi ça ressemble.

schema_arduino_buzzer

Au démarrage, il y a mon Mac qui alimente l’Arduino via un port USB. L’Arduino est le cerveau, ce qui va permettre de détecter les changements électriques. Il faut savoir que tout est électrique. Soit on mesure un passage du courant, soit une tension (qui peut varier).

Le board permet de faire passer le courant sur des lignes (les traits sur mon schéma) horizontalement sur les extrémités et verticalement à l’intérieur. J’ai juste à insérer de petits fils dans les trous qui s’attachent automatiquement.

arduino_breadboard

Le point (1) est un câble électrique qui part de la borne + et qui vient alimenter le board.

Le point (2) est juste un fil qui vient alimenter une ligne intérieure sur laquelle je place une liaison vers la borne + du buzzer (3). Je rebranche la borne négative du buzzer (4) sur une nouvelle ligne et juste après je branche un câble (5) sur P, une PIN de lecture de l’Arduino.

J’aurais pu fermer le circuit juste après et ça aurait fonctionné mais idéalement on place une LED afin de savoir si le courant passe bien. C’est ce que je fais en (6). Je place d’abord une résistance pour ne pas flinguer la LED ensuite je branche la patte haute de la LED du positif vers le négatif (7). Je viens ensuite avec un câble (8) sur la ligne négative de l’extérieur du board.

Enfin je relie la ligne négative à la borne négative de l’Arduino pour fermer le circuit.

Test électrique

Un petit test pour vérifier que le courant passe bien.

P.S. C’est le modèle final avec une rallonge de câble et une consolidation des fils pour le transport mais au niveau du schéma ça colle parfaitement.

Programme de l'Arduino

Maintenant je dois développer le programme à mettre sur l’Arduino. Et pour cela, pas besoin d’apprendre grand chose. On ne va même pas dépasser l’exercice numéro 1 du livre fourni avec le starterkit, c’est pour dire.

#include <Arduino.h>

int timeToPress		= 0;
int readBuzzer		= 0;
int signalWrited	= 0;


void setup() {
	pinMode(2,INPUT);
	Serial.begin(9600);
}

void loop() {

	readBuzzer = digitalRead(2);
	if( readBuzzer == LOW ){
		signalWrited	= 0;
		timeToPress 	= 0;
	}else{
		timeToPress++;
		if( timeToPress > 1 & signalWrited == 0){
			Serial.println("signal_for_python");
			delay(1000);
			signalWrited=1;
		}
	}

	delay(1000);
	
}

J’inclus la bibliothèque Arduino.h afin de pouvoir manipuler les PIN. Je déclare quelques variables.

La fonction setup() est native à Arduino et va s’exécuter une fois au démarrage. Je définis que j’ai branché ma lecture de courant sur la PIN numéro 2 et que c’est une entrée. Je mets un classique Baud rate à 9600.

La fonction loop() quant à elle va s’exécuter sans arrêt au démarrage de l’Arduino. À l’intérieur je vais détecter si du courant passe sur la PIN 2. Si ce n’est pas le cas je définis que le signal n’est pas encore écrit (que je n’ai rien écrit dans le port série) et que le temps pressé est de 0. Dans le cas contraire, ça veut dire que le buzzer est pressé donc j’incrémente le temps pressé de 1.

Je mets une condition que si le temps pressé est strictement supérieur à 1 et que le signal est à zéro alors j’entre dans ma seconde condition (le second if). Vu que je fais un delay de 1000 en dessous de mon programme, alors ça veut dire qu’il faut que le buzzer reste allumé au moins 2 secondes pour rentrer dans ce if. Si la condition est respectée, alors j’écris dans le port série une phrase bien spécifique « signal_for_python » et ensuite je passe la variable à signalWrited à 1 pour éviter d’écrire à chaque seconde.

arduino_ide_buzzer

Au niveau de l’IDE, je vois bien mon message apparaître dans le serial monitor lorsque j’appuie sur le « buzzer ».

Pas de wifi

Comme je n’ai pas de module Wifi à ma disposition, je vais faire relai via mon ordinateur. C’est un peu comme si je devais développer le logiciel du buzzer finalement. J’ai choisi de lancer un petit script Python pour écouter le port série de mon Arduino et là, j’imagine que tu auras compris pourquoi « signal_for_python ». En fait ce mot va faire pont entre mon code Arduino et le programme Python.

Attention, le code est incroyable… On écoute en boucle les entrées sur le port série. Si ce qui est lu est « signal_for_python » alors on balance un cURL système sur une URL spécifique.

 # -*- coding: utf-8 -*-
import serial
import time
import subprocess

ser = serial.Serial('/dev/cu.usbmodem14101', 9600)

while True:

	data = ser.readline().decode().strip()

	if data == "signal_for_python":
		subprocess.call(["curl", "-o", "/dev/null", "https://nouslesdevs.com/static_export/maintenance/reverse_maintenance.php"])

	time.sleep(0.1)

P.S. Il faut fermer le logiciel Arduino IDE sinon le script va dire qu’il ne peut pas écouter car l’appareil est déjà utilisé.

Le levé de rideau

Pour lever un rideau, c’est un script PHP qui va faire ça. Le but pour s’amuser c’est vraiment d’utiliser un maximum de langages, si si.

En premier lieu j’ajoute un petit fichier .htaccess qui va opérer une maintenance. On peut imaginer que maintenance est une comming soon ou n’importe quoi d’autre.

# MAINTENANCE MODE
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{REQUEST_URI} !^/static_export/maintenance/.*$
	RewriteRule .* https://nouslesdevs.com/static_export/maintenance/ [R=302,L]
</IfModule>

Je crée un fichier .htaccess_reverse_maintenance qui lui fait l’inverse, c’est-à-dire qu’il redirige tout le trafic de la maintenance vers le site final.

// REVERSE MAINTENANCE
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteCond %{REQUEST_URI} ^/static_export/maintenance/.*$
	RewriteRule .* https://nouslesdevs.com/static_export/index.html [L]
</IfModule>

Dans le dossier de maintenance, j’ajoute un fichier PHP reverse_maintenance.php (celui qui va être appelé en cURL par Python). À l’intérieur je fais juste l’inversion via une copie par écrasement du fichier .htaccess.

<?php

	// Chemin du modèle de maintenance
	$maintenance_template = '../.htaccess_reverse_maintenance';

	// Chemin où le fichier de maintenance sera créé
	$maintenance_file = '../.htaccess';

	// Copie du contenu du modèle de maintenance dans le fichier de maintenance
	copy($maintenance_template, $maintenance_file);

Page de maintenance

Si jamais le client affiche la page de maintenance sur un grand écran, j’aimerais bien que l’inversion de maintenance se détecte automatiquement afin que le client ne doive pas rafraichir la page. Pour ce faire, j’ai choisi de lancer un petit fetch en Javascript qui, toutes les 5 secondes, vérifie si la redirection est toujours en place. Si l’URL de retour est différente, alors je lance simplement un refresh de page, ce qui devrait m’afficher le site.

<h1>Ma super page de maintenance !!</h1>

<script>

	function fetchPageContent() {
		fetch('https://nouslesdevs.com/static_export/index.html',{method: 'GET',cache: 'no-cache',headers: {'Cache-Control': 'no-cache'}})
			.then(response => {
				if( response.redirected == true && response.url == "https://nouslesdevs.com/static_export/maintenance/" ){
					// nothing change
				}else{
					// URL change
					location.reload();
				}
			
			})
	}

	// Exécuter la fonction fetchPageContent toutes les 5 secondes
	setInterval(fetchPageContent, 5000);

</script>

Résultat final

Dans l’exemple en vidéo, tu peux voir l’ordinateur à gauche afficher la page web avec la maintenance. Il y a un fetch toutes les 5 secondes qui va permettre de refresh la page ou non. L’ordinateur de droite alimente l’Arduino et fait le pont avec. C’est cette machine qui va faire le cURL dès que je vais buzzer. Le serveur web qui fait tourner le site est quant à lui dans le cloud. Oui, c’est un vrai site web qui est fonctionnel ce n’est pas une démo en local.

Un nouveau défi

Quand on est développeur web, on est plus sur la partie logicielle. Pouvoir toucher à la partie électronique et faire un projet de bout à bout est vraiment exaltant. Ça renforce encore plus mon idée que tout est vraiment possible et que c’est une question de moyen, de temps et de volonté.

Maintenant il va falloir que je me trouve un nouveau défi !

25/06/2024

Yann Vangampelaere - nouslesdevs -

NOUS LES DEVS

Vous aimez ce que je fais ? Vous voulez que j'en fasse plus ? dans le développement du blog.