19) Agencement du démonstrateur du postes de pilotage.

Partir de rien pour arriver à agencer un réseau qui globalement semble fonctionner très correctement n’a pas du tout été un « long fleuve tranquille ». Étant à la retraite, j’ai été en mesure de consacrer un temps assez considérable pour défricher ce domaine qui manifestement n’est pas souvent abordé en ligne. Pour les personnes « dites en activité », il est impossible de pouvoir consacrer autant d’heures au développement de tels démonstrateurs. Aussi, vous fournir le canevas, l’ossature de réseaux qui fonctionnent m’a semblé très pertinent. Au final, le nombre d’heures incalculable consacrées à cette activité me semble un bon investissement. Pour que vous puissiez bénéficier au mieux du « fruit de ce travail », quelques organigrammes commentés me semblent bienvenus.

Le mode « génération automatique des JETONs ».

C’est la clef de voûte de l’architecture de notre construction logicielle. L’organigramme de la Fig.139 illustre le comportement attendu de l’une des procédures les plus vitales du démonstrateur P28_Poste_de_pilotage.ino. La toute première action consiste à déclencher en (1) un Chronomètre. Ensuite la boucle infinie commence par éteindre en (2) la LED triple rouge pour le cas où une erreur aurait été détectée dans le JETON retourné lors de la boucle précédente. Puis le démonstrateur vérifie en (3) si le compteur pour une minute est arrivé à 60 secondes. Si c’est le cas, en (4) il est réarmé pour une nouvelle minute, et en (5) on vérifie que le dialogue avec le réseau est effectif. C’est la procédure (5) qui gérerait une rupture du dialogue. Ensuite, en (6) on teste le B.P. sur A1. S’il est activé on va en (7) dans la séquence qui éteint ou allume les écrans du système. La première action consiste en (7) à allumer la LED d’Arduino pour informer l’opérateur que le bouton poussoir est pris en compte. Il y a alors attente en (8) du relâcher de ce dernier. L’état du booléen Noir est alors inversé. Le but, c’est d’éteindre les écrans une fois sur deux puis de les rallumer. Si Noir est à l’état true, en (11) on se contente d’éteindre tous les modules d’affichage. Dans le cas contraire, en (12) on affiche l’écran d’exploitation, puis en (13) on rétablit les affichages sur les postes de Travail et enfin, la Led d’arduino est éteinte en (14) le B.P. ayant été traité. Puis le traitement « courant » reprend en (15) où l’état du booléen UN_sur_deux est inversé. Une fois sur deux, et s’il reste au moins une unité à l’écoute, on va en (17) générer aléatoirement un nouveau JETON pour le ou les unités à l’écoute. Ce JETON est alors transmis sur le réseau en (18), puis affiché sur l’écran en (19). Enfin, en (20) on teste pour savoir s’il y a un retour. C’est cette procédure qui traite l’arrivée des orphelins. Enfin, une fois sur deux (Et à chaque cycle si toutes les machines sont occupées en (21).) en (22) on dépile l’un des orphelins. Puis on retrouve une séquence identique à celle de (18), (19) et (20) pour transmettre le JETON et voir comment réagit le réseau.

Travail effectué par la procédure Verifier_le_retour.

L’organigramme de la Fig.140 présente son architecture et montre assez bien que ce module de code C++ est une pièce maitresse de l’édifice. Bien que titrée Verifier_le_retour dans l’organigramme de la Fig.139, en réalité, actuellement cette procédure est nommée dans le démonstrateur Regarde_si_JETON_orphelin_sur_USB() pour avoir un identificateur « plus parlant ». En entrée de procédure, en (1) on commence par des initialisations de variables. Puis, en (2) la LED triple s’illumine en bleu pour visualiser la transmission d’une consigne sur le réseau. C’est en (3) que l’on déclenche le chronométrage du temps d’attente maximal avant de considérer que le JETON a été accepté par le poste de Travail. Commence alors une boucle d’attente en (4) et (5) dans laquelle on va rester tant qu’en (5) le délai d’attente n’est pas dépassé ou qu’en (4) un JETON n’est pas arrivé. Supposons que le JETON a été pris en compte et qu’il est valide. Alors l’unité cible l’accepte et ne le retourne pas dans le réseau. En (5) il y a sortie de la boucle. Si le chronométrage n’est pas arrivé à son terme et qu’en (4) on détecte l’arrivée d’un JETON, dans ce cas en (6) il est extrait du module Bluetooth. Cet organigramme ne montre pas toute la complexité du logiciel, car une partie très importante est traitée en (7) dans la procédure Traiter_un_retour_orphelin() et dans ses subroutines. Dans tous les cas, la suite de l’algorithme consiste à valider en (9) le poste de Travail concerné si c’est en (8) le dépassement du TIME_OUT qui a provoqué la sortie en (5).

Pour résumer le travail important qui se fait dans les procédures et leurs subroutines qui vont être détaillée plus avant, il importe déjà de comprendre qu’il y a les circonstances qui permettent de dépiler un JETON en attente, et au contraire celles pour le dépiler. Par ailleurs, plusieurs cas d’orphelins revenant du réseau doivent être ignorés, car ils ne correspondent pas au cas d’un poste de Travail occupé. Par exemple on peut citer :
• Le 555 ou le 666 servant à vérifier la synchronisation initiale du réseau.
• Le 999 qui toutes les minutes permet de tester le dialogue entre toutes les composantes du réseau.
• Les consignes FIN ou DEB qui engendrent des orphelins alors que tous les postes sont à l’écoute.
• Les messages d’erreur du genre 12E engendré par 1:K par exemple. C’est une erreur qui est volontairement générée de façon aléatoire pour vérifier le comportement correct du programme.
• Enfin, que le réseau soit à deux unités ou étendu à trois postes de Travail, de façon épisodique la génération aléatoire va créer un JETON pour une « adresse fantôme » d’une machine qui n’existe pas. Hors il ne servirait à rien de renvoyer dans le réseau cette consigne puisqu’elle sera systématiquement restituée comme retour orphelin.
Pour tous les cas qui viennent d’être listés, il importe d’ignorer ces retours orphelins. Il me semble important de commenter les procédures et les subroutines qui effectuent ce travail.

Travail effectué par la procédure Traiter_un_retour_orphelin.

Associée intimement avec sa complice Empiler_un_JETON(), cette procédure effectue le filtrage des retours qui doivent être ignorés et traite ceux qui seront empilés et dépilés en fonction des circonstances. Nous savons qu’il y a sept cas typiques à filtrer qui ne doivent pas faire l’objet d’un traitement particulier et être occultés. Le premier filtrage effectué en (1) est dans la pratique effectué par un test multiple qui englobe les six premiers cas. La variable A_empiler va servir à trier les JETONs à prendre en compte de ceux à ignorer. Cette variable est forcée à true en début de la procédure Regarde_si_JETON_orphelin_sur_USB(). Il suffit de l’initialiser à false pour tout retour ne devant pas faire l’objet d’un quelconque traitement. Pour tous les cas repérés en (1) la modification de A_empiler se fait en (2). Si ce n’est pas l’un de ces six cas, en (3) on regarde s’il s’agit d’un retour sur Erreur. Dans ce cas on allume la LED triple en rouge pour informer l’opérateur qui dans une entreprise serait chargé de la corriger. Par contre, si l’unité à informé d’une analyse syntaxique erronée, c’est que le poste de Travail concerné n’est pas occupé. Il importe alors en (5) de le valider. C’est la transmission du JETON suivant en (2) de la Fi.139 Page 69 qui éteindra ce témoin lumineux. Dans tous les cas de figure, en (6) on teste pour savoir si le retour orphelin résulte de la transmission d’un JETON aléatoire vers une adresse qui n’existe pas. Elle sera déterminée et égale à Nb_postes_de_Travail plus une unité. Si le retour est relatif à un orphelin qu’il convient de ne pas prendre en compte, en (7), si l’on est en mode manuel, le texte « JETON ignoré. » est affiché sur la ligne USB. Si suite à tous les filtrages qui précèdent le booléen A_empiler a conservé en (8) sa valeur true, alors c’est en (9) que va se traiter la mise en attente du retour orphelin dans le registre mémoire PILE_Orphelins[9].

Structure d’Empiler_un_JETON.

L’organigramme de la Fig.142 est trompeur, car comportant peu d’éléments il masque l’importance de cette procédure qui en développement à engendré pas mal de difficulté et une sérieuse remise en cause avec changement de stratégie. Initialement, cette mémoire d’attente était conçue comme un registre à décalage du type FIFO. Cette approche s’est avérée nocive, car la mémorisation et l’extraction des JETONs doit se faire de façon aléatoire. Aussi, comme déjà abordé en Page 62 le registre d’attente prend la structure d’une simple mémoire RAM à accès totalement libre. Chaque fois que l’on empile, le nombre de postes de Travail à l’écoute diminue en (10), et Nb_valides doit être mis à jour. Un_sur_deux est également forcé à false pour ne pas dépiler l’orphelin immédiatement, mais intercaler un nouveau JETON. Puis en (11) on procède à la mise en mémoire et naturellement, en (12) l’unité concernée n’est plus à l’écoute et doit être invalidée. Éventuellement, en mode développement, (Mode manuel.) en (13) ont affiche l’état actuel du registre d’attente sur le Moniteur.

La suite est ICI.