Add complete French (fr) and Chinese (zh) translations for all documentation: - Root files: README, CHANGELOG, SECURITY, BETA-RELEASE - docs/: All 16 core documentation files - DOCS/: All 19 deep-dive documents including embedded/ and archive/ - package/secubox/: All 123+ package READMEs - Misc: secubox-tools/, scripts/, EXAMPLES/, config-backups/, streamlit-apps/ Total: 346 translation files created Each file includes language switcher links for easy navigation between English, French, and Chinese versions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
32 KiB
Guide de Reference pour le Developpement LuCI
Version: 1.0.0 Derniere mise a jour: 2025-12-28 Statut: Actif Base sur: implementations luci-app-secubox et luci-app-system-hub Public cible: Claude.ai et developpeurs travaillant sur des applications LuCI OpenWrt
Voir aussi
- Design et Standards: DEVELOPMENT-GUIDELINES.md
- Commandes Rapides: QUICK-START.md
- Briefing Automatisation: CODEX.md
- Modeles de Code: CODE-TEMPLATES.md
Ce document capture les patterns critiques, bonnes pratiques et pieges courants decouverts lors du developpement des applications LuCI SecuBox. Utilisez-le comme reference de validation pour tout developpement futur d'applications LuCI.
Table des matieres
- Fondamentaux ubus et RPC
- Patterns Backend RPCD
- Patterns Module API LuCI
- Patterns d'Import de Vues LuCI
- Structure des Permissions ACL
- Conventions de Structure de Donnees
- Erreurs Courantes et Solutions
- Checklist de Validation
- Tests et Deploiement
Fondamentaux ubus et RPC
Qu'est-ce que ubus ?
ubus (architecture micro bus OpenWrt) est le systeme de communication inter-processus (IPC) d'OpenWrt. Il permet :
- RPC (Remote Procedure Call) entre processus
- Communication entre l'interface web (LuCI) et les services backend
- Interaction en ligne de commande via
ubus call
Convention de Nommage des Objets ubus
REGLE CRITIQUE : Tous les objets ubus des applications LuCI DOIVENT utiliser le prefixe luci..
// ✅ CORRECT
object: 'luci.system-hub'
object: 'luci.cdn-cache'
object: 'luci.wireguard-dashboard'
// ❌ INCORRECT
object: 'system-hub'
object: 'systemhub'
object: 'cdn-cache'
Pourquoi ? LuCI attend les objets sous l'espace de noms luci.* pour les applications web. Sans ce prefixe :
- Les permissions ACL ne correspondent pas
- RPCD ne route pas correctement les appels
- La console du navigateur affiche :
RPC call to system-hub/status failed with error -32000: Object not found
Le Nom du Script RPCD DOIT Correspondre a l'Objet ubus
Le nom du fichier script RPCD DOIT correspondre exactement au nom de l'objet ubus :
# Si JavaScript declare :
# object: 'luci.system-hub'
# Alors le script RPCD DOIT etre nomme :
/usr/libexec/rpcd/luci.system-hub
# PAS :
/usr/libexec/rpcd/system-hub
/usr/libexec/rpcd/luci-system-hub
Commande de Validation :
# Verifier les fichiers JavaScript pour les noms d'objets ubus
grep -r "object:" luci-app-*/htdocs --include="*.js"
# Verifier que le script RPCD existe avec le nom correspondant
ls luci-app-*/root/usr/libexec/rpcd/
Types d'Appels ubus
Operations de Lecture (type GET) :
status- Obtenir l'etat actuelget_*- Recuperer des donnees (ex:get_health,get_settings)list_*- Enumerer des elements (ex:list_services)
Operations d'Ecriture (type POST) :
save_*- Persister la configuration (ex:save_settings)*_action- Effectuer des actions (ex:service_action)backup,restore,reboot- Modifications systeme
Mapping ACL :
- Operations de lecture → section
"read"dans ACL - Operations d'ecriture → section
"write"dans ACL
Patterns Backend RPCD
Structure des Scripts Shell
Les backends RPCD sont des scripts shell executables qui :
- Analysent
$1pour l'action (listoucall) - Analysent
$2pour le nom de la methode (sicall) - Lisent l'entree JSON depuis stdin (pour les methodes avec parametres)
- Produisent du JSON sur stdout
- Se terminent avec le statut 0 en cas de succes, non-zero en cas d'erreur
Modele Standard
#!/bin/sh
# Backend RPCD : luci.system-hub
# Version : 0.1.0
# Charger l'assistant JSON shell
. /usr/share/libubox/jshn.sh
case "$1" in
list)
# Lister toutes les methodes disponibles et leurs parametres
echo '{
"status": {},
"get_health": {},
"service_action": { "service": "string", "action": "string" },
"save_settings": {
"auto_refresh": 0,
"health_check": 0,
"refresh_interval": 0
}
}'
;;
call)
case "$2" in
status)
status
;;
get_health)
get_health
;;
service_action)
# Lire l'entree JSON depuis stdin
read -r input
json_load "$input"
json_get_var service service
json_get_var action action
service_action "$service" "$action"
;;
save_settings)
read -r input
json_load "$input"
json_get_var auto_refresh auto_refresh
json_get_var health_check health_check
json_get_var refresh_interval refresh_interval
save_settings "$auto_refresh" "$health_check" "$refresh_interval"
;;
*)
echo '{"error": "Method not found"}'
exit 1
;;
esac
;;
esac
Sortie JSON avec jshn.sh
jshn.sh fournit des fonctions shell pour la manipulation JSON :
# Initialiser l'objet JSON
json_init
# Ajouter des valeurs simples
json_add_string "hostname" "openwrt"
json_add_int "uptime" 86400
json_add_boolean "running" 1
# Ajouter un objet imbrique
json_add_object "cpu"
json_add_int "usage" 25
json_add_string "status" "ok"
json_close_object
# Ajouter un tableau
json_add_array "services"
json_add_string "" "network"
json_add_string "" "firewall"
json_close_array
# Produire le JSON sur stdout
json_dump
Fonctions Courantes :
json_init- Demarrer un nouvel objet JSONjson_add_string "key" "value"- Ajouter une chainejson_add_int "key" 123- Ajouter un entierjson_add_boolean "key" 1- Ajouter un booleen (0 ou 1)json_add_object "key"- Demarrer un objet imbriquejson_close_object- Terminer l'objet imbriquejson_add_array "key"- Demarrer un tableaujson_close_array- Terminer le tableaujson_dump- Produire le JSON sur stdout
Gestion des Erreurs
Toujours valider les entrees et retourner des erreurs significatives :
service_action() {
local service="$1"
local action="$2"
# Valider le nom du service
if [ -z "$service" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Service name is required"
json_dump
return 1
fi
# Valider l'action
case "$action" in
start|stop|restart|enable|disable)
;;
*)
json_init
json_add_boolean "success" 0
json_add_string "error" "Invalid action: $action"
json_dump
return 1
;;
esac
# Executer l'action
/etc/init.d/"$service" "$action" >/dev/null 2>&1
if [ $? -eq 0 ]; then
json_init
json_add_boolean "success" 1
json_add_string "message" "Service $service $action successful"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "error" "Service $service $action failed"
json_dump
return 1
fi
}
Integration UCI
Pour la configuration persistante, utiliser UCI (Unified Configuration Interface) :
save_settings() {
local auto_refresh="$1"
local health_check="$2"
local refresh_interval="$3"
# Creer/mettre a jour la config UCI
uci set system-hub.general=general
uci set system-hub.general.auto_refresh="$auto_refresh"
uci set system-hub.general.health_check="$health_check"
uci set system-hub.general.refresh_interval="$refresh_interval"
uci commit system-hub
json_init
json_add_boolean "success" 1
json_add_string "message" "Settings saved successfully"
json_dump
}
get_settings() {
# Charger la config UCI
if [ -f "/etc/config/system-hub" ]; then
. /lib/functions.sh
config_load system-hub
fi
json_init
json_add_object "general"
# Obtenir la valeur ou utiliser la valeur par defaut
config_get auto_refresh general auto_refresh "1"
json_add_boolean "auto_refresh" "${auto_refresh:-1}"
config_get refresh_interval general refresh_interval "30"
json_add_int "refresh_interval" "${refresh_interval:-30}"
json_close_object
json_dump
}
Conseils de Performance
- Mettre en cache les operations couteuses : Ne pas relire les fichiers
/procplusieurs fois - Utiliser efficacement la substitution de commande :
# Bien uptime=$(cat /proc/uptime | cut -d' ' -f1) # Mieux read uptime _ < /proc/uptime uptime=${uptime%.*} - Eviter les commandes externes quand possible :
# Lent count=$(ls /etc/init.d | wc -l) # Rapide count=0 for file in /etc/init.d/*; do [ -f "$file" ] && count=$((count + 1)) done
Patterns Module API LuCI
CRITIQUE : Utiliser baseclass.extend()
REGLE : Les modules API LuCI DOIVENT utiliser le pattern baseclass.extend().
'use strict';
'require baseclass';
'require rpc';
// Declarer les methodes RPC
var callStatus = rpc.declare({
object: 'luci.system-hub',
method: 'status',
expect: {}
});
var callGetHealth = rpc.declare({
object: 'luci.system-hub',
method: 'get_health',
expect: {}
});
var callSaveSettings = rpc.declare({
object: 'luci.system-hub',
method: 'save_settings',
params: ['auto_refresh', 'health_check', 'refresh_interval'],
expect: {}
});
// ✅ CORRECT : Utiliser baseclass.extend()
return baseclass.extend({
getStatus: callStatus,
getHealth: callGetHealth,
saveSettings: callSaveSettings
});
// ❌ INCORRECT : Ne PAS utiliser ces patterns
return baseclass.singleton({...}); // Casse tout !
return {...}; // L'objet simple ne fonctionne pas
Pourquoi baseclass.extend() ?
- Le systeme de modules LuCI attend des modules bases sur des classes
- Les vues importent avec
'require module/api as API'qui auto-instancie baseclass.extend()cree un constructeur de classe appropriébaseclass.singleton()casse le mecanisme d'instanciation- Les objets simples ne supportent pas le cycle de vie des modules LuCI
Parametres rpc.declare()
var callMethodName = rpc.declare({
object: 'luci.module-name', // nom objet ubus (DOIT commencer par luci.)
method: 'method_name', // nom methode RPCD
params: ['param1', 'param2'], // Optionnel : noms des parametres (l'ordre compte !)
expect: {} // Structure de retour attendue (ou { key: [] } pour les tableaux)
});
L'Ordre des Parametres est Important :
// RPCD attend les parametres dans cet ordre exact
var callSaveSettings = rpc.declare({
object: 'luci.system-hub',
method: 'save_settings',
params: ['auto_refresh', 'health_check', 'debug_mode', 'refresh_interval'],
expect: {}
});
// L'appel JavaScript DOIT passer les parametres dans le meme ordre
API.saveSettings(1, 1, 0, 30); // auto_refresh=1, health_check=1, debug_mode=0, refresh_interval=30
Patterns du Parametre expect
// La methode retourne un objet unique
expect: {}
// La methode retourne un tableau au niveau superieur
expect: { services: [] }
// La methode retourne une structure specifique
expect: {
services: [],
count: 0
}
Gestion des Erreurs dans le Module API
Les methodes API retournent des Promises. Gerer les erreurs dans les vues :
return API.getHealth().then(function(data) {
if (!data || typeof data !== 'object') {
console.error('Invalid health data:', data);
return null;
}
return data;
}).catch(function(err) {
console.error('Failed to load health data:', err);
ui.addNotification(null, E('p', {}, 'Failed to load health data'), 'error');
return null;
});
Patterns d'Import de Vues LuCI
CRITIQUE : Utiliser 'require ... as VAR' pour les APIs
REGLE : Lors de l'import de modules API, utiliser le pattern 'require ... as VAR' en haut du fichier.
// ✅ CORRECT : Auto-instancie la classe
'require system-hub/api as API';
return L.view.extend({
load: function() {
return API.getHealth(); // API est deja instancie
}
});
// ❌ INCORRECT : Retourne le constructeur de classe, pas l'instance
var api = L.require('system-hub.api');
api.getHealth(); // ERREUR : api.getHealth is not a function
Pourquoi ?
'require module/path as VAR'(avec des slashes) auto-instancie les classesL.require('module.path')(avec des points) retourne le constructeur de classe brut- Les modules API etendent
baseclass, qui necessite une instanciation - Le chargeur de modules LuCI gere l'instanciation avec le pattern
as VAR
Structure de Vue Standard
'use strict';
'require view';
'require form';
'require ui';
'require system-hub/api as API';
return L.view.extend({
load: function() {
// Charger les donnees necessaires au rendu
return Promise.all([
API.getHealth(),
API.getStatus()
]);
},
render: function(data) {
var health = data[0];
var status = data[1];
// Creer les elements UI
var container = E('div', { 'class': 'cbi-map' }, [
E('h2', {}, 'Dashboard'),
// ... plus d'elements
]);
return container;
},
handleSave: null, // Desactiver le bouton sauvegarder
handleSaveApply: null, // Desactiver le bouton sauvegarder et appliquer
handleReset: null // Desactiver le bouton reinitialiser
});
Resume des Patterns d'Import
// Modules core LuCI (toujours avec des guillemets)
'require view';
'require form';
'require ui';
'require rpc';
'require baseclass';
// Modules API personnalises (utiliser 'as VAR' pour l'auto-instanciation)
'require system-hub/api as API';
'require cdn-cache/api as CdnAPI';
// Acceder a l'objet global L (pas de require)
L.resolveDefault(...)
L.Poll.add(...)
L.ui.addNotification(...)
Structure des Permissions ACL
Emplacement du Fichier
Les fichiers ACL sont situes dans :
/usr/share/rpcd/acl.d/luci-app-<nom-module>.json
Dans l'arborescence source :
luci-app-<nom-module>/root/usr/share/rpcd/acl.d/luci-app-<nom-module>.json
Modele ACL Standard
{
"luci-app-module-name": {
"description": "Module Name - Description",
"read": {
"ubus": {
"luci.module-name": [
"status",
"get_system_info",
"get_health",
"list_services",
"get_logs",
"get_storage",
"get_settings"
]
}
},
"write": {
"ubus": {
"luci.module-name": [
"service_action",
"backup_config",
"restore_config",
"reboot",
"save_settings"
]
}
}
}
}
Classification Lecture vs Ecriture
Operations de Lecture (pas de modification systeme) :
status- Obtenir l'etat actuelget_*- Recuperer des donnees (info systeme, sante, parametres, logs, stockage)list_*- Enumerer des elements (services, interfaces, etc.)
Operations d'Ecriture (modifier l'etat systeme) :
*_action- Effectuer des actions (demarrer/arreter services, etc.)save_*- Persister les changements de configurationbackup,restore- Sauvegarde/restauration systemereboot,shutdown- Controle systeme
Erreurs ACL Courantes
Erreur : Access denied ou erreur RPC -32002
Cause : Methode non listee dans l'ACL, ou listee dans la mauvaise section (lecture vs ecriture)
Solution :
- Identifier si la methode est une operation de lecture ou d'ecriture
- Ajouter le nom de la methode a la section appropriee dans l'ACL
- Redemarrer RPCD :
/etc/init.d/rpcd restart
Validation :
# Verifier que le fichier ACL est du JSON valide
jsonlint /usr/share/rpcd/acl.d/luci-app-system-hub.json
# Lister tous les objets et methodes ubus
ubus list luci.system-hub
# Tester une methode avec ubus call
ubus call luci.system-hub get_health
Conventions de Structure de Donnees
Structure des Metriques de Sante (system-hub v0.1.0)
Basee sur des iterations extensives, cette structure fournit clarte et coherence :
{
"cpu": {
"usage": 25,
"status": "ok",
"load_1m": "0.25",
"load_5m": "0.30",
"load_15m": "0.28",
"cores": 4
},
"memory": {
"total_kb": 4096000,
"free_kb": 2048000,
"available_kb": 3072000,
"used_kb": 1024000,
"buffers_kb": 512000,
"cached_kb": 1536000,
"usage": 25,
"status": "ok"
},
"disk": {
"total_kb": 30408704,
"used_kb": 5447680,
"free_kb": 24961024,
"usage": 19,
"status": "ok"
},
"temperature": {
"value": 45,
"status": "ok"
},
"network": {
"wan_up": true,
"status": "ok"
},
"services": {
"running": 35,
"failed": 2
},
"score": 92,
"timestamp": "2025-12-26 10:30:00",
"recommendations": [
"2 service(s) enabled but not running. Check service status."
]
}
Principes Cles :
- Objets imbriques pour les metriques liees (cpu, memory, disk, etc.)
- Structure coherente : Chaque metrique a
usage(pourcentage) etstatus(ok/warning/critical) - Valeurs brutes + calculees : Fournir les deux (ex:
used_kbETusageen pourcentage) - Seuils de statut : ok (< warning), warning (warning-critical), critical (>= critical)
- Score global : Score de sante unique 0-100 pour le tableau de bord
- Recommandations dynamiques : Tableau d'alertes actionnables basees sur les seuils
Valeurs de Statut
Utiliser des chaines de statut coherentes pour toutes les metriques :
"ok"- Fonctionnement normal (vert)"warning"- Approche du seuil (orange)"critical"- Seuil depasse (rouge)"error"- Impossible de recuperer la metrique"unknown"- Metrique non disponible
Format d'Horodatage
Utiliser ISO 8601 ou un format local coherent :
timestamp="$(date '+%Y-%m-%d %H:%M:%S')" # 2025-12-26 10:30:00
Valeurs Booleennes en JSON
Dans les scripts shell utilisant jshn.sh :
json_add_boolean "wan_up" 1 # true
json_add_boolean "wan_up" 0 # false
En JavaScript :
if (health.network.wan_up) {
// WAN est actif
}
Tableau vs Valeur Unique
Utiliser des tableaux pour :
- Elements multiples du meme type (services, interfaces, points de montage)
- Donnees de longueur variable
Utiliser des valeurs uniques pour :
- Metriques systeme globales (CPU, memoire, disque)
- Valeurs primaires/agregees (temperature globale, uptime total)
Exemple - Stockage :
// Points de montage multiples - utiliser un tableau
"storage": [
{
"mount": "/",
"total_kb": 30408704,
"used_kb": 5447680,
"usage": 19
},
{
"mount": "/mnt/usb",
"total_kb": 128000000,
"used_kb": 64000000,
"usage": 50
}
]
// Systeme de fichiers racine seulement - utiliser un objet
"disk": {
"total_kb": 30408704,
"used_kb": 5447680,
"usage": 19,
"status": "ok"
}
Erreurs Courantes et Solutions
1. Erreur RPC : "Object not found" (-32000)
Message d'Erreur :
RPC call to system-hub/status failed with error -32000: Object not found
Cause : Le nom du script RPCD ne correspond pas au nom de l'objet ubus en JavaScript
Solution :
-
Verifier le nom de l'objet dans JavaScript :
grep -r "object:" luci-app-system-hub/htdocs --include="*.js"Sortie :
object: 'luci.system-hub' -
Renommer le script RPCD pour correspondre exactement :
mv root/usr/libexec/rpcd/system-hub root/usr/libexec/rpcd/luci.system-hub -
S'assurer que le script est executable :
chmod +x root/usr/libexec/rpcd/luci.system-hub -
Redemarrer RPCD :
/etc/init.d/rpcd restart
2. Erreur JavaScript : "api.methodName is not a function"
Message d'Erreur :
Uncaught TypeError: api.getHealth is not a function
at view.load (health.js:12)
Cause : Mauvais pattern d'import - import du constructeur de classe au lieu de l'instance
Solution : Changer de :
var api = L.require('system-hub.api'); // ❌ Incorrect
A :
'require system-hub/api as API'; // ✅ Correct
Pourquoi : L.require('module.path') retourne la classe brute, 'require module/path as VAR' auto-instancie.
3. Erreur RPC : "Access denied" (-32002)
Message d'Erreur :
RPC call to luci.system-hub/get_settings failed with error -32002: Access denied
Cause : Methode non listee dans le fichier ACL, ou dans la mauvaise section (lecture vs ecriture)
Solution :
-
Ouvrir le fichier ACL :
root/usr/share/rpcd/acl.d/luci-app-system-hub.json -
Ajouter la methode a la section appropriee :
"read": { "ubus": { "luci.system-hub": [ "get_settings" ] } } -
Deployer et redemarrer RPCD :
scp luci-app-system-hub/root/usr/share/rpcd/acl.d/*.json router:/usr/share/rpcd/acl.d/ ssh router "/etc/init.d/rpcd restart"
4. Erreur d'Affichage : "NaN%" ou Valeurs Indefinies
Erreur : Le tableau de bord affiche "NaN%", "undefined", ou des valeurs vides
Cause : Le frontend utilise des cles de structure de donnees incorrectes (obsoletes apres des changements backend)
Solution :
-
Verifier la sortie backend :
ubus call luci.system-hub get_health -
Mettre a jour le frontend pour correspondre a la structure :
// ❌ Ancienne structure var cpuPercent = health.load / health.cores * 100; var memPercent = health.memory.percent; // ✅ Nouvelle structure var cpuPercent = health.cpu ? health.cpu.usage : 0; var memPercent = health.memory ? health.memory.usage : 0; -
Ajouter des verifications null/undefined :
var temp = health.temperature?.value || 0; var loadAvg = health.cpu?.load_1m || '0.00';
5. HTTP 404 : Fichier Vue Non Trouve
Message d'Erreur :
HTTP error 404 while loading class file '/luci-static/resources/view/netifyd/overview.js'
Cause : Le chemin du menu ne correspond pas a l'emplacement reel du fichier vue
Solution :
-
Verifier le JSON du menu :
cat root/usr/share/luci/menu.d/luci-app-netifyd-dashboard.jsonChercher :
"path": "netifyd/overview" -
Verifier l'emplacement reel du fichier :
ls htdocs/luci-static/resources/view/Le fichier est a :
view/netifyd-dashboard/overview.js -
Corriger soit le chemin du menu SOIT l'emplacement du fichier :
// Option 1 : Mettre a jour le chemin du menu pour correspondre au fichier "path": "netifyd-dashboard/overview" // Option 2 : Deplacer le fichier pour correspondre au menu mv view/netifyd-dashboard/ view/netifyd/
6. Erreur de Build : "factory yields invalid constructor"
Message d'Erreur :
/luci-static/resources/system-hub/api.js: factory yields invalid constructor
Cause : Mauvais pattern utilise dans le module API (singleton, objet simple, etc.)
Solution :
Toujours utiliser baseclass.extend() :
return baseclass.extend({
getStatus: callStatus,
getHealth: callGetHealth,
// ... plus de methodes
});
Ne PAS utiliser :
baseclass.singleton({...})- Objet simple :
return {...} baseclass.prototype
7. RPCD Ne Repond Plus Apres des Changements
Symptome : Les changements au script RPCD ne prennent pas effet
Solution :
-
Verifier que le script est deploye :
ssh router "ls -la /usr/libexec/rpcd/" -
Verifier que le script est executable :
ssh router "chmod +x /usr/libexec/rpcd/luci.system-hub" -
Redemarrer RPCD :
ssh router "/etc/init.d/rpcd restart" -
Vider le cache du navigateur (Ctrl+Shift+R)
-
Verifier les logs RPCD :
ssh router "logread | grep rpcd"
Checklist de Validation
Utiliser cette checklist avant le deploiement :
Structure des Fichiers
- Le script RPCD existe :
/usr/libexec/rpcd/luci.<nom-module> - Le script RPCD est executable :
chmod +x - Le JSON du menu existe :
/usr/share/luci/menu.d/luci-app-<module>.json - Le JSON ACL existe :
/usr/share/rpcd/acl.d/luci-app-<module>.json - Le module API existe :
htdocs/luci-static/resources/<module>/api.js - Les vues existent :
htdocs/luci-static/resources/view/<module>/*.js
Conventions de Nommage
- Le nom du script RPCD correspond a l'objet ubus en JavaScript (incluant le prefixe
luci.) - Les chemins du menu correspondent a la structure de repertoire des fichiers vue
- Tous les objets ubus commencent par
luci. - La cle ACL correspond au nom du package :
"luci-app-<module>"
Validation du Code
- Le module API utilise le pattern
baseclass.extend() - Les vues importent l'API avec le pattern
'require <module>/api as API' - Tous les appels rpc.declare() incluent
object,method,params,expectcorrects - Le script RPCD produit du JSON valide (tester avec
ubus call) - Le JSON du menu est valide (tester avec
jsonlint) - Le JSON ACL est valide (tester avec
jsonlint)
Permissions
- Toutes les methodes de lecture dans la section ACL
"read" - Toutes les methodes d'ecriture dans la section ACL
"write" - Les methodes dans l'ACL correspondent exactement aux noms des methodes du script RPCD
Tests
- Executer le script de validation :
./secubox-tools/validate-modules.sh - Tester chaque methode via ubus :
ubus call luci.<module> <method> - Tester le frontend dans le navigateur (verifier la console pour les erreurs)
- Vider le cache du navigateur apres le deploiement
- Verifier le redemarrage RPCD :
/etc/init.d/rpcd restart
Commande de Validation Automatisee
# Executer la validation complete
./secubox-tools/validate-modules.sh
# Valider un module specifique
./secubox-tools/validate-module-generation.sh luci-app-system-hub
# Verifier la syntaxe JSON
find luci-app-system-hub -name "*.json" -exec jsonlint {} \;
# Verifier les scripts shell
shellcheck luci-app-system-hub/root/usr/libexec/rpcd/*
Tests et Deploiement
Tests Locaux avec ubus
Avant de deployer sur le routeur, tester le script RPCD localement :
# Copier le script RPCD vers /tmp local
cp luci-app-system-hub/root/usr/libexec/rpcd/luci.system-hub /tmp/
# Rendre executable
chmod +x /tmp/luci.system-hub
# Tester l'action 'list'
/tmp/luci.system-hub list
# Tester l'action 'call' avec une methode
/tmp/luci.system-hub call status
# Tester une methode avec parametres
echo '{"service":"network","action":"restart"}' | /tmp/luci.system-hub call service_action
Script de Deploiement
Utiliser un script de deploiement pour une iteration rapide :
#!/bin/bash
# deploy-system-hub.sh
ROUTER="root@192.168.8.191"
echo "Deploiement de system-hub vers $ROUTER"
# Deployer le module API
scp luci-app-system-hub/htdocs/luci-static/resources/system-hub/api.js \
"$ROUTER:/www/luci-static/resources/system-hub/"
# Deployer les vues
scp luci-app-system-hub/htdocs/luci-static/resources/view/system-hub/*.js \
"$ROUTER:/www/luci-static/resources/view/system-hub/"
# Deployer le backend RPCD
scp luci-app-system-hub/root/usr/libexec/rpcd/luci.system-hub \
"$ROUTER:/usr/libexec/rpcd/"
# Deployer l'ACL
scp luci-app-system-hub/root/usr/share/rpcd/acl.d/luci-app-system-hub.json \
"$ROUTER:/usr/share/rpcd/acl.d/"
# Definir les permissions et redemarrer
ssh "$ROUTER" "chmod +x /usr/libexec/rpcd/luci.system-hub && /etc/init.d/rpcd restart"
echo "Deploiement termine ! Videz le cache du navigateur (Ctrl+Shift+R)"
Tests Navigateur
- Ouvrir la console du navigateur (F12)
- Naviguer vers la page du module
- Verifier les erreurs :
- Erreurs RPC (object not found, method not found, access denied)
- Erreurs JavaScript (api.method is not a function)
- Erreurs 404 (fichiers vue non trouves)
- Tester les fonctionnalites :
- Le chargement des donnees s'affiche correctement
- Les actions fonctionnent (demarrer/arreter services, sauvegarder parametres)
- Pas de "NaN", "undefined", ou valeurs vides
Tests ubus a Distance
Tester les methodes RPCD sur le routeur :
# Lister toutes les methodes
ssh router "ubus list luci.system-hub"
# Appeler une methode sans parametres
ssh router "ubus call luci.system-hub status"
# Appeler une methode avec parametres
ssh router "ubus call luci.system-hub service_action '{\"service\":\"network\",\"action\":\"restart\"}'"
# Formater la sortie JSON
ssh router "ubus call luci.system-hub get_health | jsonlint"
Conseils de Debogage
Activer la journalisation de debogage RPCD :
# Editer /etc/init.d/rpcd
# Ajouter le flag -v a la commande procd_set_param
procd_set_param command "$PROG" -v
# Redemarrer RPCD
/etc/init.d/rpcd restart
# Surveiller les logs
logread -f | grep rpcd
Activer la journalisation console JavaScript :
// Ajouter a api.js
console.log('API v0.1.0 chargee a', new Date().toISOString());
// Ajouter aux vues
console.log('Chargement des donnees de sante...');
API.getHealth().then(function(data) {
console.log('Donnees de sante:', data);
});
Tester la sortie JSON :
# Sur le routeur
/usr/libexec/rpcd/luci.system-hub call get_health | jsonlint
# Verifier les erreurs courantes
# - Virgules manquantes
# - Virgules en fin de liste
# - Cles non quotees
# - Sequences d'echappement invalides
Resume des Bonnes Pratiques
A FAIRE :
- Utiliser le prefixe
luci.pour tous les objets ubus - Nommer les scripts RPCD pour correspondre exactement a l'objet ubus
- Utiliser
baseclass.extend()pour les modules API - Importer les APIs avec le pattern
'require module/api as API' - Ajouter des verifications null/undefined dans le frontend :
health.cpu?.usage || 0 - Valider le JSON avec
jsonlintavant de deployer - Tester avec
ubus callavant les tests navigateur - Redemarrer RPCD apres les changements backend
- Vider le cache du navigateur apres les changements frontend
- Executer
./secubox-tools/validate-modules.shavant de commiter
A NE PAS FAIRE :
- Utiliser des noms d'objets ubus sans le prefixe
luci. - Utiliser
baseclass.singleton()ou des objets simples pour les modules API - Importer les APIs avec
L.require('module.path')(retourne la classe, pas l'instance) - Oublier d'ajouter les methodes au fichier ACL
- Melanger les methodes lecture/ecriture dans les sections ACL
- Produire du non-JSON depuis les scripts RPCD
- Utiliser des structures de donnees incoherentes entre backend et frontend
- Deployer sans tester localement d'abord
- Supposer que les donnees existent - toujours verifier null/undefined
- Oublier de rendre les scripts RPCD executables (
chmod +x)
Historique des Versions
v1.0 (2025-12-26)
- Guide de reference initial
- Base sur luci-app-secubox v1.0.0 et luci-app-system-hub v0.1.0
- Documentation de tous les patterns critiques et erreurs courantes
- Valide contre les defis d'implementation reels
References
- Documentation OpenWrt : https://openwrt.org/docs/guide-developer/start
- Documentation LuCI : https://github.com/openwrt/luci/wiki
- Documentation ubus : https://openwrt.org/docs/techref/ubus
- Documentation UCI : https://openwrt.org/docs/guide-user/base-system/uci
- Bibliotheque jshn.sh :
/usr/share/libubox/jshn.shsur OpenWrt
Contact
Pour des questions ou contributions a ce guide de reference :
- Auteur : CyberMind contact@cybermind.fr
- Projet : SecuBox OpenWrt
- Depot : https://github.com/cybermind-fr/secubox-openwrt
FIN DU GUIDE DE REFERENCE