Mise en place d'automatisations au fablab

Utilisation de la plateforme M5Stack poour développer des solutions d'automatisation de l'enregistrement/l'emprunt de matériel/l'utilisation de machines dans le FabLab

Présentation et mise en place de l'environnement de développement

présentation des objectifs et desccription des librairies, initialisation de TimeTonic et mise en place de l'environnement de développement

Présentation et mise en place de l'environnement de développement

Objectifs

Dans le cadre de l’amélioration des processus au sein du fablab, un projet d’automatisation a été initié afin de moderniser et de simplifier la gestion des accès et des ressources. Ce projet s’articule autour de plusieurs objectifs principaux :

Automatisation de l’enregistrement via la carte étudiante
L’un des axes majeurs du projet consiste à automatiser l’enregistrement des utilisateurs grâce à leur carte étudiante. Cette solution vise à remplacer les méthodes manuelles d’identification par un système de scan rapide et sécurisé, facilitant ainsi l’accès au fablab tout en renforçant la traçabilité des entrées.

Création d’une base de données centralisée et complète
Le projet prévoit la mise en place d’une base de données exhaustive sur Timetonic. Celle-ci regroupera l’ensemble des enregistrements, des emprunts de matériel et des utilisations de machines. L’objectif est de disposer d’un historique fiable et consultable, permettant d’optimiser la gestion des équipements et d’assurer un suivi précis des activités.

Refonte du mode de gestion des emprunts et des utilisations
Le fonctionnement des emprunts et de l’utilisation des machines sera entièrement revu. Désormais, toutes les opérations passeront par le scan de la carte étudiante, supprimant la nécessité de solliciter les emplois étudiants pour valider les demandes. Ce nouveau mode opératoire vise à fluidifier les procédures, à réduire les délais et à responsabiliser les utilisateurs.

En résumé, ce projet d’automatisation s’inscrit dans une démarche d’innovation et d’efficacité, en s’appuyant sur des technologies modernes pour améliorer l’expérience des usagers et la gestion quotidienne du fablab.

Présentation et mise en place de l'environnement de développement

Présentation de TimeTonic

TimeTonic est une plateforme collaborative no-code, conçue pour centraliser, organiser et automatiser la gestion de données, de projets et de processus métier. Flexible et visuelle, elle s’adresse aussi bien aux petites équipes qu’aux grandes entreprises, permettant de créer rapidement des applications métiers personnalisées sans compétences en programmation.

Fonctionnalités principales

Avantages de TimeTonic

Automatisation des processus

TimeTonic intègre un moteur d’automatisation puissant permettant de déclencher des actions dès qu’un événement se produit dans la base de données :

Communication et intégration avec d’autres outils (API)

TimeTonic propose une API complète, permettant d’intégrer la plateforme à d’autres applications ou systèmes d’information :


En résumé, TimeTonic se distingue par sa capacité à centraliser l’information, à automatiser les tâches répétitives et à communiquer facilement avec l’ensemble de l’écosystème numérique de l’entreprise. C’est un véritable atelier numérique collaboratif, personnalisable et évolutif, qui permet de gagner en efficacité, en transparence et en réactivité

Présentation et mise en place de l'environnement de développement

Présentation M5Stack

Dans le cadre de ce projet, nous utilisons la plateforme de développement M5Stack, et plus précisément le module M5Stack Basic associé à un module RFID I2C. Cette combinaison permet de réaliser rapidement des prototypes embarquant des fonctionnalités de lecture de badges RFID. M5Stack reprend tous les codes de développement d'Arduino, comme son language (C++), et est notamment compatible avec une grande partie de ses librairies.

1. La plateforme M5Stack

La M5Stack est une solution de développement modulaire dédiée à l’IoT (Internet of Things). Elle se distingue par sa facilité d’utilisation, son aspect compact et sa capacité à empiler différents modules pour ajouter des fonctionnalités selon les besoins du projet.

Principaux atouts :

2. Le M5Stack Basic

Le M5Stack Basic est le modèle d’entrée de gamme de la série. Il est particulièrement adapté à l’apprentissage, au prototypage rapide et au développement de solutions embarquées.

Caractéristiques principales :

Le M5Stack Basic est donc une base idéale pour développer des applications connectées et interactives.

3. Le module RFID I2C (MFRC522)

Pour ajouter la fonctionnalité de lecture de badges RFID, nous utilisons un module RFID basé sur la puce MFRC522, qui communique avec le M5Stack via le protocole I2C.

Caractéristiques du module RFID :

Intégration :


Cette combinaison d’outils permet de disposer d’une plateforme puissante, flexible et facile à mettre en œuvre pour des projets impliquant la lecture de badges RFID et le développement de solutions IoT.

Présentation et mise en place de l'environnement de développement

Mise en place de plateformeIO

Présentation de PlatformIO

PlatformIO est un environnement de développement intégré (IDE) moderne et multiplateforme, spécifiquement conçu pour le développement de logiciels embarqués. Il permet de programmer une grande variété de microcontrôleurs et de cartes, en offrant une gestion avancée des bibliothèques, de la compilation et du déploiement, tout en restant open source et sans verrouillage propriétaire.

Avantages de PlatformIO

Intégration dans Visual Studio Code (VS Code)

PlatformIO s’intègre parfaitement à Visual Studio Code (VS Code), l’éditeur de code de Microsoft. L’extension PlatformIO IDE pour VS Code transforme ce dernier en un environnement puissant pour le développement embarqué.

Installation de PlatformIO dans VS Code

  1. Installer VS Code : Téléchargez et installez Visual Studio Code depuis le site officiel.

  2. Installer l’extension PlatformIO IDE :

    • Ouvrez VS Code.

    • Allez dans l’onglet Extensions (Ctrl+Shift+X).

    • Recherchez “PlatformIO IDE” et cliquez sur “Installer”.

  3. Redémarrer VS Code si nécessaire pour activer l’extension.

Une fois installée, l’icône PlatformIO apparaît dans la barre latérale de VS Code, donnant accès à toutes les fonctionnalités de gestion de projets, compilation, upload et monitoring série.

Configuration pour développer sur M5Stack Basic

Le M5Stack Basic repose sur un microcontrôleur ESP32. Pour le programmer avec PlatformIO, il suffit de créer un nouveau projet en sélectionnant la carte appropriée et d’ajouter les bibliothèques nécessaires.

Étapes de configuration

  1. Créer un nouveau projet PlatformIO :

    • Cliquez sur l’icône PlatformIO dans VS Code.

    • Sélectionnez “New Project”.

    • Donnez un nom au projet (ici FabLab stage).

    • Choisissez la carte : recherchez et sélectionnez M5Stack Core ESP32 (ID : m5stack-core-esp32).

    • Sélectionnez le framework souhaité (Arduino ou ESP-IDF, par exemple).

    • Validez pour créer le projet.

  2. Configurer le fichier platformio.ini :
    Le fichier platformio.ini est alor configuré automatiquementet contient normalement :

    [env:m5stack-core-esp32] platform = espressif32 board = m5stack-core-esp32 framework = arduino

    Vous pouvez personnaliser d’autres options (fréquence CPU, protocole d’upload, etc.) selon vos besoins. Les bibliothèques ajoutées au porjet via plateformeIO seront automattiquement ajoutées au fichier platformio.ini.

  3. Développer et téléverser votre code :

    • Écrivez votre code dans le dossier src.

    • Utilisez les boutons “Build” (Ctrl+Alt+B) et “Upload” (Ctrl+Alt+U) de PlatformIO pour compiler et téléverser le programme sur le M5Stack Basic.

    • Le moniteur série intégré permet de visualiser les messages envoyés par la carte.


En résumé, PlatformIO, intégré à VS Code, offre un environnement moderne, puissant et flexible pour développer sur M5Stack Basic. Il facilite la gestion des bibliothèques, la compilation, l’upload et le monitoring, tout en permettant une personnalisation avancée et une grande évolutivité pour tous vos projets embarqués.

Présentation et mise en place de l'environnement de développement

Présentation des librairies utilisées

M5Unified

La librairie M5Unified est le cœur du développement sur les appareils M5Stack. Elle offre une interface unifiée pour contrôler la majorité des composants matériels intégrés aux modules M5Stack, comme l’écran LCD, les boutons, le haut-parleur, le microphone, etc. Grâce à cette abstraction, le même code peut fonctionner sur différents modèles de M5Stack sans modification majeure. M5Unified est compatible avec les plateformes Arduino et ESP-IDF, ce qui facilite le développement et améliore la portabilité du code.

Wire

La librairie Wire permet la communication via le bus I2C, un protocole de communication série très utilisé pour connecter des capteurs et modules externes à une carte microcontrôleur. Elle sert notamment à dialoguer avec des périphériques comme le lecteur RFID ou d’autres capteurs branchés sur le port Grove du M5Stack.

WiFi

La librairie WiFi permet de connecter l’ESP32 (présent dans le M5Stack Basic) à un réseau sans fil. Elle offre des fonctions pour scanner les réseaux disponibles, se connecter à un point d’accès, gérer les événements Wi-Fi et obtenir une adresse IP. Elle est essentielle pour tout projet nécessitant une communication réseau, comme l’envoi ou la réception de données sur Internet.

HTTPClient

HTTPClient est une librairie qui facilite la réalisation de requêtes HTTP (GET, POST, etc.) depuis l’ESP32. Elle permet d’interagir facilement avec des serveurs web ou des API (comme ici celui de TimeTonic), d’envoyer des données ou de récupérer des informations à distance. Cette librairie est souvent utilisée en complément de WiFi pour des applications IoT connectées.

MFRC522_I2C

La librairie MFRC522_I2C permet de piloter un module lecteur RFID MFRC522 via le protocole I2C. Elle simplifie la lecture et l’écriture de badges RFID/Mifare en fournissant des fonctions haut niveau pour détecter, lire et écrire sur les cartes. Cette librairie est compatible avec Arduino et ESP32, et nécessite de spécifier l’adresse I2C du module et la broche de reset. Attention toutefois, un certain nombre de librairies porte ce nom et seule celle disponible sur le GitHub de M5Stack fonctionne avec leur capteur RFID.

ArduinoJson

ArduinoJson est une librairie puissante et optimisée pour la manipulation de données JSON sur microcontrôleurs. Elle permet de sérialiser (convertir des objets en texte JSON) et de désérialiser (analyser du texte JSON pour en extraire des données) facilement, ce qui est très utile pour échanger des données structurées avec des serveurs web ou des API (cellui de TimeTonic utilise principalement des objets JSON pour recevoir/envoyer des données). Elle gère les objets, les tableaux, les filtres et l’optimisation mémoire, ce qui la rend idéale pour les projets embarqués.


Résumé des rôles

Librairie Rôle principal
M5Unified Contrôle du matériel M5Stack (écran, boutons, haut-parleur, etc.)
Wire Communication I2C avec les modules externes
WiFi Connexion réseau sans fil et gestion des événements Wi-Fi
HTTPClient Envoi et réception de requêtes HTTP vers/depuis des serveurs web
MFRC522_I2C Lecture/écriture de badges RFID via le module MFRC522 en I2C
ArduinoJson Manipulation et traitement de données JSON (sérialisation/désérialisation)


L’utilisation combinée de ces librairies permet de gérer efficacement le matériel, de communiquer avec des serveurs distants et de traiter des données structurées, couvrant ainsi l’ensemble des besoins fonctionnels du projet.

Premier prototype et preuve de concept

mise en place d'un exemple simple permettant la lecture de cartes RFID et la communication entre le M5Stack et l'API de TimeTonic.

Premier prototype et preuve de concept

Lecture de carte RFID

1. Connexion matérielle

Le module RFID MFRC522 se connecte au port GROVE A du M5Stack Basic, qui correspond aux broches I2C (SDA sur GPIO21, SCL sur GPIO22). L’adresse I2C par défaut du module est 0x28.


2. Initialisation logicielle

Il faut utiliser la bibliothèque MFRC522_I2C pour piloter le lecteur RFID, ainsi que les bibliothèques Wire (I2C) et M5Unified (pour gérer l’écran et l’initialisation du M5Stack).

L’initialisation consiste à :


3. Lecture du UID

Dans la boucle principale du programme, il s’agit de :


4. Fonction de conversation hexadécimale

Le capteur RFID renvoie les données lues de la carte dans un tableau sous forme de bits bruts. Il faut donc convertir ces données en une chaine de charactères hexadécimaux :

String uidhex(MFRC522 &rfid){
    String uidStr;
    for (byte i = 0; i < rfid.uid.size; i++) {
        if (rfid.uid.uidByte[i] < 0x10) uidStr += "0";
        uidStr += String(rfid.uid.uidByte[i], HEX);
        if (i < rfid.uid.size - 1) uidStr += ":";
    }
    return uidStr;
}

Ce code renvoie une chaine de charactères contenant le numéro de série de la carte lue au format standard, c'est à dire : XX:XX:XX:XX ... où X est un caractère hexadécimal.

5. Exemple de code

#include <M5Unified.h>
#include <Wire.h>
#include "MFRC522_I2C.h"

MFRC522 mfrc522(0x28);  // Adresse I2C du module RFID

void setup() {
    M5.begin();
    Wire.begin();
    mfrc522.PCD_Init();
    M5.Display.setTextSize(2);
    M5.Display.println("Presentez une carte");
}

void loop() {
    if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
        String uid = uidhex(mfrc522);
        M5.Display.print("UID : ");
        M5.Display.println("uid");)
    }
    M5.delay(2000);
    M5.Display.fillRect(0, 60, 320, 240, BLACK);
}

Ce code affiche le UID de chaque carte RFID présentée devant le lecteur sur l’écran du M5Stack.


5. Résumé du fonctionnement

Cette méthode est fiable pour des applications telles que le contrôle d’accès, la gestion de présence ou l’inventaire.

Premier prototype et preuve de concept

Communication avec l'API de TimeTonic

Pour permettre au M5Stack de communiquer avec l’API de TimeTonic, il faut exploiter les capacités réseau du M5Stack (via l’ESP32), utiliser les librairies WiFi et HTTPClient, et structurer les requêtes selon les spécifications de l’API TimeTonic.


1. Préparer l’accès à l’API TimeTonic

L’API TimeTonic permet d’accéder, de lire et de modifier les données de vos espaces de travail à distance. Pour chaque requête, il est nécessaire de transmettre un sesskey (clé d’API/session), associé à votre compte utilisateur. Cette clé s’obtient via l’interface TimeTonic et doit être gardée confidentielle (elle ne sera donc publiée ici, si vous copiez l'exemple de code, pensez bien à mettre la votre).

Il est aussi important de repérer dès maintenant où trouver les différents codes permettant d'identifier les books, tables, lignes et colonnes dans TimeTonic :

Book ID : nom de l'espace de travail (attention, si celui-ci a été renommé, il gardera son 1er nom en ID, en cas de doute vérifier dans les paramètres du book dans la catégorie workspace informations).

Table ID : code à 6 chiffres accessible en cliquant sur les 3 points verticaux à droite de la fenêtre lorsque vous visualiser la table, puis en cliquant sur organize fields. L'ID sera entre parenthèse en haut de la fenêtre qui apparait.

Field ID : code à 6 chiffres accessible dans la même fenêtre que pour Table ID, sous la catégorie éponyme.

Row ID : correspond simplement au numéro de la ligne. Lorsqu'on voudra en créer une nouvelle en fin de tableau, on utilisera le code tmpNEW_ROW.


2. Interaction avec l'API

Lors du développement, il existe plusieurs manière d'interagir avec l'API de TimeTonic :

2. Exemple de requête : getAllBooks

La méthode getAllBooks permet de récupérer la liste de tous les « books » (espaces de travail) auxquels l’utilisateur a accès. Pour connaitre l'étendu des possibilité de l'API de TimeTonic, je vous renvois vers la documentation de celui-ci. La requête doit être envoyée en POST à l’URL suivante :

https://timetonic.com/live/api.php

Les paramètres à inclure sont :

  • version : version de l’API (ex : "6.20b") (optionnel)

  • req : "getAllBooks"

  • o_u : identifiant utilisateur (doit correspondre à celui du sesskey)

  • u_c : identifiant utilisateur (idem)

  • sesskey : votre clé d’API/session, qui peut être créée dans les paramètres de votre compte TimeTonic


3. Implémentation sur M5Stack (Arduino)

Voici comment structurer le code avec les librairies WiFi, HTTPClient et ArduinoJson :

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "fablabstaff";
const char* password = "xxxxxxxxx"; //Pensez à remplacer le SSID et le mot de passe par vos paramètres WiFi

HTTPClient http;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connecte au WiFi");

  http.begin("https://timetonic.com/live/api.php");
  String postData = "req=getAllBooks"
                    "&o_u=USER"// Remplacez bien USER par votre nom d'utilisateur TimeTonic
                    "&u_c=USER"
                    "&sesskey=xxxxxxxxxxxxxxxxxxxxxxxxxx"; // Remplacez par votre sesskey
  int httpResponseCode = http.POST(postData);

  if (httpResponseCode > 0) {
    String reponse = http.getString();
    Serial.println("Réponse API :");
    Serial.println(reponse);

    // Traitement JSON (exemple)
    DynamicJsonDocument doc(4096);
    deserializeJson(doc, reponse);
    if (doc["status"] == "ok") {
      JsonArray books = doc["allBooks"];
      for (JsonObject book : books) {
        Serial.println(book["b_c"].as<String>()); // Affiche le code du book
      }
    }
  }
  else {
    Serial.print("Erreur HTTP : ");
    Serial.println(httpResponseCode);
  }
  http.end();
}


void loop() {
  // Rien ici pour cet exemple
}

Ce code permet de récupérer les informatiosn de tous les espaces de travail présents dans un compte TimeTonic.

4. Points importants

  • Connexion sécurisée : L’API TimeTonic nécessite une connexion HTTPS, ce qui est supporté par l’ESP32.

  • Format POST : Les paramètres doivent être envoyés en POST, au format application/x-www-form-urlencoded23.

  • Traitement de la réponse : La réponse de l’API est en JSON, d’où l’utilisation de la librairie ArduinoJson pour extraire les informations utiles.

  • Gestion des erreurs : Toujours vérifier le code de retour HTTP et le champ status dans la réponse JSON.


5. Résumé

Pour communiquer avec l’API de TimeTonic depuis un M5Stack, il faut :

  • Se connecter au WiFi,

  • Construire une requête POST avec les bons paramètres,

  • Envoyer la requête à l’API,

  • Traiter la réponse JSON pour exploiter les données reçues.

Ce principe peut être adapté à toutes les autres méthodes de l’API TimeTonic, en changeant simplement le paramètre req et les paramètres associés.

Premier prototype et preuve de concept

Lecture et écriture sur TimeTonic

Maintenant que nous pouvons communiquer avec l'API TimeTonic via le M5Stack, il faut savoir utiliser les principales requêtes permettant de lire, créer et modifier les données contenues dans un book (espace de travail). Voici les étapes principales, avec le détail des fonctions API à utiliser et des exemples de structure de requête.


1. Lire les données d’une smart table

Pour récupérer le contenu d’une smart table, il faut utiliser la requête getTableValues. Cette requête retourne les lignes (rows) et les valeurs des champs (fields) d’une table donnée.

Paramètres nécessaires :

  • req : "getTableValues"

  • o_u et u_c : identifiants utilisateur

  • sesskey : clé de session API

  • b_c : code du book (carnet)

  • catCode : code de la table (catégorie)

Exemple de requête POST :

req=getTableValues&o_u=USER_ID&u_c=USER_ID&sesskey=SESSION_KEY&b_c=BOOK_CODE&catCode=TABLE_CODE

En version formatée pour le code C précédemment utilisé :

"req=getTableValues"
"&b_c=BOOK_CODE"
"&catCode=TABLE_CODE"
"&o_u=USER_ID"
"&u_c=USER_ID"
"&sesskey=SESSION_KEY"

La réponse contiendra un tableau JSON avec toutes les lignes et les valeurs des champs pour chaque ligne. Pour pouvoir exploiter ces données dans le code C, il faut utiliser un parseur, qui permet d'identifier et d'isoler chaque donnée lue.


2. Filtrage des données lues

Pour ne pas récupérer toutes les données de la table à chaque requête, on peut utiliser deux arguments dans celle-ci : 

Par exemple :

&fieldIds = [7457220, 7457221]

Où 7457220 et 7457221 sont les IDs des champs que je veux récupérer.

Par exemple :

&filterRowIds={"applyViewFilters": 1181354}

Où 1181354 est l'ID de la vue que je souhaite utiliser. Pour récupérer cet ID, il faut inspecter la page lorsque vous êtes sur la vue qui vous intéresse, puis cliquer sur l'onglet "network". Dans les filtres en haut, sélectionner "Fetch/XHR" puis rafraichisser la page. Dans les fichiers qui se chargent alors, sélectionner newDashboard?getUtilisateur et défiler jusqu'à la section Request Headers. Dans celle-ci, trouvez la ligne Referer, elle contient en regard un lien terminant par /view/Un numéro. Ce numéro est l'ID de votre vue.

ATTENTION : le view ID peut maintenant être directement récupéré dans l'URL de la page : sélectionnez la vue souhaitée puis copiez le numéro après /view/ , il 'sagit du viewId.

Pour construire une vue avec un objet JSON, la manoeuvre est beaucoup plus compliquée : il faut remplacer l'ID de vue par un objet JSON avec une syntaxe particulière :

Voici un exemple d'objet JSON à mettre après "applyViewFilters": :

{
    "filterGroup": {
        "operator": "and",
        "id": "tmpId",
        "filters": [
            {
                "field_id": 7457220,
                "json": {
                    "predicate": "contains",
                    "operand": "ABC"
                }
            },
            {
                "field_id": 7457221,
                "json": {
                    "predicate": "is",
                    "operand": "abc"
                }
            }
        ]
    }
}

NB : "filterGroup" (nom de l'objet JSON), "filters" (tableau JSON contenant les différents filtres) et "json"(objet JSON contenant les arguments de filtrage) sont des éléments statiques mais nécessaires de la syntaxe. toute erreur dans la syntaxe entrainera une réponse valide mais ne contenant aucune donnée de la table interrogée ("rowInfosLength": 0 dans la réponse).


3. Écrire des données dans une smart table

L’ajout ou la modification de données dans une smart table se fait avec la requête createOrUpdateTableRow. Pour modifier une ligne, il suffit d’indiquer l’identifiant de la ligne (rowId=ROW_ID_EXISTANTou rowId=tmpNEW_ROW) et de fournir les nouveaux champs à modifier dans fieldValues.

Paramètres nécessaires :

  • req : "createOrUpdateTableRow"

  • o_u et u_c : identifiants utilisateur

  • sesskey : clé de session API

  • b_c : code du book (carnet)

  • catCode : code de la table (catégorie)

  • fieldValues : données à écrire. celles-ci doivent être sous la forme d'un objet JSON avec la syntaxe suivante :
{
	"field ID": "Value",
	"field ID 2": "Value 2",
	"field ID 3": "Value 3"
	}

Exemple de requête POST:

req=createOrUpdateTableRow&o_u=USER_ID&u_c=USER_ID&sesskey=SESSION_KEY&b_c=BOOK_CODE&catCode=TABLE_CODE&rowId=ROW_ID_EXISTANT&fieldValues={"FIELD_ID1":"NouvelleValeur"}

En version formatée pour le code C (bien noter les antislashs avant les guillemets contenus dans fieldValues : ils permettent de les considérer comme des caractères normaux sans interférer avec les balises de Strings):

"req=createOrUpdateTableRow"
"&o_u=USER_ID"
"&u_c=USER_ID"
"&sesskey=SESSION_KEY"
"&b_c=BOOK_CODE"
"&catCode=TABLE_CODE"
"&rowId=ROW_ID"
"&fieldValues={\"FIELD_ID\":\"NouvelleValeur\"}"

Seuls les champs à modifier doivent être précisés dans fieldValues.


4. Récupérer les identifiants nécessaires

Si les données que vous lisez/écrivez sont toujours au même endroit, vous pouvez manuellement regarder les IDs de chaque champ et les copier dans votre code. Cependant, si vous voulez écrire des données à des endroits dépendant de certains champs/valeurs, vous pouvez obtenir les IDs pertinents via les requêtes getAllBooks (pour les books) et getBookTables (pour les tables et champs). Avant de pouvoir lire ou écrire, il est indispensable de connaître :

  • Le code du book (b_c)

  • Le code de la table (catCode)

  • Les identifiants des champs (fieldID1, fieldID2, etc.)

  • L’identifiant de la ligne, si modification (rowId)


5. Résumé des étapes

  1. Authentification : Obtenir un sesskey via l’API.

  2. Lister les tables : Utiliser getAllBooks puis getBookTables pour identifier le book et la table cible si nécessaire.

  3. Lire des données : Utiliser getTableValues pour obtenir les lignes et champs.

  4. Écrire des données : Utiliser createOrUpdateTableRow avec rowId=tmpNEW_ROW si vous voulez créer une nouvelle ligne.


6. Bonnes pratiques

  • Utiliser systématiquement la méthode POST pour transmettre les paramètres.

  • Manipuler les objets JSON avec soin pour le paramètre fieldValues, et utiliser un parseur pour pouvoir utiliser les données lues.

  • Toujours vérifier le champ status dans la réponse de l’API pour s’assurer du succès de l’opération (le code de succès 200 indique simplement que la requête est parvenue à l'API, pas nécessairement qu'elle a été correctement exécutée).


En résumé, la lecture et l’écriture dans une smart table TimeTonic via l’API sont simples, mais nécessites une grande attention aux détails : il faut bien identifier les bons paramètres (book, table, champs), utiliser les requêtes appropriées, et les structurer correctement afin de traiter ou d'envoyer les données correctement.

Création d'une bibliothèque uniformisée : M5lib

Conception et codage d'une bibliothèque commune à tous les M5Stack déployés dans le FabLab afin de rendre le déploiement, la maintenance et l'évolution plus simples et efficaces. Du fait sa relative complexité, il n'est pas garanti qu'elle fonctionne sur les M5Stack Core 1 (elle est optimisée pour les Core 2).

Création d'une bibliothèque uniformisée : M5lib

Présentation

Présentation Générale

La bibliothèque M5lib vise à uniformiser la gestion d’une flotte de M5 Core2 au sein d’un FabLab, facilitant le déploiement, l’évolution et la maintenance. Sa structure repose sur des concepts avancés de programmation orientée objet : factory design pattern et polymorphisme.  

Factory Design Pattern dans M5lib

Structure de Base

Objectif du Pattern

Le factory design pattern permet d’instancier dynamiquement le bon type d’objet dérivé (accueilservante, etc.) en fonction du contexte (par exemple, d’un paramètre de configuration ou d’une saisie utilisateur), tout en manipulant leur interface commune à travers des pointeurs ou références de type M5lib. Dans ce cas, cela veut dire que la déclaration du type d'objet dérivé dans le firmware du M5 permet automatiquement et de manière transparente d'adapter toutes les fonctions nécessaires au comportement de ce type de M5 (requêtes d'API, type d'emprunt...).

Avantages

Polymorphisme dans M5lib

Implémentation

Usage

Limites et inconvénients

Cette flexibilité du code ne vient pas sans compromis :

Création d'une bibliothèque uniformisée : M5lib

Structure

Dépendances

La librairie fait appel à de nombreuses librairies :

Structure de code

La bibliothèque M5lib est conçue pour uniformiser le comportement de plusieurs dispositifs M5Stack Core2 dans l'environnement du FabLab, chacun jouant un rôle défini (accueil, servante, machine, etc.). Elle repose sur une architecture orientée objet claire et modulaire, facilitant l’évolution, la maintenance et l'intégration au back-end (TimeTonic).

Structure de la Bibliothèque M5lib

1. Classe de base abstraite : M5lib

  • Représente l’interface commune à tous les types de M5.

  • Contient les méthodes de base utilisées par tous les modules : lecture de carte RFID (scancard), scan UHF (scanuhf), interaction utilisateur (showchoice, getuser), etc.

  • Déclare des méthodes virtuelles pures (polymorphisme) à implémenter dans les classes dérivées : uploadlog() et changestatus().

2. Classes dérivées spécialisées

Chaque type de M5 (défini dans M5type) possède une classe dédiée, dérivée de M5lib :

Classe Hérite de Spécificités
accueil M5lib Méthodes supplémentaires : entree(), sortie(), regcard().
Menu de motifs de visite.
servante M5lib Gère la traçabilité des servantes utilisées.
machine M5lib Pour l'enregistrement d’utilisation de machines.
ordinateur M5lib Associe cartes/scans à une session ordinateur précise.
materiel M5lib Permet le prêt/retour d’outils ou matériels via borrow().

Chaque classe surcharge au moins :

  • uploadlog: envoie les journaux d’usage à l’API TimeTonic avec une structure propre (identifiants de champs différents selon le type).

  • changestatus: placeholder actuel (pour la plupart renvoie 200) servant potentiellement à signaler un changement d’état matériel (ex : verrouillage machine, etc.).

3. Composants globaux manipulés

  • Périphériques :

    • MFRC522 mfrc522 : pour la lecture RFID classique (Mifare).

    • Unit_UHF_RFID uhf : pour les lectures UHF/EPC.

  • API & Données :

    • HTTPClient http : communication HTTP avec TimeTonic.

    • JsonDocument doc : stockage de la réponse JSON.

  • Accès réseau :

    • Configuration du Wi-Fi intégrée dans setupstd().

Résumé Visuel Simplifié

        +---------------------------+
        |           M5lib          |  <--- classe abstraite
        +---------------------------+
    /        |        |       |         \
   /         |        |       |          \
accueil   servante  machine ordinateur  materiel  <--- classes concrètes

Toutes implémentent :
    + uploadlog()
    + changestatus()

Chaque classe possède des méthodes propres, par exemple :
accueil fournit aussi :
    + entree()
    + sortie()
    + regcard()

Une évolution fluide : il suffit d’ajouter une nouvelle classe dérivée et d’enrichir la factory pour intégrer un nouveau comportement ou un nouveau rôle matériel dans le système du FabLab.

Création d'une bibliothèque uniformisée : M5lib

Structure détaillées

1. Classe Abstraite : M5lib

Classe de base commune à tous les types de M5. Elle définit les fonctionnalités fondamentales.

Fonctions membres

Fonction Rôle
setupstd() Effectue l'initialisation matérielle commune : écran, Wi-Fi, RFID, UHF. Attention : la fonction est lboquante tant que le M5 n'est pas connecté au réseau prédéfinit.
reducejson(String json) Réduit et structure le JSON de réponse de l’API TimeTonic pour simplifier l’accès aux champs utiles. Ne garde que le contenu de "fields" (endroit où est stocké entre autres les données demandées) et "rowInfos" (qui contient notamment le rowId des informations demandées)
scancard() Scanne une carte RFID classique, retourne l’UID du tag sous forme de String. Contient une UI intégrée. Attention : la fonction est bloquante tant qu'elle n'a pas lu une carte.
scanuhf(String* urfid) Scanne les tags RFID UHF via le module UHF externe, remplit le tableau passé en paramètre avec les EPC lues (max 200 EPC, ce qui est le max supporté par le module RFID UHF). Fonction actuellement inutilisée dans le code.
showchoice(String choices[]) Affiche sur l’écran un menu de sélection contenant les String du tableau passé en paramètre  : l’utilisateur peut naviguer puis valider un choix(jusqu’à 9 options), qui est retourné sous forme de String.
virtual int uploadlog(String card, String action, String other) = 0 Méthode virtuelle pure pour uploader un log dans la table correspondante au type de M5. Prend en paramètre une carte lue, l'action effectuée par l'utilisateur et un agument optionnel (au choix, le motif de la visite, l'ordinateur ou l'outil emprunté).
virtual int changestatus() = 0 Méthode virtuelle pure pour changer le statut d'emprunt/de présence (obsolète pour le moment car remplacé par automatisation TimeTonic).
getuser(String* user) Lance un scan RFID (avec scancard() ), puis interroge l’API TimeTonic pour récupérer le nom, prénom, et rowId de l'utilisateur scanné. Peuple ensuite le tableau passé en paramètre : [nom, prénom, tag RFID, rowId].
borrow() Gère tout le cycle d’emprunt et retour d’un matériel/machine/ordinateur : identification (avec un appel getuser() ), log (avec un appel uploadlog() ), et contrôle utilisateur (gestion par l'utilisateur de la durée de son emprunt, avec à nouveau un scan de carte et un upload de log à la fin de l'emprunt. Boucles if/else à chaque étape du cycle pour gérer chaque type d'erreur (API, utilisateur inconnu, etc...).
Attributs

2. Classes Dérivées

Chaque classe dérivée apporte des fonctionnalités propres à chaque typologie de M5 dans le FabLab.

a. Classe : accueil

Ajoute des méthodes spécifiques à la gestion d’accueil.

Fonction Rôle
int uploadlog(...) override Upload des logs d’accueil à l’API avec les bons id (table, champs...).
int changestatus() override Change le statut d’accueil (placeholder : actuellement valeur fixe pour compatibilité).
void entree() Gère la procédure d’entrée : identification (avec getuser), choix du motif de visite (avec showchoice), upload du log d’arrivée (avec uploadlog)
void sortie() Gère la sortie d’un utilisateur (avec getuser) et log cet évènement (avec uploadlog).
void regcard() Enregistre une nouvelle carte RFID (avec un scancard puis une requete d'API spécifique) pour un utilisateur après inscription sur Timetonic (liaison rangée TimeTonic <-> badge RFID). La requête d'API récupère la dernière rangée créée avec une vue filtrée (vue chronologique dans TimeTonic), il faut donc faire l'association de carte immédiatement après l'inscription.
Attributs spécifiques

String motifs[9]: Liste des motifs de visite disponibles à la sélection (préremplie pour plus de simplicité).String name : nom du M5, permet de définir l'action d'accueil effectuée : entrée, sortie ou 1ère inscription.

b. Classe : servante

Pour la traçabilité de l’usage des servantes.

Fonction Rôle
int uploadlog(...) override Upload des logs liés à l’utilisation d’une servante (carte, action, ""). L'argument other ne sert pas pour les servantes.
int changestatus() override Change le statut de la servante (obsolète, pour compatibilité).
Attributs spécifiques

c. Classe : machine

Gère l’utilisation des machines/outils fixes.

Fonction Rôle
int uploadlog(...) override Upload logs liés à l’utilisation d’une machine (carte utilisateur, action).
Attributs spécifiques

d. Classe : ordinateur

Gère le suivi de l'emprunt des ordinateurs portables.

Fonction Rôle
int uploadlog(...) override Upload logs spécifiques à l’usage d’un ordinateur (par exemple : session ouverte/fermée).
Attributs spécifiques

e. Classe : materiel

Gère les cycles d’emprunt et de retour d’outillage ou matériel divers.

Fonction Rôle
int uploadlog(...) override Upload logs liés à l’utilisation (emprunt/retour) de matériels.
Attributs spécifiques

3. Utilisation de méthodes virtual / override

Les méthodes uploadlog et changestatus sont définies comme virtual dans la base, et nécessaires à la personnalisation du comportement selon chaque situation FabLab : chaque classe dérivée implémente les appels API avec les bons identifiants et formats de données.

Avec cette structure, chaque fonction de M5lib remplit un rôle précis dans la gestion, la traçabilité, l’ajout de dispositifs et l’intégration back-end dans l’écosystème du FabLab.

Création d'une bibliothèque uniformisée : M5lib

UI

Afin de simplifier, d'uniformiser et de clarifier l'affichage de texte et de l'interface dans le M5, Une classe UI a été créé. Elle permet de simplifier l'implémentation de l'interface utilisateur dans toutes les fonctions interagissant avec celui-ci.

Structure

Méthodes

showchoice : UI de sélection de choix multiples (anciennement dans M5lib), retourne la String du choix sélectionné
titre : affichage de texte en gros centré (taille 4, 13 charactères maximum avant dépassement de l'écran)
soustitre : affichage de texte en moyen centré (taille 3, 17 charactères maximum)
corps : affichage de texte en  petit centré (taille 2, 26 charactères maximum)
feedback : vibration pour retour utilisateur, à appeler à chaque fois qu'un bouton est pressé

Lecteur de badge comme clavier BT

Lecteur de badge comme clavier BT

Principe

La saisie des numéros longs est fastidieuse : codes barres, numéros de cartes étudiants, etc. doivent pouvoir être "scannés" rapidement pour remplir des formulaires.

Pour les codes barres, la solution est connue et commerciale : il s'agit de "douchettes" laser, comme par exemple la série Honeywell 1470 :

sps-ppr-1470g-barcode-scanner-5.webp

L'appareil est reconnu comme un clavier par l'ordinateur auquel il est connecté. Ainsi, appuyer sur la gachette revient à saisir au clavier les numéros inscrits sur le code barre ou le QR code.

L'idée est de faire la même chose avec un M5Stack équipé d'un lecteur RFID pour saisir les numéros de carte étudiant.

On pourrait alternativement imprimer des codes barres à coller sur les cartes étudiant.

Cette approche est très différente de celle adoptée dans les autres chapitres du projet. Ici, Timetonic ou Fabtrack n'ont pas d'interaction avec le M5 Stack. La douchette ou le lecteur RFID sont -au fond- le prolongement de la main de l'utilisateur qui saisit le code. Dans les autres chapitres, le M5 Stack équipé du lecteur utilise l'API de Timetonic pour déclencher des actions. C'est radicalement différent (et plus complexe).


Lecteur de badge comme clavier BT

Bibliothèques utilisées

Emuler un clavier

Pour pouvoir interagir avec un maximum de dispositifs d'interrogation de Timetonic/Fabtrack, que ce soient des ordinateurs fixes ou des iPads mobiles dans l'espace, le scanner de cartes est sans fil et se connecte en bluetooth BLE.

Une bibliothèque qui permet cela pour les plateformes à base d'ESP32 est disponible ici. (archive)

BleKeyboard.cpp

BleKeyboard.h

La disposition du clavier qui est émulée est celle du clavier QWERTY-US exclusivement ! 

Il faut donc que ce soit le clavier choisi dans l'environnement/OS. Sinon, le résultat peut être surprenant.

Accesoirement, on constate que le clavier bluetooth, même lorsqu'aucune carte n'est transmise, cause des frappes malignes. L'ajout d'un appel à la fonction releaseAll semble résourdre le problème. C'est un point à éclaircir. 

Testé totalement sur macOS.

Sous Windows, le périphérique bluetooth est reconnu, se connecte, transmets correctement nom et niveau de charge batterie, mais aucune donnée ne semble transmise : dans le menu "bluetooth et autres appareils", il n'apparaît pas dans la section claviers/souris mais dans "autres appareils" :

Capture d’écran 2025-07-22 132736.png

Reste à faire : 

Lire les cartes RFID

Pour lire les cartes, on utilise la même bibliothèque ce celle déjà employée par Mathieu de Rooster, qui explique son fonctionnement ici.

MFRC522_I2C.h

MFRC522_I2C.cpp

Lecteur de badge comme clavier BT

Implémentation

Le code ci-dessous permet, en utilisant les bibliothèques précédentes, d'émuler un clavier bluetooth pour envoyer les caractères lus sur une carte RFID.

Le programme comporte :

BleKeyboardExemple.ino


#include <M5Unified.h>
#include "BleKeyboard.h"
#include "MFRC522_I2C.h"

BleKeyboard bleKeyboard("M5CardReader", "M5Stack", 100);
MFRC522 mfrc522(0x28);

void setup() {
  M5.begin();
  Wire.begin();
  Serial.begin(115200);
  bleKeyboard.begin();
  M5.Lcd.println("M5Stack BLE Keyboard");
  mfrc522.PCD_Init();
  M5.Display.setTextSize(2);
  M5.Display.setFont(&fonts::efontCN_12);
  M5.Speaker.begin();
  M5.Speaker.setVolume(50);
}

void loop() {
  M5.update();
  String uid = "";
  M5.Lcd.clear();

  M5.Display.setTextDatum(MC_DATUM);
  M5.Display.setTextSize(3);
  M5.Display.drawString("Présentez", 160, 100);
  M5.Display.drawString("votre carte", 160, 140);

  while (1) {
        M5.Display.setTextSize(1);
        float batLevel = M5.Power.getBatteryLevel();
        M5.Display.drawString("Batterie : " + String(batLevel), 160, 40);
        bleKeyboard.setBatteryLevel(M5.Power.getBatteryLevel());
        if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
            for (byte i = 0; i < mfrc522.uid.size; i++) {
                if (mfrc522.uid.uidByte[i] < 0x10) {
                  uid += "0";
                }
                uid += String(mfrc522.uid.uidByte[i], HEX);
                if (i < mfrc522.uid.size - 1) {
                  uid += ":";
                }
            }
            M5.Lcd.clear();
            int L = uid.length();
            if (L == 20) { 
              M5.Display.setTextSize(3);
              M5.Display.drawString("Carte scannée", 160, 120);
              M5.Speaker.tone(440, 250);  // Frequence Hz, duree ms
              M5.delay(100);
              M5.Speaker.tone(880, 250); 
              //M5.Display.drawString(uid, 160, 120);
              int L = uid.length();
              //M5.Display.drawString(String(L), 160, 160);
              String uidDeb = "";
              String uidFin = "";
              for (int j = 0; j < 10 ; j++) {
                uidDeb += uid[j];
                uidFin += uid[j+10];
              } 
              //M5.Display.drawString(uidDeb, 160, 200);
              //M5.Display.drawString(uidFin, 160, 240);
              bleKeyboard.print(uidDeb);
              M5.delay(100);
              bleKeyboard.print(uidFin);
              M5.delay(2000);
              bleKeyboard.releaseAll();
              break;
            }
            else {
              M5.Display.setTextSize(3);
              M5.Display.drawString("Erreur de lecture", 160, 80);
              M5.Display.drawString("Réessayez svp", 160, 120);
              M5.Speaker.tone(440, 250);  // Frequence Hz, duree ms
              M5.delay(100);
              M5.Speaker.tone(220, 250); 
              M5.delay(2000);
              bleKeyboard.releaseAll();
              break;
            }
        }
  }
}

Réflexions sur l'ergonomie de UI

Réflexions sur l'ergonomie de UI

Etat des lieux

Aujourd'hui, les informations liées à l'accueil et les emprunts sont enregistrées dans un logiciel développé en interne, FabTrack, accessible uniquement aux emplois-étudiants, avec une interface web accessible via deux PC Linux :

IMG_3841.pngIMG_3846.png

Les enregistrements des participants à des ateliers spécifiques fait appel à des formulaires web de style Google Form/Framaform. Enfin, les données liées à l'usage des machines ne sont pas collectées, et seules les informations de maintenance sont notées, sur papier :  

IMG_3842.pngIMG_3844.png

Les objectifs de l'introduction de Timetonic et de la transformation sont multiples :

  1. centraliser les informations, 
  2. unifier la façon de les saisir les informations, pour fiabiliser la collecte.
  3. alléger la charge de travail des emplois étudiants et personnels,
  4. permettre l'extension de la collecte d'information à d'autres situations


Réflexions sur l'ergonomie de UI

Possibilités techniques

Le point d'entrée des utilisateurs (contributeurs) doit être leur identification (simple, sans authentification). Pour cela, il existe plusieurs possibilités : 

L'interface sur laquelle se poursuite la saisie peut être : 

Toutes les combinaisons ne sont pas possible, ni cohérentes : par exemple, le téléphone peut scanner un QR code, mais on ne peut pas équiper tout le monde de lecteur de badge RFID.

On peut donc envisager essentiellement trois combinaisons : 

Côté imprimantes, l'ajout d'un SBC doté d'Octoprint pour récupérer les informations de l'impression est envisagé. Rien n'empêche d'y connecter un lecteur RFID et un verrou électronique. Le processus devient alors :  l'utilisateur entre dans la pièce, prépare son fichier sur le PC local, utilise la clé USB locale, déverrouille l'imprimante avec son badge RFID, branche la clé USB, lance l'impression, puis attend et enfin referme la porte.

Cahier des charges du SBC : 

Nicolas suggère le LicheeRV Nano de Sipeed. Mais on trouve aussi le RTF5350 chez Olimex, directement doté de relais pour la commande des verrous.

Lecteur NFC ACR122U

Lecteur NFC ACR122U

Mise en oeuvre lecteur NFC

Le lecteur se connecte en USB au PC de l'accueil, sous Linux.

Il est nécessaire d'installer les paquets lib-nfc6 et lib-nfc-dev, lib-nfc-bin, ydotool.

Il faut élargir les droits sur /dev/uinput +r pour que ydotool puisse y accéder.

Le script suivant permet d'obtenir un comportement adéquat ressemblant à un clavier :

#/bin/env bash

STRING=""
OLDSTRING=""

while true ; do 

STRING=$(/usr/bin/nfc-list |grep UID |awk '{ print $3,":",$4,":",$5,":",$6,":",$7,":",$8,":",$9 }'|sed 's/ //g' |sed 's/;/:/g' )

[[ $STRING != $OLDSTRING ]] && (gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us+alt-intl')]" ; ydotool type $STRING < /dev/null > /dev/null 2> /dev/null; gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'fr+latin9'), ('xkb', 'us+alt-intl')]" )
OLDSTRING=$STRING
done

ydotool s'attend à un clavier US, d'où la nécessité de jouer avec gsettings.

Le script est appelé au démarrage via l'application de réglage des préférences gnome-session-properties :

image.png

Malgré le #/bin/env bash en début de script, il est nécessaire d'indiquer /bin/bash /home/fablabuser/run-nfc-scan

Compléments : API, webhooks, PWA

Compléments : API, webhooks, PWA

Webhooks

Les webhooks sont un mécanisme complémentaire de l'API pour interagir avec les applications/services en ligne. Timetonic en particulier peut "écouter" les webhooks pour réagir lors d'appels.

Une bonne introduction est disponible sur Webhook.net (archive)

Pour intégrer des appels webhooks dans une page web, avec des scripts, la démarche et des exemples sont présentés ici dans un contexte de pilotage d'un robot via une page web (archive).

Outils pour tester les requêtes et apprendre :

Concernant l'usage de curl, il existe d'ailleurs un site web curlconverter qui traduit une syntaxe curl vers d'autres langages (C, python, javascript et de nombreux autres)

Quelques bonne pratiques (y compris sécurité) pour la programmation avec des webhooks.