1. Introduction
SchreinSerialParser est une bibliothèque Arduino professionnelle dédiée à la communication série pour les projets IoT et embarqués. Elle permet de recevoir, parser et envoyer des trames structurées entre votre carte Arduino/ESP et une interface de supervision (comme Schrein UI Builder).

1.1. Caractéristiques techniques

1.2. Avantages
✅ Zéro allocation dynamique – Pas de new/malloc, sûr pour les systèmes critiques
✅ Non-bloquant – La fonction loop() ne bloque jamais l’exécution
✅ File circulaire – Jusqu’à 4 trames en attente
✅ Checksum intégré – Détection d’erreurs optionnelle
✅ Callbacks – Programmation événementielle
✅ Statistiques – Monitoring des performances
2. Installation
2.1. Installation depuis l’IDE Arduino
- Téléchargez les fichiers
.het.cpp - Créez un dossier
SchreinSerialParserdans votre dossierlibraries/Arduino - Copiez les fichiers dans ce dossier
- Redémarrez l’IDE Arduino
2.2. Structure des fichiers
SchreinSerialParser/
├── examples/
│ └── Basic_Usage
│ └── Basic_Usage.ino
├── src/
│ ├── SchreinSerialParser.h
│ └── SchreinSerialParser.cpp
│
│
│
├── README.txt
├── library.properties
└── keywords.txt3. Format de trame
La bibliothèque utilise un format de trame simple, robuste et compatible avec Schrein UI Builder.
3.1. Format standard (sans checksum)
3.1.1. De Schrein UI Builder → Carte embarquée
Format : <[CONTROL|KEY|VALUE]>
Exemples :
// Mettre à jour une jauge de température
<[gaugeTemperature|value|24.5]>
// Changer la couleur d'un texte
<[labelStatus|color|#00FF00]>
// Allumer/éteindre une LED
<[ledRouge|state|1]>
// Définir l'angle d'un servo-moteur
<[servoMoteur|angle|90]>
// Envoyer une commande à un bouton
<[btnStart|click|1]>
// Contrôler une prise connectée
<[priseSalon|power|ON]>
3.1.2. De la carte embarquée → Schrein UI Builder
Format : CONTROL=KEY:VALUE;
Exemples :
// Envoyer une température depuis un capteur DHT
gaugeTemperature=value:24.5;
// Envoyer l'état d'un capteur de présence
capteurPresence=state:1;
// Envoyer une pression
gaugePression=value:1013.25;
// Envoyer une luminosité
gaugeLuminosite=value:450;
// Envoyer un texte de log
console=message:"Capteur démarré";
// Envoyer une alerte
alerte=message:"Température élevée"
3.2. Format avec checksum (sécurisé)
Le checksum est un XOR sur l’ensemble des caractères du corps de la trame (entre [ et ] inclus, ou entre = et ; inclus).
3.2.1. De Schrein UI Builder → Carte embarquée
Format : <[CONTROL|KEY|VALUE]&XX>
XX représente le checksum en hexadécimal (2 caractères).
Exemples :
// Avec checksum
<[gaugeTemperature|value|24.5]&3F>
// Changer couleur avec checksum
<[labelStatus|color|#00FF00]&5A>
// Allumer LED avec checksum
<[ledRouge|state|1]&2C>
// Commande servo avec checksum
<[servoMoteur|angle|90]&1E>
// Contrôle prise avec checksum
<[priseSalon|power|ON]&4B>
3.2. De la carte embarquée → Schrein UI Builder
Format : CONTROL=KEY:VALUE;&XX
XX représente le checksum en hexadécimal (2 caractères).
Exemples :
// Envoyer température avec checksum
SchreinVThermometer2=value:24.5;&3F
// Envoyer état capteur avec checksum
SchreinToggleSwitch5=state:1;&2C
// Envoyer pression avec checksum
SchreinAnalogicGauge1=value:1013.25;&7E
// Envoyer luminosité avec checksum
SchreinVProgressBar4=value:450;&A3
// Envoyer log avec checksum
SchreinLabel1=message:"Capteur démarré";&5F
4. Installation et inclusion
4.1. Inclusion de la bibliothèque
#include <SchreinSerialParser.h>
// Créer une instance sur le port Serial (ou Serial1, Serial2...)
SchreinSerialParser parser(Serial);5. API principale
5.1. Configuration de base
void setup() {
Serial.begin(115200);
// Optionnel : activer le checksum (désactivé par défaut)
parser.enableChecksum(true);
// Optionnel : définir un timeout (défaut: 1000ms)
parser.setTimeout(2000);
Serial.println("SchreinSerialParser prêt !");
}5.2. Réception de trames (boucle principale)
void loop() {
// À appeler à chaque cycle - traite les données entrantes
parser.loop();
// Vérifier si une trame est disponible
if (parser.isFrameAvailable()) {
// Récupérer une valeur spécifique
const char* temperature = parser.getValue("gaugeTemperature", "value");
if (strlen(temperature) > 0) {
float temp = atof(temperature);
Serial.print("Température reçue : ");
Serial.println(temp);
}
// Réinitialiser l'état de la trame
parser.resetFrame();
}
}5.3. Envoi de commandes (3 méthodes)
Méthode 1 : sendCommand() – La plus simple ✅
// Envoyer une valeur à une jauge
parser.sendCommand("SchreinVThermometer", "Value", "24.5");
// Changer la couleur d'un texte
parser.sendCommand("SchreinLabel1", "color", "#00FF00");
// Allumer/éteindre une LED virtuelle
parser.sendCommand("SchreinToggleSwitch6", "IsOn", "1");Méthode 2 : sendFrame() – Trame brute
parser.sendFrame("SchreinVThermometer1=Value:24.5;");Méthode 3 : buildCommand() – Avec buffer pré-construit
char buffer[64];
SchreinSerialParser::buildCommand(buffer, sizeof(buffer),
"servoMoteur", "angle", "90");
parser.sendFrame(buffer);6. Système de callbacks
Les callbacks permettent une programmation événementielle plus propre et réactive.
6.1. Callback de trame parsée
void onFrameParsed(const char* control, const char* key, const char* value) {
Serial.print("Reçu - Ctrl:");
Serial.print(control);
Serial.print(" Key:");
Serial.print(key);
Serial.print(" Val:");
Serial.println(value);
// Traitement spécifique par contrôleur
if (strcmp(control, "ledRouge") == 0 && strcmp(key, "etat") == 0) {
digitalWrite(LED_BUILTIN, atoi(value) ? HIGH : LOW);
}
}
void setup() {
Serial.begin(115200);
parser.onFrameParsed(onFrameParsed);
}6.2. Callback de données brutes
void onRawData(const char* data) {
Serial.print("Donnée brute reçue : ");
Serial.println(data);
}
void setup() {
parser.onDataReceived(onRawData);
}6.3. Callback d’erreur
void onError(const char* error) {
Serial.print("ERREUR : ");
Serial.println(error);
}
void setup() {
parser.onError(onError);
}7. File de trames (Queue)
Pour les applications à haut débit, la bibliothèque stocke jusqu’à 4 trames en attente.
7.1. Utilisation de la file
void loop() {
parser.loop();
// Traiter toutes les trames en attente
ParsedFrame frame;
while (parser.dequeueFrame(frame)) {
if (frame.valid) {
Serial.print("Control: ");
Serial.print(frame.controlName);
Serial.print(" | Key: ");
Serial.print(frame.key);
Serial.print(" | Value: ");
Serial.println(frame.value);
}
}
}7.2. Vérification du nombre de trames en attente
uint8_t pending = parser.pendingFrameCount();
if (pending > 0) {
Serial.print(pending);
Serial.println(" trames en attente");
}8. Gestion des erreurs
8.1. Codes d’erreur

8.2. Récupération d’erreur
void loop() {
parser.loop();
if (parser.getLastError() != SchreinSerialParser::ErrorCode::NO_ERROR) {
Serial.print("Erreur : ");
Serial.println(parser.getLastErrorMessage());
parser.clearError();
}
}9. Statistiques et debug
9.1. Métriques de performance
void afficherStats() {
Serial.print("Trames reçues : ");
Serial.println(parser.getFramesReceived());
Serial.print("Trames perdues : ");
Serial.println(parser.getFramesDropped());
Serial.print("Erreurs checksum : ");
Serial.println(parser.getChecksumErrors());
Serial.print("Temps max parse : ");
Serial.print(parser.getParseTimeUsMax());
Serial.println(" µs");
Serial.print("Trames en attente : ");
Serial.println(parser.pendingFrameCount());
}9.2. Mode debug
// Afficher le buffer de réception
parser.debugOutput("receiveBuffer");
// Afficher la dernière trame parsée
parser.debugOutput("parsedFrame");
// Afficher la dernière erreur
parser.debugOutput("error");
// Afficher les statistiques
parser.debugOutput("stats");
// Afficher l'état de la file
parser.debugOutput("queue");10. Exemples complets
10.1. Réception basique
#include <SchreinSerialParser.h>
SchreinSerialParser parser(Serial);
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
parser.enableChecksum(false);
Serial.println("Prêt à recevoir des trames...");
}
void loop() {
parser.loop();
if (parser.isFrameAvailable()) {
// Lire la température
const char* temp = parser.getValue("gaugeTemp", "value");
if (strlen(temp) > 0) {
Serial.print("Température: ");
Serial.println(temp);
}
// Lire l'état LED
const char* etat = parser.getValue("ledEtat", "state");
if (strlen(etat) > 0) {
digitalWrite(LED_BUILTIN, atoi(etat) ? HIGH : LOW);
}
parser.resetFrame();
}
}10.2. Envoi de données capteur (DHT22)
#include <SchreinSerialParser.h>
#include <DHT.h>
SchreinSerialParser parser(Serial);
DHT dht(2, DHT22);
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
static unsigned long lastSend = 0;
if (millis() - lastSend > 2000) {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
// Envoyer température
parser.sendCommand("gaugeTemp", "value", String(temp).c_str());
// Envoyer humidité
parser.sendCommand("gaugeHum", "value", String(hum).c_str());
lastSend = millis();
}
parser.loop();
}10.3. Gestion avancée avec queue et callbacks
#include <SchreinSerialParser.h>
SchreinSerialParser parser(Serial);
void onFrame(const char* ctrl, const char* key, const char* val) {
if (strcmp(ctrl, "moteur") == 0 && strcmp(key, "vitesse") == 0) {
analogWrite(9, atoi(val));
}
else if (strcmp(ctrl, "servo") == 0 && strcmp(key, "angle") == 0) {
// Commande servo
}
}
void onError(const char* err) {
Serial.print("⚠️ Erreur: ");
Serial.println(err);
}
void setup() {
Serial.begin(115200);
parser.onFrameParsed(onFrame);
parser.onError(onError);
parser.enableChecksum(true);
}
void loop() {
parser.loop();
// Traitement par lots via la queue
ParsedFrame frame;
while (parser.dequeueFrame(frame)) {
if (frame.valid) {
onFrame(frame.controlName, frame.key, frame.value);
}
}
}10.4. Projet complet : Station météo
#include <SchreinSerialParser.h>
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT22
SchreinSerialParser parser(Serial);
DHT dht(DHT_PIN, DHT_TYPE);
unsigned long lastSend = 0;
char buffer[16];
void setup() {
Serial.begin(115200);
dht.begin();
parser.enableChecksum(false);
Serial.println("Station météo connectée");
}
void loop() {
parser.loop();
// Envoi des données toutes les 2 secondes
if (millis() - lastSend > 2000) {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (!isnan(temp)) {
dtostrf(temp, 4, 1, buffer);
parser.sendCommand("gaugeTemperature", "value", buffer);
}
if (!isnan(hum)) {
dtostrf(hum, 4, 1, buffer);
parser.sendCommand("gaugeHumidite", "value", buffer);
}
lastSend = millis();
}
// Réception des commandes
if (parser.isFrameAvailable()) {
const char* cmd = parser.getValue("systeme", "commande");
if (strlen(cmd) > 0 && strcmp(cmd, "reset") == 0) {
// Réinitialiser la carte
}
parser.resetFrame();
}
}11. Compatibilité avec Schrein UI Builder
La bibliothèque est nativement compatible avec les trames générées par Schrein UI Builder.
11.1. Schéma de communication typique

12. Optimisations mémoire
12.1. Pour Arduino Uno (2KB RAM)
Modifiez les constantes dans SchreinSerialParser.h :
#define MAX_CONTROL_NAME_LEN 16 // au lieu de 24
#define MAX_KEY_LEN 12 // au lieu de 16
#define MAX_VALUE_LEN 32 // au lieu de 48
#define PARSER_BUFFER_SIZE 64 // au lieu de 128
#define MAX_PENDING_FRAMES 2 // au lieu de 412.2. Pour ESP32 (520KB RAM)
Les valeurs par défaut sont déjà optimisées.
12.3. Estimation de l’empreinte mémoire

13. Dépannage
13.1. Problèmes courants

13.2. Debug pas à pas
// 1. Vérifier la connexion série
void setup() {
Serial.begin(115200);
Serial.println("Test de communication");
}
// 2. Activer le mode debug
parser.debugOutput("stats");
// 3. Vérifier les erreurs
if (parser.getLastError() != SchreinSerialParser::ErrorCode::NO_ERROR) {
parser.debugOutput("error");
}14. Référence rapide (Cheatsheet)
// Inclusion
#include <SchreinSerialParser.h>
// Instance
SchreinSerialParser parser(Serial);
// Setup
parser.enableChecksum(true); // Activer checksum
parser.setTimeout(1000); // Timeout 1s
parser.onFrameParsed(callback); // Callback trame
// Loop
parser.loop(); // Traitement série
// Réception simple
if (parser.isFrameAvailable()) {
const char* val = parser.getValue("controleur", "propriete");
parser.resetFrame();
}
// Réception avec queue
ParsedFrame f;
while (parser.dequeueFrame(f)) {
// Traiter f.controlName, f.key, f.value
}
// Envoi (3 méthodes)
parser.sendCommand("ctrl", "prop", "val");
parser.sendFrame("<[ctrl|prop|val]>");
parser.buildCommand(buf, sizeof(buf), "ctrl", "prop", "val");
// Debug
parser.debugOutput("stats");15. Support et ressources
15.1. Liens utiles
- Documentation en ligne : https://schreiken.tech/schreinuibuilder
- Chaîne YouTube : @SchreinUIBuilder
- GitHub : SchreikenLab/SchreinSerialParser
📊 Comparaison de Performance
Utilisation Mémoire

Performance

Plateformes suppertés

Applications Types
