Bêta précoce (0.1.0), pas encore pour un process critique. Voir la roadmap
PNeX logo

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 PneXCustom (IDE)Prédéfinie (prête à l'emploi)
Ce que vous faitesConfigurer 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é
CodeAucunLe vôtre, versionné dans PNeXAucun : 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 commandesFonctions prédéfinies (humidité du sol, vidéo live…)
Usage typeRelais, boutons, entrées analogiquesCapteurs I2C/SPI/1-Wire, logique locale, valeurs calculéesUn 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 avant begin() (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, bool ou 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çoit unknown_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.ini est 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.cpp est 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.

Boîte de dialogue de flash Web Serial

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.

Confirmation de déploiement OTA

É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.

On this page