| 
	 
      | 
     |||||
|  
       
  | 
     
       Hibernation ou non ? Le canard est toujours vivant...  | 
     
       
  | 
  
|   Maj : 13/08/21 
 
  | 
  ||
![]()
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.