MyGlassBox — un miroir connecté, du prototype au produit
Quatre mois pour porter un miroir sans tain au stade du produit : Raspberry Pi en kiosque, point d’accès Wi-Fi embarqué, back-office PHP et applications mobiles. Ce qui a tenu, ce qui n’aurait pas dû.
Technologies employées
- Raspberry Pi
- Raspbian
- PHP 5
- MySQL
- Apache
- hostapd
- dnsmasq
- Midori
- Matchbox
- Android
- iOS
- jQuery
D’octobre 2016 à février 2017, j’ai tenté de transformer une idée en produit : un miroir sans tain doublé d’un écran, qui affiche la météo, les messages, les rappels et les photos qu’on lui envoie depuis un téléphone. Pas seulement le code — le matériel, l’image système, les applications mobiles, la brochure, l’étude de coûts et le modèle économique. Le projet s’est arrêté avant la commercialisation. Ce qui reste est un objet qui fonctionnait vraiment, une architecture réseau dont je suis toujours satisfait, et une poignée de décisions que je regarde aujourd’hui avec beaucoup moins d’indulgence.
L’objet
Une glace sans tain devant une dalle d’écran : là où l’écran est noir, on voit son reflet ; là où il affiche du blanc, le texte traverse la glace et semble flotter dans le miroir. Tout l’effet tient dans ce contraste, et donc dans une interface presque entièrement noire.

Derrière la glace : un Raspberry Pi, un module L298N pour piloter le ruban de LED, un capteur de température et d’humidité, un capteur tactile capacitif collé au dos de la vitre, deux haut-parleurs, une clé Wi-Fi et une alimentation commune répartie par bornes à levier.

Le problème que personne ne voit dans une démo
Un miroir connecté est vendu à un particulier, donc installé derrière une box Internet. Aucune adresse publique, aucun port ouvert, aucune redirection à demander au client — un produit grand public ne peut pas exiger que l’acheteur configure son routeur.
Or le back-office doit pouvoir agir dessus : régler le volume, couper le son, redémarrer, lancer une vidéo. Comment commander un appareil qu’on ne peut pas joindre ?
La réponse retenue inverse le sens : le miroir interroge le serveur, jamais l’inverse. Le back-office se contente d’écrire la commande dans une colonne d’une table, et le miroir la récupère à son rythme. C’est la bonne réponse, et c’est encore celle que je donnerais aujourd’hui — le principe est exactement celui d’un agent qui tire sa configuration depuis un point central.
Un ordre aurait dû être un mot dans une liste fermée — volume:70, reboot —
que le miroir traduit lui-même en action. Le code livré transportait le
comportement au lieu de transporter l’intention. C’est la différence entre une
commande et une injection, et elle tient dans le vocabulaire employé.
Le point d’accès embarqué
La décision dont je suis le plus satisfait ne concerne pas l’application, mais le premier démarrage.
À la sortie du carton, le miroir n’a aucun réseau, aucun clavier et un écran
qu’on ne peut pas toucher. Il démarre donc son propre point d’accès Wi-Fi,
nommé MYGLASSBOX- suivi de quatre caractères aléatoires, avec hostapd et
dnsmasq, un serveur DHCP sur une plage de quatre adresses et un nom local
résolu sur le Pi lui-même. L’acheteur s’y connecte depuis son téléphone, ouvre
une page, saisit les identifiants de sa box, et le miroir bascule sur le réseau
domestique.
C’est un mécanisme d’appairage classique aujourd’hui ; en 2016, dans un projet mené seul, en avoir vu la nécessité reste ce dont je suis le plus content.
L’affichage : un navigateur en kiosque
Il n’y a pas d’application graphique. Le miroir affiche une page web servie en local, dans un navigateur sans aucun ornement.
| Élément | Choix retenu | Ce qu’il apportait |
|---|---|---|
| Gestionnaire de fenêtres | Matchbox | Aucune décoration, aucune barre : la page occupe la dalle |
| Navigateur | Midori | Léger, suffisant pour du DOM et de l’AJAX sur un Pi |
| Curseur | unclutter | Le pointeur disparaît — un miroir n’a pas de souris |
| Entrées simulées | xdotool, xautomation | Rejouer une frappe pour relancer l’affichage |
| Serveur | Apache et PHP en local | La page est servie par la machine qui l’affiche |
| Son | mpg321 | Lecture des musiques et des radios sans interface |
Chaque bloc de l’écran est un petit script PHP interrogé séparément : un pour la météo, un pour la température, un pour les messages, un pour les rappels. La page les rappelle en boucle et remplace le fragment correspondant. Découpage sommaire, mais il a une vertu réelle : la panne d’un bloc n’emporte pas l’écran. Si la météo ne répond pas, le reste continue de s’afficher.
Ce qui n’allait pas
Le code de 2017 comporte des défauts que je ne laisserais passer sur aucune revue aujourd’hui, et il vaut mieux les nommer.
Les identifiants de la base sont écrits en clair dans chaque fichier, et recopiés d’un fichier à l’autre — le même script ouvre parfois trois connexions successives avec les mêmes paramètres répétés à l’identique. Une inclusion partagée existait pourtant déjà dans le projet ; elle n’a pas été utilisée partout.
Les requêtes sont construites par concaténation. L’adresse e-mail et l’identifiant de l’appareil arrivent de la session ou de l’URL et sont insérés directement dans le SQL. Les requêtes préparées existaient en PHP 5 depuis des années ; je ne les ai pas employées.
L’authentification tient dans un jeton passé en paramètre d’URL, comparé à une valeur unique lue en base — la même pour tous les appareils. Un identifiant d’appareil dans l’adresse suffisait ensuite à désigner le compte associé.
Le déploiement passait par un FTP en clair, dont les identifiants figurent
dans le script d’installation exécuté sur chaque miroir. Le même script élargit
les droits du serveur web au maximum et lui accorde sudo sans mot de passe.
Le produit autour du code
La partie que je sous-estimais complètement en commençant, c’est tout ce qui n’est pas du code. Sur quatre mois, une bonne moitié du temps y est passée : étude des coûts de fabrication, grille tarifaire, contrat de vente, politique de conservation des données, choix du nom commercial, brochure, visuels pour les deux magasins d’applications, préparation d’une campagne de financement participatif, et deux applications mobiles empaquetées.
Le modèle économique visé était celui qu’on appelle hardmium : vendre l’objet à prix coûtant ou presque, parce que sa vraie fonction est de rendre un service qui, lui, fidélise. J’avais noté à l’époque le risque principal de ce modèle — que l’objet soit détourné de son service — et c’est bien ce qui rendait l’équation fragile pour un miroir dont la valeur perçue reste celle d’un meuble.
Le projet s’est arrêté là, avant la mise en vente. Un prototype fonctionnel, une chaîne complète, et pas de marché démontré.
Enseignements
- Un appareil vendu à un particulier vit derrière une box : il tire sa configuration, il ne la reçoit pas. Le principe reste valable, c’est sa mise en œuvre qui était fautive.
- Une commande doit transporter une INTENTION prise dans une liste fermée, jamais un comportement exécutable. Écrire du JavaScript en base, c’est confondre les deux.
- Prévoir l’appairage avant le réseau : un point d’accès embarqué au premier démarrage est ce qui rend un objet connecté installable par son acheteur.
- Découper l’affichage en fragments indépendants évite qu’une source défaillante n’efface tout l’écran — la seule vertu du découpage sommaire de l’époque.
- Savoir qu’une rustine est une rustine ne la rend pas acceptable : mes propres commentaires signalaient les droits trop larges, et j’ai livré quand même.
- Sur un projet de produit, le code n’est qu’une moitié du travail. L’autre moitié — coûts, contrat, données, distribution — décide autant du résultat.
Ce projet est le plus ambitieux que j’aie mené seul, et le seul qui soit allé jusqu’à la brochure et au plan de financement. Il n’a pas trouvé son marché, mais c’est lui qui m’a fait passer du code à l’exploitation : un objet posé chez quelqu’un doit démarrer sans moi, se raccorder sans moi, se réparer sans moi, et ne pas devenir une porte d’entrée chez son propriétaire. Ces quatre exigences décrivent assez bien ce que je fais aujourd’hui.