Patrick Schurig b8e882616b docs: document internal data flow and EnergyManagerConfiguration in INTERFACE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 09:13:04 +02:00

18 KiB
Raw Permalink Blame History

INTERFACE.md — API JSON-RPC du plugin nymea-energy-plugin-nymea

Ce fichier fait autorité sur l'interface exposée par le plugin. Mettre à jour ce fichier à chaque modification de l'API.

Namespace : NymeaEnergy Versions enregistrées : 08 (registerExperienceHandler(..., 0, 8)) Transport : WebSocket JSON-RPC 2.0, port 4444 (nymea standard)


Enums

ChargingMode

Valeur Description
ChargingModeNormal Recharge immédiate au maximum disponible
ChargingModeEco Recharge sur surplus solaire uniquement
ChargingModeEcoWithTargetTime Eco + deadline de fin (endDateTime + targetPercentage)
ChargingModeEcoWithMinCurrent Eco + courant minimum garanti (6 A) si pas de surplus
ChargingModeEcoMinWithTargetTime Eco + courant minimum + deadline

ChargingState (lecture seule — calculé par le manager)

Valeur Description
ChargingStateIdle Pas de recharge active
ChargingStateSurplusCharging Recharge sur surplus solaire en cours
ChargingStateSpotMarketCharging Recharge sur créneau spot market en cours
ChargingStateTimeRequirement Recharge forcée pour atteindre la deadline

ChargingActionIssuer

Valeur Description
ChargingActionIssuerUnknown Émetteur non identifié
ChargingActionIssuerSurplusCharging Action émise par le surplus manager
ChargingActionIssuerSpotMarketCharging Action émise par le spot market manager
ChargingActionIssuerTimeRequirement Action émise pour honorer la deadline
ChargingActionIssuerOverloadProtection Action émise par la protection surcharge

EnergyError

Valeur Description
EnergyErrorNoError Succès
EnergyErrorMissingParameter Paramètre obligatoire absent
EnergyErrorInvalidParameter Valeur de paramètre invalide

Types

ChargingInfo

Configuration d'une borne EV. Seuls les champs marqués (writable) peuvent être modifiés via SetChargingInfo — les autres sont ignorés ou read-only.

Champ Type Writable Description
evChargerId Uuid Identifiant de la borne (obligatoire dans SetChargingInfo)
assignedCarId Uuid Véhicule associé (optionnel)
chargingMode ChargingMode Mode de recharge
endDateTime DateTime Deadline cible (EcoWithTargetTime / EcoMinWithTargetTime)
repeatDays [Int] Jours de répétition (0=Lun … 6=Dim, liste vide = pas de répétition)
targetPercentage Uint Niveau batterie cible en % (défaut : 80)
chargingState ChargingState État calculé (lecture seule)
spotMarketChargingEnabled Bool Activer la recharge sur spot market
dailySpotMarketPercentage Uint % de la charge quotidienne à faire en heures spot bon marché

ChargingAction

Action envoyée au charger physique (présente dans les schedules).

Champ Type Description
chargingEnabled Bool Activer/désactiver la recharge
maxChargingCurrent Double Courant max en Ampères
desiredPhaseCount Uint Nombre de phases souhaitées (1 ou 3)
issuer ChargingActionIssuer Origine de la décision

ChargingSchedule

Créneau de recharge planifié (résultat du calcul du manager).

Champ Type Description
evChargerId Uuid Borne concernée
startDateTime DateTime Début du créneau
endDateTime DateTime Fin du créneau
action ChargingAction Action prévue sur ce créneau

ScoreEntry

Entrée de cotation horaire du spot market, avec pondération relative.

Champ Type Description
startDateTime DateTime Début du créneau tarifaire
endDateTime DateTime Fin du créneau tarifaire
value Float Prix brut (€/MWh, selon provider)
weighting Float Pondération relative : 0.0 = le plus cher, 1.0 = le moins cher

SpotMarketProviderInfo

Fournisseur de données spot market disponible.

Champ Type Description
providerId Uuid Identifiant du provider
name String Nom affiché
country Uint Pays (QLocale::Country)
website String URL du site du provider

Providers enregistrés :

Nom providerId
aWATTar AT 5196b3cc-b2ee-46d6-b63a-7af2cf70ba67
aWATTar DE 0ca6ad88-e243-438d-a0f8-986cecf61834

Méthodes

Notation : o: = paramètre optionnel. Tous les appels requièrent un token d'auth nymea.


Overload protection

NymeaEnergy.GetPhasePowerLimit

Retourne la limite de courant par phase configurée.

Params : aucun

Returns :

{ "phasePowerLimit": 25 }

0 signifie non configuré — tout le smart charging est désactivé.


NymeaEnergy.SetPhasePowerLimit

Définit la limite de courant par phase (en Ampères). 0 désactive le smart charging.

Params :

{ "phasePowerLimit": 25 }

Returns :

{ "energyError": "EnergyErrorNoError" }

Paramètres de recharge

NymeaEnergy.GetAcquisitionTolerance

Retourne le seuil de surplus nécessaire pour démarrer une recharge Eco.

Params : aucun

Returns :

{ "acquisitionTolerance": 0.5 }

Valeur entre 0.0 et 1.0. Plus la valeur est haute, plus il faut de surplus.


NymeaEnergy.SetAcquisitionTolerance

Params :

{ "acquisitionTolerance": 0.5 }

Returns :

{ "energyError": "EnergyErrorNoError" }

Retourne EnergyErrorInvalidParameter si hors de [0.0, 1.0].


NymeaEnergy.GetBatteryLevelConsideration

Retourne le facteur de prise en compte du stockage batterie dans le calcul du surplus.

Params : aucun

Returns :

{ "batteryLevelConsideration": 0.9 }

0.0 = stockage ignoré, 1.0 = surplus réduit intégralement de la puissance de charge batterie.


NymeaEnergy.SetBatteryLevelConsideration

Params :

{ "batteryLevelConsideration": 0.9 }

Returns :

{ "energyError": "EnergyErrorNoError" }

Retourne EnergyErrorInvalidParameter si hors de [0.0, 1.0].


NymeaEnergy.GetLockOnUnplug

Retourne si la borne doit être verrouillée à la déconnexion du véhicule.

Params : aucun

Returns :

{ "lockOnUnplug": false }

NymeaEnergy.SetLockOnUnplug

Params :

{ "lockOnUnplug": true }

Returns :

{ "energyError": "EnergyErrorNoError" }

Configuration EV

NymeaEnergy.GetChargingInfos

Retourne la configuration de recharge de toutes les bornes, ou d'une seule.

Params :

{ "o:evChargerId": "uuid-de-la-borne" }

Returns :

{
  "chargingInfos": [
    {
      "evChargerId": "uuid-de-la-borne",
      "assignedCarId": "uuid-du-car",
      "chargingMode": "ChargingModeEco",
      "chargingState": "ChargingStateSurplusCharging",
      "endDateTime": "2025-06-15T08:00:00+02:00",
      "repeatDays": [1, 2, 3, 4, 5],
      "targetPercentage": 80,
      "spotMarketChargingEnabled": false,
      "dailySpotMarketPercentage": 0
    }
  ]
}

NymeaEnergy.SetChargingInfo

Met à jour la configuration d'une borne. Seuls les champs USER true sont modifiables (voir type ChargingInfo). Les autres champs sont ignorés.

Params :

{
  "chargingInfo": {
    "evChargerId": "uuid-de-la-borne",
    "chargingMode": "ChargingModeEcoWithTargetTime",
    "endDateTime": "2025-06-15T08:00:00+02:00",
    "targetPercentage": 80
  }
}

Returns :

{ "energyError": "EnergyErrorNoError" }

NymeaEnergy.GetChargingSchedules

Retourne le planning de recharge calculé (toutes les bornes, horizon ~24h).

Params : aucun

Returns :

{
  "chargingSchedules": [
    {
      "evChargerId": "uuid-de-la-borne",
      "startDateTime": "2025-06-15T02:00:00+02:00",
      "endDateTime": "2025-06-15T04:30:00+02:00",
      "action": {
        "chargingEnabled": true,
        "maxChargingCurrent": 16.0,
        "desiredPhaseCount": 1,
        "issuer": "ChargingActionIssuerSpotMarketCharging"
      }
    }
  ]
}

Spot market

NymeaEnergy.GetAvailableSpotMarketProviders

Retourne la liste des providers spot market disponibles.

Params : aucun

Returns :

{
  "providers": [
    {
      "providerId": "5196b3cc-b2ee-46d6-b63a-7af2cf70ba67",
      "name": "aWATTar AT",
      "country": 14,
      "website": "https://www.awattar.at"
    },
    {
      "providerId": "0ca6ad88-e243-438d-a0f8-986cecf61834",
      "name": "aWATTar DE",
      "country": 82,
      "website": "https://www.awattar.de"
    }
  ]
}

NymeaEnergy.GetSpotMarketConfiguration

Retourne la configuration spot market courante.

Params : aucun

Returns :

{
  "enabled": true,
  "available": true,
  "o:providerId": "5196b3cc-b2ee-46d6-b63a-7af2cf70ba67"
}

providerId est absent si enabled est false.


NymeaEnergy.SetSpotMarketConfiguration

Active ou désactive le spot market et sélectionne le provider.

Params :

{
  "enabled": true,
  "o:providerId": "5196b3cc-b2ee-46d6-b63a-7af2cf70ba67"
}

Si enabled: true, providerId est obligatoire et doit être un UUID valide.

Returns :

{ "energyError": "EnergyErrorNoError" }

Retourne EnergyErrorInvalidParameter si enabled: true sans providerId, ou providerId inconnu.


NymeaEnergy.GetSpotMarketScoreEntries

Retourne les cotations pondérées du provider actif. Liste vide si désactivé ou non disponible.

Params : aucun

Returns :

{
  "spotMarketScoreEntries": [
    {
      "startDateTime": "2025-06-15T00:00:00+02:00",
      "endDateTime": "2025-06-15T01:00:00+02:00",
      "value": 45.2,
      "weighting": 0.85
    }
  ]
}

Notifications

S'abonner via JSONRPC.SetNotificationStatus avec le namespace "NymeaEnergy".


NymeaEnergy.PhasePowerLimitChanged

{ "phasePowerLimit": 25 }

NymeaEnergy.AcquisitionToleranceChanged

{ "acquisitionTolerance": 0.5 }

NymeaEnergy.BatteryLevelConsiderationChanged

{ "batteryLevelConsideration": 0.9 }

NymeaEnergy.LockOnUnplugChanged

{ "lockOnUnplug": true }

NymeaEnergy.ChargingInfoAdded

Émis quand une nouvelle borne est détectée et sa ChargingInfo créée.

{ "chargingInfo": { ... } }

NymeaEnergy.ChargingInfoRemoved

Émis quand une borne est supprimée.

{ "evChargerThingId": "uuid-de-la-borne" }

NymeaEnergy.ChargingInfoChanged

Émis à chaque modification de la ChargingInfo (config ou état).

{ "chargingInfo": { ... } }

NymeaEnergy.ChargingSchedulesChanged

Émis à chaque recalcul du planning (cycle ~1 min).

{ "chargingSchedules": [ ... ] }

NymeaEnergy.SpotMarketConfigurationChanged

Émis quand le provider actif, l'état enabled ou l'état available change.

{
  "enabled": true,
  "available": true,
  "o:providerId": "5196b3cc-b2ee-46d6-b63a-7af2cf70ba67"
}

NymeaEnergy.SpotMarketStatusChanged

Émis quand enabled ou available change (sans les détails du provider).

{ "enabled": true, "available": true }

NymeaEnergy.SpotMarketScoreEntriesChanged

Émis quand les cotations sont mises à jour par le provider.

{ "spotMarketScoreEntries": [ ... ] }

Interfaces nymea consommées

Le plugin détecte les appareils par interface, jamais par ThingClassId.

Interface États lus Actions envoyées
evcharger chargingEnabled, maxChargingCurrent, pluggedIn, charging, currentPhaseA/B/C, currentPowerPhaseA/B/C setChargingEnabled, setMaxChargingCurrent
electricvehicle batteryLevel, maxChargingCurrent, capacity, minChargingCurrent, phaseCount
rootmeter / energymeter currentPowerPhaseA/B/C, currentPhaseA/B/C
energystorage currentPower, batteryLevel

Déclencheur du cycle : signal PowerBalanceEntryAdded de nymea-experience-plugin-energy (~1 min). Déclencheur overload : signal EnergyManager::powerBalanceChanged (temps réel, découplé du cycle).


EnergyManagerConfiguration

Paramètres de tuning chargés une seule fois au démarrage depuis un fichier JSON.
Pas de setters — un changement nécessite un redémarrage du daemon nymea.

Chemin (ordre de priorité) :

  1. $NYMEA_ENERGY_MANAGER_CONFIG (variable d'environnement)
  2. /var/lib/nymea/energy-manager-configuration.json
  3. Valeurs par défaut si aucun fichier trouvé

Format JSON :

{
  "chargingEnabledLockDuration": 300,
  "chargingCurrentLockDuration": 10,
  "minimumScheduleDuration": 15,
  "spotMarketChargePredictableEnergyPercentage": 0.5
}
Paramètre Défaut Unité Rôle
chargingEnabledLockDuration 300 secondes Anti-flapping : durée de verrouillage après changement ON/OFF
chargingCurrentLockDuration 10 secondes Anti-flapping : durée de verrouillage après changement de courant
minimumScheduleDuration 15 minutes Durée minimale d'un créneau spot market planifié
spotMarketChargePredictableEnergyPercentage 0.5 ratio [01] Fraction de l'énergie spot considérée "prédictible" dans le planning

Flux interne — SmartChargingManager

Entrées de données

EnergyManager::logs()::powerBalanceEntryAdded (SampleRate1Min)
    └─→ update(now)                    ← cycle principal ~1/min

EnergyManager::powerBalanceChanged             ← temps réel
    └─→ verifyOverloadProtection(now)  ← safety loop immédiate, découplée du cycle

RootMeter (wraps Thing interface=rootmeter/energymeter)
    ├── currentPower()            ← total W (négatif = surplus / export)
    ├── currentPowerPhaseA/B/C()  ← W par phase
    └── currentPhaseA/B/C()       ← A par phase

ThingManager → interface "energystorage"
    ├── batteryLevel  ← % (moyenne de tous les stockages)
    └── currentPower  ← W total (+ = charge,  = décharge)

EvCharger → interface "evcharger" + "electricvehicle"
    ├── currentPower(), maxChargingCurrent(), phaseCount()
    ├── meteredPhases()   ← phases réelles via currentPhaseA/B/C live
    └── car: batteryLevel, capacity, minChargingCurrent, phaseCount

Pipeline update() — exécuté à chaque cycle

update(currentDateTime)
  │
  ├─ 1. updateManualSoCsWithoutMeter()
  │      Estime le SoC à partir de l'énergie intégrée si pas de compteur sur le VE.
  │
  ├─ 2. prepareInformation()
  │      - Filtre les EV chargers actifs (plugged, car assignée, mode ≠ Normal)
  │      - Calcule par charger : phases effectives, SoC, temps restant, phaseLimitPower
  │      - Reset m_chargingActions à OFF/minCurrent pour les 3 issuers
  │
  ├─ 3. verifyOverloadProtection()
  │      - Lit rootMeter->currentPowerPhaseA/B/C()
  │      - Si une phase dépasse phasePowerLimit × 230 W → throttle immédiat (issuer=OverloadProtection)
  │
  ├─ 4. verifyOverloadProtectionRecovery()
  │      - Ré-active les chargers throttlés si la marge est suffisante
  │
  ├─ 5. planSpotMarketCharging()
  │      - SpotMarketManager::scheduleChargingTime() → TimeFrames (créneaux bon marché)
  │      - Remplit m_chargingSchedules + m_chargingActions[SpotMarket] = ON
  │
  ├─ 6. planSurplusCharging()
  │      - currentLoad = rootMeter->currentPower()
  │          + correction batteries (fromBatteries)
  │          + puissance ajoutée dans ce cycle (addedPower)
  │      - allowanceInAmpere = currentLoad / 230
  │      - Si allowance ≥ minCurrent × acquisitionTolerance → chargingActions[Surplus] = ON
  │
  └─ 7. adjustEvChargers()
         Applique la décision finale par priorité décroissante :
         1. TimeRequirement  → ON au max courant disponible (deadline imminente)
         2. SurplusCharging  → ON au courant surplus calculé
         3. SpotMarketCharging → ON au courant max dans le créneau
         4. EcoWithMinCurrent fallback → ON à 6 A (EcoMinChargingCurrent)
         5. Idle             → OFF
              │
              ├── executeChargingAction()
              │     └─→ Thing::executeAction(setChargingEnabled, setMaxChargingCurrent)
              │
              ├── emit chargingInfoChanged()      ← met à jour ChargingState (lu par JSON-RPC)
              └── emit chargingSchedulesChanged() ← planning rafraîchi (lu par JSON-RPC)

Persistance des settings utilisateur

Données Fichier
phasePowerLimit, acquisitionTolerance, batteryLevelConsideration EnergySettings (QSettings INI, energy.conf)
ChargingInfo par charger (mode, endDateTime, repeatDays, etc.) même EnergySettings, groupe ChargingInfos/
lockOnUnplug /var/lib/nymea/energy.conf (QSettings séparé)
SpotMarket enabled, providerId EnergySettings (géré par SpotMarketManager)

Point d'injection pour powersync-optimizer

Le point naturel est entre prepareInformation() et adjustEvChargers().
L'optimizer reçoit les données de contexte (SurplusData) et retourne une ChargingAction qui remplace ou complète les actions calculées localement. Voir PowerSyncClient::requestOptimization() dans etm/.


Notes d'intégration

  • Les timestamps sont des QDateTime sérialisés ISO 8601 avec timezone.
  • Les puissances sont en Watts, les courants en Ampères.
  • phasePowerLimit est en Ampères (par phase), pas en Watts.
  • weighting des ScoreEntry : 1.0 = créneau le moins cher, 0.0 = le plus cher.
  • SetChargingInfo est partiel : seuls les champs présents sont appliqués, sauf evChargerId qui est toujours requis.
  • currentPower du root meter est négatif quand il y a surplus solaire (export réseau).
  • Le plugin fonctionne sans powersync-optimizer (mode Community, dégradé proprement).