jeudi 19 mars 2020

Serveur ESP32 : implémentation (2ème partie)



Serveur ESP32 : implémentation

(2ème partie)



Ceci est la suite de l'article précédent :
Serveur ESP32 : implémentation

Nous allons ajouter quelques petites facilités à notre serveur :
  • un lien permettant d'afficher les informations du serveur
    • titre
    • auteur
    • site WEB de l'auteur
    • version du serveur
  • une possibilité de rechercher un abonné :
    • par son identifiant
    • par son nom
  • un dictionnaire pour les variables de la template
    Cette évolution ne concerne que la version SPIFFS avec templates. Il me serait en effet difficile de maintenir 3 versions simultanément.
Il est parfaitement possible d'avoir une notion de template en utilisant des fichiers HTML codés en dur (voir versions USE_SPRINTF et USE_STRING de l'article précédent), mais il faudra ajouter la fonctionnalité soi-même.
Je l'ai déjà réalisé ici : un-web-server-sur-ethernet

1. Informations du serveur

Ces information sont affichées par la fonction JAVASCRIPT alert() :

function about() {
  var message = document.getElementById("title").value;
  message += "\r\n\r\nAuthor: ";
  message += document.getElementById("author").value;
  message += "\r\nWebSite: ";
  message += document.getElementById("website").value;
  message += "\r\nVersion: ";
  message += document.getElementById("version").value;
  alert(message);
};


Que sont ces nouveaux objets "title", "author", "website" et "version" ?
Ce sont des objets cachés dans la page HTML :

<input id="title" name="title" type="hidden" value="%PLACEHOLDER TITLE%">
<input id="author" name="author" type="hidden" value="%PLACEHOLDER AUTHOR%">
<input id="website" name="website" type="hidden" value="%PLACEHOLDER WEBSITE%">
<input id="version" name="version" type="hidden" value="%PLACEHOLDER VERSION%">


Ces objets cachés ont l'attribut hidden et ne sont pas visibles dans le navigateur.
Elles sont renseignées par le même mécanisme de variables templates décrit dans l'article précédent.

Les informations sont affichées lorsque l'on clique sur le lien "About ..." en bas de page :

<a href="#null" onclick="javascript:about();">About ...</a>


Comme on le voit la version est 1.1. En effet il aurait été malvenu de choisir 1.0 étant donné que la version 1.0 était la précédente.
La gestion de version est une notion qu'il ne faut pas négliger.

2. Rechercher un abonné

Deux liens hypertexte ... ont été ajoutés en face des champs "identifiant de l'abonné" et "nom de l'abonné" :


Il suffit maintenant d'entrer l'identifiant ou le nom de l'abonné et de cliquer sur les 3 points pour que la page affiche les informations de l'abonné.
Si l'abonné n'existe pas le status affiché est : Subscriber is UNKNOWN !!!

Comme pour le bouton N° d'abonné cette nouvelle fonctionnalité est réalisée en JAVASCRIPT :

<a href=javascript:void(0); onclick=idChanged()>...</a>
<a href=javascript:void(0); onclick=nameChanged()>...</a>

function idChanged(value) {
  var id = document.getElementById("subscriber_id").value;
  document.location ="/?id=" + id;
};
function nameChanged(value) {
  var name = document.getElementById("subscriber_name").value;
  document.location ="/?name=" + name;
};


Les deux arguments id et name seront interprétés par la fonction handleRoot de l'ESP32 :

    if (request->hasParam("id", false)) {
      const char *s = request->arg("id").c_str();
      uint32_t id;
      sscanf(s, "%lx", &id);
      subscriberIndex = Subscriber::fromId(id);
    }
    if (request->hasParam("name", false)) {
      subscriberIndex = Subscriber::fromName(request->arg("name").c_str());
    }


fromId() et fromName() sont deux méthodes de la classe Subscriber permettant de faire une recherche dans la liste des abonnés.

Il est à noter que l'identifiant de l'abonné est affiché maintenant en hexadécimal.
En effet c'est souvent avec cette notation que l'on affiche un N° de carte. S'il s'agissait d'un autre média, comme une carte à code barre, on pourrait adopter un autre format.

3. Le dictionnaire

Auparavant nous avions 9 variables à afficher dans la page. On passe à 13 (dont 4 cachées).

On ne peut décemment pas passer 13 variables à une fonction. cela devient très vite lourd, et il est rare que cela n'augmente pas.

J'ai donc ajouté une liste de variables (un dictionnaire composé de couples de chaînes nom + valeur).
Voici l'implémentation :
template.h
template.cpp

Elle s'appuie sur une liste standard de la librairie C++ STL (Standard Template Library). Cette librairie est très utilisée en développement C++.

Chaque entrée du dictionnaire est une instance de la classe DictionaryEntry, contenant un nom et une valeur.

Avant d'appeler la fonction qui va envoyer la réponse, l'application enregistre chaque variables à afficher :

  clearDictionary();
  addToDictionary("DATE", timeString);

  addToDictionary("SUBSCRIBER", subscriberIndex);
  // etc 

  addToDictionary("VERSION", version);
  SendSubscribersForm(request);
 

Le dictionnaire est vidé à chaque page par clearDictionary().

Ensuite la fonction responsable de la traduction des variables (PLACEHOLDERS) pour la template, lorsqu'elle est appelée, recherche le nom de la variable dans le dictionnaire :

String templateProcessor(const String& var)
{
  return getDictionaryValue(var.substring(strlen("PLACEHOLDER ")).c_str());
}


Le mot PLACEHOLDER ne fait pas partie du nom enregistré dans le dictionnaire. Si dans le fichier HTML on a :

%PLACEHOLDER DATE%

Dans le dictionnaire seule la variable nommée "DATE" est enregistrée. Il serait inutile d'enregistrer le nom complet "PLACEHOLDER DATE" puisque le premier mot est constant. Donc il suffit de rechercher le mot suivant, "DATE".

Si l'on revient à la version précédente de la fonction templateProcessor() :

String templateProcessor(const String& var)
{
  if (var == "PLACEHOLDER DATE") {
    return var_timeString;
  }
  else if (var == "PLACEHOLDER SUBSCRIBER") {
    return String(var_subscriberIndex);
  }
  else if (var == "PLACEHOLDER NSUBSCRIBERS") {
    return String(var_totalSubscribers);
  }
  else if (var == "PLACEHOLDER SUBSCRIBER_ID") {
    return String(var_subscriberId);
  }
  else if (var == "PLACEHOLDER SUBSCRIBER_NAME") {
    return var_subscriberName;
  }
  else if (var == "PLACEHOLDER SUBSCRIBER_CREDIT") {
    return String(var_credit);
  }
  else if (var == "PLACEHOLDER SUBSCRIBER_HISTORY") {
    return var_history;
  }
  else if (var == "PLACEHOLDER STATUS") {
    return var_status;
  }
  else if (var == "PLACEHOLDER STATUS_COLOR") {
    return var_statusColor;
  }
  return "?????";
}


Cela n'a plus grand chose à voir.

4. Téléchargement

Cette version 1.1 est disponible ici :
https://bitbucket.org/henri_bachetti/webserver-form/src/v1.1/esp32-subscriber/

5. Liens utiles

La suite :
Serveur ESP32 : implémentation (3eme-partie)
Serveur ESP32 : implémentation (4eme-partie)
Serveur ESP32 : implémentation (5eme-partie)
Serveur ESP32 : tests automatisés
Serveur ESP32 : tests automatisés (2ème partie)
Serveur ESP32 : implémentation (6eme-partie)

6. Conclusion

Pour cette évolution j'ai cherché avant tout à ne pas trop compliquer les choses avec trop de JAVASCRIPT. Le CSS est d'ailleurs absent jusqu'à présent.
Le fichier HTML reste assez simple :
https://bitbucket.org/henri_bachetti/webserver-form/src/master/esp32-subscriber/data/index.html

La version précédente :
https://bitbucket.org/henri_bachetti/webserver-form/src/v1.0/esp32-subscriber/data/index.html


Cordialement
Henri

Aucun commentaire:

Enregistrer un commentaire