Hibernation ou non ? Le canard est toujours vivant... |
Maj : 13/08/21
Abstract :
Résumé : |
Et bien non, le webmaster n’est pas en hibernation malgré une longue navigation et la bronzette aux Antilles en compagnie des moustiques agressifs.
Après une introduction explosive de l’intégration du capricieux Nextion à mes programmes de domotique, plus rien ne semble bouger dans les pages WEB depuis l’été Covid 2020 !
Il n’est est rien mais le système reste coincé.
Mes programmes de domotique marchaient parfaitement, avec un fichier ino d’environ 4000 lignes de code (un gros tas...). L’introduction du Nextion en a rajouté 2000 (sans parler des HMI propres au Nextion), et tout continuait à fonctionner, mais je commençais à me heurter à un mur.
Une telle masse de lignes en vrac, mélangeant programme et IHM devenait impossible à maintenir quand il a fallu rajouter d’autres « clients » d’affichage, comme, le PC via usb, le smartphone en Bluetooth, un serveur en Wifi…
La seule solution était de tout reconstruire en classes modulaires propres pour retrouver un système fonctionnel en séparant totalement les données et l’IHM
Il ne faut pas s’obstiner à boucher sans fin les fissures d’un bâtiment branlant, il faut tout raser et reconstruire sur de nouvelles fondations solides.
Citation d'auteur inconnu : "Ce n'est pas en améliorant la bougie qu'on a inventé l'ampoule électrique."
Tout doit être conçu en classes indépendantes et robustes, avec chaque fois un programme de test rigoureux pour chaque méthode mise à disposition.
On arrive ainsi à décomposer en un ensemble de nombreuses classes en C++
** ESP32 **
C’est la classe (mère) principale d’entrée qui fournit à (presque) toutes les autres le numéro de la carte, indispensable pour les corrections de capteurs et les signatures (adresses) des 18b20.
** Interrupt **
Pendant plus de 95% du temps, le système est en sommeil pour économiser l’énergie, je participe activement à la lutte contre le réchauffement climatique pour protéger les ours polaires…
Il faut quand même le réveiller de temps en temps !
Toute les minutes une interruption est déclenchée par l’horloge RTC qui génère une avalanche d’actions.
* Tous les capteurs sont lus et un tableau de valeurs instantanées corrigées et maintenu à jour.
* Si la minute est multiple de 4 écriture de toutes les nouvelles valeurs dans la base de données sur 4 jours et rafraîchissement complet des clients d’affichage.
* Si Minuit, les dernières 24 h sont sauvées dans la carte SD pour permettre les exploitations futures sur de longues périodes (plus de 4 jours).
D’autres déclenchements sont possibles, par divers boutons sur la carte (GPIO) par le PIO, ou via l’IHM qui demande une nouvelle page.
Trois classes capteurs offrent chacune une méthode pour lire la température : Float getRawTemp () ;
** DS18b20 **
(il y en a 3 sur la ligne One Wire)
** BMP280 **
(avec en plus getRawPress())
** DS3231 **
(avec en plus l’horloge RTC fournissant l’heure et déclenchant les interruptions minute)
** PCF8574 **
La classe PIO gère les 5 leds {" Red", " Green", " Blue", " Yellow", " White"} et 3 boutons poussoirs (via la classe interruption)
** Datas **
Cette classe gère les lectures et écritures de la base de données.
Elle maintient (interruption minute) toutes les données à jour (capteurs, ...) et gère le pointeur de la base.
** DatasW **
La classe fille DataWrite n’est activée que toutes les 2 minutes pour écrire les données brutes fraîches dans la base. C’est une classe très légère.
** DatasR **
La classe lourde DataRead est la plus complexe. Elle répond à un appel de l’IHM qui demande un affichage de page.
Elle réalise les nombreux calculs sur les données de la base, transformant les données brutes en compensées, calculant minimum et maximum, optimisant les affichages en valeurs entières, gérant les étiquettes à afficher, les lignages, etc.
L’appel à cette classe se fait par une unique méthode qui contient en paramètres le format d’affichage, en effet elle s’adapte à n’importe qu’elle résolution et sort le tableau des pixels, vexteurs et textes optimisé pour affichage direct par le client.
Les classes IHM (Interfaces Homme-Machine). Toutes sortes d’affichages sont possibles, il sera simple d’en rajouter sans aucun risque de fragiliser l’existant.
Pour commencer nous ne traiterons que de la première.
** Nextion **
Comme vu sur une autre page, cet IHM présente de nombreuses carences et il faudra beaucoup ruser pour trouver des solutions de contournement, en particulier à cause de l’impossibilité catastrophique d’inclure des fonctions internes.
Dans tous les cas, il faudra lui envoyer 360 lignes pour la courbe, plus les quadrillages, les étiquettes, etc. Ce sont des lignes de commande très lourdes du genre :
nexSerial.print("xstr 380,0,100,40,0,RED,GRAY,1,1,1,t1.txt") ;
Il faut les passer à 115 kbauds, c’est très long et l’image prend 0.7 seconde à rafraîchir !
Il n’y a aucun moyen de faire autrement. Le temps d’effectuer tous les calculs complexes par l’ESP32 est totalement négligeable.
Nous n’évoquerons les classes secondaires que plus tard.
Chaque classe est testée par un programme ino le plus rigoureux possible pour déceler toute anomalie, vérifier les bonnes initialisations et chacune répond bien aux spécifications.
Un très gros problème apparaît lorsque toutes ces superbes classes sont mises ensemble, appelées depuis la classe mère, pour réaliser un ino d’exécution global presque vide !
Chaque classe testée séparément marche très bien, mais quand tout est en place, cela fait 20 classes encapsulés qui doivent papoter en n’utilisant quasiment aucune variable globale.
Alors que tout semblait bien conçu pour que les méthodes communiquent entre les classes, la compilation donne des messages d’erreurs obscurs indiquant que des méthodes des classes ne se voient pas...
Il s’agit d’un défaut de conception extrêmement difficile à régler, bien plus complexe que la programmation de tout le code précédent. C’est sur ce point que tout bloque et que l’ensemble des classes amoureusement concoctées refuse de coopérer. Ma conception est bancale et je suis pour le moment dans une impasse.
IL existe de très nombreux bons ouvrages et cours sur le C++, mais le sujet de la coexistence harmonieuse d’un ensemble de classes est très obscur.
Qui, comment, dans quel ordre, …, se font les initialisations des classes et instanciations des objets ?
C’est la base pour que tout coexiste ! En cas de problèmes ici, rien ne fonctionnera.
Je suis dans le syndrome du « culte du cargo », j’applique des solutions en partant d’exemples mal ou non compris, et la résolution divine n’apparaît pas.
Je continue à développer les codes, mais les classes ne vivent qu’appelées individuellement depuis un ino encore trop gros, ce qui n’était pas l’objectif prévu. Le projet ne se concrétisera que lorsque le brouillard sera dissipé.
Ne sous-estimez pas ce problème de conception qu’il faut régler avant tout en faisant des classes quasiment vides avec des méthodes publiques qui ne font que renvoyer des données fictives pour vérifier les liaisons inter classes, sans se préocuper des fonctions (cuisine interne invisible hors de la classe).
Il sera ensuite facile d’écrire les vraies fonctions et méthodes. J’ai fait exactement le contraire.