Firmware & OTA
Builds serveur, firmware custom dans le navigateur, flash et mises à jour OTA
PNeX compile, flashe et met à jour le firmware sans quitter la plateforme.
Trois familles d'appareils
| Générique PneX | Custom (IDE) | Prédéfinie (prête à l'emploi) | |
|---|---|---|---|
| Ce que vous faites | Configurer entrées et sorties depuis l'UI | Écrire votre propre main.cpp dans l'éditeur intégré | Brancher une carte dont PNeX garantit la compatibilité |
| Code | Aucun | Le vôtre, versionné dans PNeX | Aucun : un firmware dédié maintenu par PNeX, imposé par le modèle — aucun choix de firmware |
| Valeurs | États des pins (numérique, analogique, PWM) | Vos propres métriques (temp, humidity…) et commandes | Fonctions prédéfinies (humidité du sol, vidéo live…) |
| Usage type | Relais, boutons, entrées analogiques | Capteurs I2C/SPI/1-Wire, logique locale, valeurs calculées | Un capteur ou une caméra clé en main |
Les trois sont compilées par appareil côté serveur, partagent le même transport chiffré et la même OTA, et se flashent de la même façon. Un firmware custom tourne sur la carte d'un modèle générique : vous choisissez son projet au provisioning de l'appareil. Les ordinateurs et Raspberry Pi ne sont pas des cartes : ils rejoignent PNeX comme agents edge.
Service de build
Le serveur compile le firmware à la demande par appareil : les sources PlatformIO sont embarquées dans le binaire serveur, les secrets (Wi-Fi, hôte, token, clé de chiffrement, autorité de certification épinglée) sont injectés en env de build, et le résultat est stocké comme artefact (PostgreSQL ou S3-compatible). SoCs supportés : ESP8266, ESP32, ESP32-C3, ESP32-S3.
Les builds passent par une file de jobs, exécutée par un builder dédié ; le serveur d'API n'embarque aucune toolchain. Le mot de passe Wi-Fi vit dans le coffre de secrets : un job en file ne porte qu'une référence, et le builder résout la valeur au moment de compiler.
Chaque binaire est propre à son appareil — il n'existe pas d'image générique réutilisable. Changer un mot de passe Wi-Fi ne recompile donc rien : les appareils déjà flashés gardent l'ancien identifiant jusqu'à ce que vous les recompiliez et reflashiez, un par un.
Firmware custom
La page Firmware (menu Edges) est un éditeur C++ dans le navigateur. Vous
écrivez un seul main.cpp sur la bibliothèque PNeX ; la carte vient de l'appareil,
et la bibliothèque est toujours la version livrée avec votre serveur — rien à
installer.
L'API PNeX
#include <Pnex.h>
#include <Adafruit_BME280.h>
PnexDevice pnex;
Adafruit_BME280 bme;
void setup() {
Wire.begin(21, 22);
bme.begin(0x76);
// Announced to the server; each metric becomes its own telemetry series.
pnex.addMetric("temp", "°C");
pnex.addMetric("humidity", "%");
// Callable from PNeX; the return value becomes the acknowledgement.
pnex.onCommand("calibrate", [](JsonVariantConst args) {
return true;
});
pnex.begin();
}
unsigned long last = 0;
void loop() {
pnex.loop(); // every iteration: heartbeat, OTA, commands
if (millis() - last >= 10000) {
last = millis();
pnex.publish("temp", bme.readTemperature());
pnex.publish("humidity", bme.readHumidity());
}
}addMetric(id, unité)— déclare une métrique avantbegin()(16 au plus). Le serveur ne stocke que les métriques annoncées par le firmware ; le reste est jeté.publish(id, valeur)— envoie une valeur (float, entier,boolou chaîne courte). Elle arrive dans la télémétrie de l'appareil comme n'importe quelle mesure, prête pour les flows, les tableaux de bord et les alertes.onCommand(nom, callback)— déclare une commande (8 au plus). L'éditeur de firmware liste les commandes annoncées par chaque appareil et peut les envoyer ; une commande inconnue du firmware reçoitunknown_command. Un nœud de flow pour les commandes custom est prévu.
Le menu + PneX API de l'éditeur insère ces appels avec leur documentation.
Appelez pnex.loop() à chaque itération et ne bloquez jamais dans un long
delay() : passé le délai du heartbeat, le serveur marque l'appareil hors ligne et
ses sorties retombent dans leur état de sûreté. Utilisez le motif non bloquant
millis() ci-dessus.
Identifiants Wi-Fi, token et clé de chiffrement n'apparaissent jamais dans votre sketch : le builder les injecte pour l'appareil ciblé.
Bibliothèques
Les bibliothèques additionnelles viennent d'un catalogue curé aux versions épinglées : BME280, BMP280, SHT3x, AHT20, BH1750, INA219, ADS1x15, OneWire, DS18B20, DHT, NeoPixel, ESP32Servo, SSD1306 et Adafruit Unified Sensor. Ajoutez-les depuis le menu + Lib ; le serveur refuse toute bibliothèque hors catalogue. Les clients réseau (MQTT, SDK HTTP cloud…) sont exclus volontairement : le transport, c'est le rôle de PNeX.
Révisions
Chaque enregistrement crée une révision immuable, avec son auteur et son message ; un contenu identique ne crée rien. L'historique permet de comparer et de restaurer. Chaque build garde la révision qu'il a compilée : vous savez toujours quel code tourne sur quel appareil — et pousser en OTA un build plus ancien, c'est un rollback.
Vérifier, puis déployer
- Vérifier compile votre code sans aucun vrai secret et ne garde aucun
artefact. Les erreurs du compilateur sont projetées sur les lignes de votre
main.cpp; celles levées dans une bibliothèque sont listées avec leur fichier. - Provisioning : dans l'assistant appareil, l'étape Modèle propose les projets firmware compatibles avec la puce de la carte. Un projet peut servir plusieurs appareils.
- Recompiler compile la dernière révision du projet pour cet appareil ; flashez ensuite en USB ou poussez en OTA.
Un projet ne peut pas être supprimé tant que des appareils l'utilisent.
Sécurité du build
Compiler du C++, c'est exécuter un outillage contrôlé par l'utilisateur sur le builder ; les builds custom sont donc encadrés :
- le
platformio.iniest généré par le serveur et jamais éditable : il porte les secrets et la politique de bibliothèques, et un script de build déclaré là exécuterait du code arbitraire ; - le
main.cppest contrôlé avant compilation : pas d'include absolu ni en.., pas de#embed, pas d'incbin— rien qui puisse faire entrer un fichier du builder dans le binaire que vous téléchargez. Taille plafonnée à 256 Ko ; - seules les bibliothèques du catalogue sont acceptées ;
- un sandbox bubblewrap optionnel exécute le compilateur sans réseau, dans son propre espace de processus, avec l'hôte en lecture seule hors du dossier du job et un répertoire personnel vide.
Le firmware custom est désactivé par défaut (PNEX_FIRMWARE_CUSTOM_ENABLED).
Activez le sandbox (PNEX_FIRMWARE_SANDBOX=bwrap) avant de l'ouvrir à des personnes
en qui vous n'avez pas entièrement confiance ; sans lui, réservez la fonction aux
installations mono-utilisateur. Les bibliothèques du catalogue sont encore
téléchargées au build aujourd'hui — un magasin préchargé, entièrement hors ligne,
est prévu.
Flash USB
Flash en un clic, sans aucun toolchain sur votre machine :
- App web (Chrome, Edge) : Web Serial avec esptool-js. Le navigateur choisit le port série par un geste utilisateur, télécharge le binaire mergé depuis le store d'artefacts et flashe la carte.
- App desktop (Linux, Windows) : un esptool embarqué, à version épinglée, flashe la carte ; le port série est détecté automatiquement.
- App Android : pas de flash USB — flashez depuis un ordinateur, puis mettez à jour en OTA.

OTA
Les mises à jour sont un état désiré poussé aux appareils en ligne par WebSocket, ou récupéré à la prochaine annonce. L'appareil télécharge l'image en HTTPS, authentifié par son token et avec l'autorité de certification épinglée. Il calcule le hash pendant le téléchargement et vérifie le SHA-256 avant de basculer de partition : en cas d'écart, la mise à jour est abandonnée et l'ancien firmware continue de tourner. La mise à jour n'est réussie qu'une fois l'appareil redémarré sur la nouvelle version annoncée. Des gardes refusent les assignations dupliquées ou en cours, et les payloads surdimensionnés sur les SoCs contraints.

Écrans
La lib firmware supporte SSD1306 OLED et ST7735 TFT avec barre d'état, timeline de
connexion et redraws à changement seulement — et un nœud pnex-display pipe des
valeurs vers les écrans.

