Embarquer un moteur de script dans une app .NET MAUI — logique dynamique, commandes BLE, sans mise à jour de l’app

Le point de départ

MOGWAI est un moteur de script RPN open-source à pile pour .NET, que je développe et utilise en production depuis plusieurs années. Si vous n’êtes pas familier avec la notation polonaise inverse (RPN), pensez au modèle d’exécution des calculatrices HP : les opérandes sont empilés, et les opérations les consomment. MOGWAI étend ce modèle en un véritable langage de script avec des fonctions, des variables, des boucles, des timers et des liaisons vers les applications hôtes.

Pendant longtemps, MOGWAI vivait dans des contextes desktop et serveur. Puis j’ai eu besoin de l’embarquer dans une application mobile construite avec .NET MAUI. Cet article décrit pourquoi, comment, et à quoi ressemble l’architecture.

Le problème

Mon application MAUI communique avec des appareils matériels via Bluetooth Low Energy (BLE). Les commandes envoyées à ces appareils ne sont pas triviales : elles dépendent de paramètres de configuration, de l’état de l’appareil, et d’une logique métier qui peut évoluer dans le temps.

L’approche naïve consiste à coder cette logique directement dans l’app. Ça fonctionne — jusqu’à ce que ça doive changer. Chaque modification implique un nouveau build, une nouvelle soumission sur les stores iOS et Android, et d’attendre que les utilisateurs mettent à jour. Pour une logique qui évolue fréquemment, ce cycle est lent et fragile.

Ce que je voulais : une séparation nette entre le moteur d’exécution et la couche de communication (stables, versionnés dans l’app) d’un côté, et la logique métier (flexible, mise à jour indépendamment) de l’autre.

Pourquoi un moteur de script et pas un fichier de configuration

Un fichier de configuration gère des valeurs statiques. Un moteur de script gère de la logique.

Quand la commande à envoyer dépend de conditions, de séquences d’opérations, ou de calculs sur l’état à l’exécution, un fichier clé-valeur ne suffit pas. Il faut quelque chose qui peut réellement exécuter du code. MOGWAI fournit cette couche : un environnement d’exécution sandboxé et embarquable qui prend un script en entrée et produit un résultat en sortie.

La séparation est propre :

  • L’app est responsable de la communication BLE, de l’UI et du cycle de vie
  • MOGWAI est responsable de la génération des commandes
  • Les scripts sont responsables de la logique métier

Chaque couche peut évoluer indépendamment.

Intégration via NuGet

Ajouter MOGWAI à un projet MAUI est une simple référence NuGet. Le moteur est du .NET pur — pas de bindings natifs, pas de configuration spécifique à la plateforme, pas de compilation conditionnelle. Il tourne sur iOS et Android sans modification.

// Initialiser le moteur
var engine = new MogwaiEngine();

// Charger un script depuis un fichier ou une source distante
var script = await File.ReadAllTextAsync(scriptPath);

// Exécuter et récupérer le résultat
var result = await engine.EvalAsync(script);

// Le résultat est le payload de la commande BLE
var command = result.AsBytes();
await bleService.SendAsync(command);

L’initialisation du moteur est identique sur les deux plateformes. L’exécution du script est identique. La gestion du résultat est identique. MAUI gère la couche BLE spécifique à la plateforme via son abstraction de services ; MOGWAI se situe entièrement au-dessus, produisant les payloads qui sont ensuite envoyés.

Les scripts viennent de l’extérieur de l’app

Les scripts sont des fichiers .mog récupérés depuis un serveur distant ou chargés depuis le stockage local. Quand la logique métier doit changer, seul le fichier script est mis à jour — l’application elle-même n’a pas besoin d’être modifiée.

C’est l’avantage opérationnel clé. Le moteur d’exécution est stable et versionné dans l’app. La logique est flexible et peut être mise à jour indépendamment. Pas de build, pas de soumission sur les stores, pas d’attente de mise à jour des utilisateurs.

À quoi ressemble l’architecture

Serveur distant / fichier local

Script (fichier .mog)

Moteur MOGWAI (.NET)

Payload de commande (bytes)

Service BLE (MAUI)

Appareil matériel

L’app récupère le script, le passe au moteur, reçoit le résultat et le transmet à la couche BLE. Chaque composant a une responsabilité unique.

iOS et Android — le même code

Parce que MOGWAI est du .NET pur, il n’y a rien de spécifique à la plateforme à gérer au niveau de la couche de scripting. Le moteur tourne de façon identique sur les deux plateformes. Le seul code spécifique à la plateforme dans l’app est l’implémentation du service BLE, que MAUI gère déjà via son abstraction.

Cela a une importance pratique : une correction de bug ou un ajout de fonctionnalité dans la couche de scripting bénéficie simultanément aux deux plateformes, sans divergence à gérer.

Une note sur le threading

Le pipeline d’exécution de MOGWAI est entièrement asynchrone, ce qui s’adapte naturellement au modèle async de MAUI. L’exécution d’un script ne bloque pas le thread UI. Un script en cours d’exécution peut être arrêté à tout moment en appelant Engine.Halt() — utile pour les scénarios de timeout ou d’annulation à la demande de l’utilisateur. Le moteur est conçu pour être hébergé dans des boucles applicatives asynchrones, ce qui est exactement ce qu’est une application mobile.

Conclusion

Si vous avez de la logique dans votre application mobile qui évolue plus souvent que l’application elle-même, embarquer un moteur de script vaut la peine d’être envisagé. L’intégration NuGet se fait en une ligne. Le moteur tourne de façon identique sur iOS et Android. La capacité à mettre à jour la logique sans soumission sur les stores est un véritable avantage opérationnel — surtout quand on cible les deux plateformes simultanément.

MOGWAI est open source, sous licence Apache 2.0, disponible sur NuGet et GitHub.

Laisser un commentaire

En savoir plus sur CODING 4 PHONE

Abonnez-vous pour poursuivre la lecture et avoir accès à l’ensemble des archives.

Poursuivre la lecture

En savoir plus sur CODING 4 PHONE

Abonnez-vous pour poursuivre la lecture et avoir accès à l’ensemble des archives.

Poursuivre la lecture