LoadConfig gagne la forme "relay-router" (ECS multipalier rév. 3) : liste de relais
power (relays[] = [{thingId, powerW}]) + minOnS/minOffS. Coexiste avec la forme
"etmvariableload" (continu/dynamic ou multipalier natif). powerLevels NON stockés pour
le cas relais (DÉRIVÉS par le routeur en étape 3-4).
- LoadConfigRelay (struct) + relays/minOnS/minOffS dans LoadConfig (Q_GADGET + toMap/fromMap).
- isValid() CONDITIONNELLE au type (adapter/mode), pas "tous champs requis" :
relay-router → relays[] valides ; etmvariableload → powerLevels (fixed) | maxPowerW (dynamic).
- Schéma SET : TOUS les champs spécifiques en "o:" (powerLevels, maxPowerW, relays, minOnS,
minOffS, needs) — sinon nymea rejette une des deux formes avant le handler (bug objectRef
strict de T4, doublé en rév. 3). GET reste typé objectRef<LoadConfig>.
- testLoadConfigRpc étendu : SET des DEUX formes (etmvariableload + relay-router) tous deux
acceptés, round-trip relays[]/minOnS, rejets conditionnels (powerLevels sans 0 ; relays[] vide).
Build prod 0/0 ; suite config/L2/migrés verte.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pont moteur↔app : déclaration des charges etmvariableload persistée et éditable,
construction des adaptateurs à chaud depuis la config (remplace le registre en dur).
- LoadConfig / LoadConfigNeeds (Q_GADGET typés, introspectables) — forme mot pour mot
du LoadDescriptor §4 (jonction inter-repos avec l'app).
- LoadConfigStore : persistance atomique /var/lib/nymea/energy-load-configuration.json,
validation en bloc, signal changed().
- Handler NymeaEnergy.GetLoadConfig / SetLoadConfig (+ notif LoadConfigChanged). GET typé
objectRef<LoadConfig> ; SET schéma inline o: (powerLevels/needs conditionnels §4).
- EnergyArbitrator : setLoadConfigStore + rebuildEtmVariableLoadAdapters (enabled==true
seulement, §9) ; repli L2 = setPowerSetpoint(0) force=true sur tout etmvariableload
(ferme le trou sécurité ouvert en T2).
- Tests simulation : migration ECS→etmvariableload (arrondi fixed/dynamic, recrédit,
délestage, round-trip powerSetpoint), budget partagé etmvariableload↔PAC, watchdog L2
réactivé, persistance + construction depuis config + injection RPC end-to-end.
PAC SG-Ready reste hors config (§8, gelée). Les 5 tâches du brief sont couvertes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>