- Pluggable multi-provider architecture (ReferenceEngine) - Wassup provider implementation (HTTP GET + X_WASSUP_USER_IP) - Auto-resolve references on Inform (BOOT/BOOTSTRAP events) - References displayed in device Identity card - REST API: GET/POST references per device - Config via config/references.json - Fix event extraction for single EventStruct and numeric EventCodes - Mock Wassup provisioned by home-device-simulator on device creation
8.7 KiB
8.7 KiB
Feature : Références Client — Système de Providers Pluggable
Contexte
Dans adam-acs, on veut un système de références externes (informations client) associées aux devices. Inspiré de Wassup (karma-com) mais conçu comme un système de plugins permettant de brancher N fournisseurs de données.
Principe : N Providers
Chaque device peut être enrichi par plusieurs providers indépendants. Chaque provider est un service externe interrogé via HTTP qui retourne des paires clé-valeur.
┌─────────────────────────────────────┐
│ adam-acs │
│ │
│ DeviceRecord │
│ └─ references: [ │
Inform ──────► │ { provider: "wassup", ... } │
│ { provider: "crm", ... } │
│ { provider: "noc", ... } │
│ ] │
│ │
│ ReferenceEngine │
│ ├─ WassupProvider │───► Wassup (HTTP)
│ ├─ CRMProvider │───► CRM API
│ └─ NOCProvider │───► NOC API
└─────────────────────────────────────┘
Architecture
Interface Provider
Chaque provider implémente une interface commune :
interface ReferenceProvider {
/** Identifiant unique du provider (ex: "wassup", "crm") */
name: string
/** Résout les références pour un device. Retourne null si non applicable. */
resolve(device: DeviceRecord, context: InformContext): Promise<ResolvedReference | null>
/** Indique si ce provider est activé */
enabled: boolean
}
interface ResolvedReference {
provider: string
resolvedAt: Date
resolvedBy: string // ex: "ip:10.0.0.1"
properties: Record<string, string>
status: 'ok' | 'unknown' | 'error'
error?: string
}
interface InformContext {
events: string[]
remoteIp: string
headers: Record<string, string>
}
ReferenceEngine (orchestrateur)
class ReferenceEngine {
private providers: ReferenceProvider[] = []
register(provider: ReferenceProvider): void
/** Résout tous les providers pour un device (en parallèle) */
async resolveAll(device: DeviceRecord, context: InformContext): Promise<ResolvedReference[]>
/** Résout un seul provider par nom */
async resolveOne(providerName: string, device: DeviceRecord, context: InformContext): Promise<ResolvedReference | null>
}
Modèle de données (MongoDB)
// Ajouté à DeviceRecord
interface DeviceRecord {
// ... champs existants ...
references?: DeviceReference[]
}
interface DeviceReference {
provider: string
resolvedAt: Date
resolvedBy: string
status: 'ok' | 'unknown' | 'error'
properties: Record<string, string>
error?: string
}
Configuration : config/references.json
Fichier de config qui déclare les providers actifs et leur paramétrage :
{
"providers": [
{
"name": "wassup",
"type": "wassup",
"enabled": true,
"url": "http://wassup-mock:9999",
"timeout": 3000,
"trigger": ["BOOT", "BOOTSTRAP"],
"resolveBy": "ip",
"requestedProperties": ["sai", "spr", "clo", "puid", "utz"]
},
{
"name": "crm",
"type": "http-json",
"enabled": false,
"url": "http://crm-api:8080/api/customers",
"timeout": 5000,
"trigger": ["BOOT"],
"resolveBy": "serialNumber",
"mapping": {
"requestParam": "serial",
"responseMapping": {
"customerId": "id",
"customerName": "name",
"offer": "subscription.offer"
}
}
}
]
}
Types de providers supportés
| Type | Description | Protocole |
|---|---|---|
wassup |
Protocole Wassup (HTTP GET + headers + text/plain response) | Conforme au format Wassup Orange |
http-json |
API REST standard (GET avec query params, réponse JSON) | Générique |
http-properties |
HTTP GET avec réponse key=value (Java properties) | Générique |
static |
Valeurs statiques déclarées dans la config (pas d'appel externe) | Local |
Champ resolveBy — Comment identifier le device auprès du provider
| Valeur | Source dans le device | Exemple |
|---|---|---|
ip |
Header x-forwarded-for de l'Inform ou IP source |
10.0.0.1 |
serialNumber |
device.deviceId.serialNumber |
LB4-TEST-001 |
oui |
device.deviceId.oui |
F8B7FF |
mac |
Paramètre MACAddress du device | F8:B7:FF:00:11:22 |
parameter:<path> |
Valeur d'un paramètre du device | Device.ManagementServer.Username |
Champ trigger — Quand déclencher la résolution
| Valeur | Événement |
|---|---|
BOOT |
Event "1 BOOT" |
BOOTSTRAP |
Event "0 BOOTSTRAP" |
PERIODIC |
Event "2 PERIODIC" |
SCHEDULED |
Event "3 SCHEDULED" |
CONNECTION_REQUEST |
Event "6 CONNECTION REQUEST" |
MANUAL |
Uniquement via API (pas automatique) |
Intégration dans le flux Inform
// Dans cwmp_controller.ts → handleInform(), après persist device :
const informContext: InformContext = { events, remoteIp: request.ip(), headers: request.headers() }
const references = await referenceEngine.resolveAll(device, informContext)
if (references.length > 0) {
await DeviceModel.updateReferences(hashId, references)
}
API REST
| Méthode | Route | Description |
|---|---|---|
GET |
/api/v1/devices/:id/references |
Toutes les références du device |
GET |
/api/v1/devices/:id/references/:provider |
Références d'un provider spécifique |
POST |
/api/v1/devices/:id/references/resolve |
Déclencher la résolution (tous les providers) |
POST |
/api/v1/devices/:id/references/resolve/:provider |
Résoudre un seul provider |
PUT |
/api/v1/devices/:id/references/:provider |
Mettre à jour manuellement |
DELETE |
/api/v1/devices/:id/references/:provider |
Supprimer les références d'un provider |
UI (DeviceDetail.vue)
Nouvelle section collapsible "Références" dans la page device :
┌─────────────────────────────────────────────────┐
│ Références (2 providers) ▾ │
├─────────────────────────────────────────────────┤
│ 🟢 wassup — résolu le 02/06/2026 via ip:10.0.0.1│
│ SAI: 088913491 │
│ SPR: EN │
│ CLO: pppLB.user │
│ [Rafraîchir] │
│ │
│ ⚪ crm — non résolu (désactivé) │
└─────────────────────────────────────────────────┘
Fichiers à créer/modifier dans adam-acs
| Fichier | Action |
|---|---|
config/references.json |
Créer — configuration des providers |
app/domain/device/device_record.ts |
Modifier — ajouter references?: DeviceReference[] |
app/services/references/reference_engine.ts |
Créer — orchestrateur |
app/services/references/providers/wassup_provider.ts |
Créer — provider Wassup |
app/services/references/providers/http_json_provider.ts |
Créer — provider HTTP JSON générique |
app/services/references/types.ts |
Créer — interfaces et types |
app/controllers/references_controller.ts |
Créer — API REST |
app/controllers/cwmp_controller.ts |
Modifier — appel ReferenceEngine dans handleInform |
inertia/pages/DeviceDetail.vue |
Modifier — section Références |
start/routes.ts |
Modifier — ajouter routes references |
Mock Wassup (gogowassupgo)
Déjà implémenté et testé. Le mock tourne dans Docker (wassup-mock:9999) et est provisionné automatiquement par le simulateur lors de la création de devices.
- Protocole : identique à Wassup (HTTP GET +
X_WASSUP_USER_IP) - Provisioning : API
/admin/entries(POST/GET/DELETE) - Stockage :
data/entries.json - Modes d'erreur :
--error http-500,--error-status KO,--delay 2s