633 lines
18 KiB
Markdown
633 lines
18 KiB
Markdown
# 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 :** 0–8 (`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 :**
|
||
```json
|
||
{ "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 :**
|
||
```json
|
||
{ "phasePowerLimit": 25 }
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "energyError": "EnergyErrorNoError" }
|
||
```
|
||
|
||
---
|
||
|
||
### Paramètres de recharge
|
||
|
||
#### `NymeaEnergy.GetAcquisitionTolerance`
|
||
Retourne le seuil de surplus nécessaire pour démarrer une recharge Eco.
|
||
|
||
**Params :** aucun
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "acquisitionTolerance": 0.5 }
|
||
```
|
||
> Valeur entre 0.0 et 1.0. Plus la valeur est haute, plus il faut de surplus.
|
||
|
||
---
|
||
|
||
#### `NymeaEnergy.SetAcquisitionTolerance`
|
||
**Params :**
|
||
```json
|
||
{ "acquisitionTolerance": 0.5 }
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "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 :**
|
||
```json
|
||
{ "batteryLevelConsideration": 0.9 }
|
||
```
|
||
> 0.0 = stockage ignoré, 1.0 = surplus réduit intégralement de la puissance de charge batterie.
|
||
|
||
---
|
||
|
||
#### `NymeaEnergy.SetBatteryLevelConsideration`
|
||
**Params :**
|
||
```json
|
||
{ "batteryLevelConsideration": 0.9 }
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "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 :**
|
||
```json
|
||
{ "lockOnUnplug": false }
|
||
```
|
||
|
||
---
|
||
|
||
#### `NymeaEnergy.SetLockOnUnplug`
|
||
**Params :**
|
||
```json
|
||
{ "lockOnUnplug": true }
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "energyError": "EnergyErrorNoError" }
|
||
```
|
||
|
||
---
|
||
|
||
### Configuration EV
|
||
|
||
#### `NymeaEnergy.GetChargingInfos`
|
||
Retourne la configuration de recharge de toutes les bornes, ou d'une seule.
|
||
|
||
**Params :**
|
||
```json
|
||
{ "o:evChargerId": "uuid-de-la-borne" }
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{
|
||
"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 :**
|
||
```json
|
||
{
|
||
"chargingInfo": {
|
||
"evChargerId": "uuid-de-la-borne",
|
||
"chargingMode": "ChargingModeEcoWithTargetTime",
|
||
"endDateTime": "2025-06-15T08:00:00+02:00",
|
||
"targetPercentage": 80
|
||
}
|
||
}
|
||
```
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "energyError": "EnergyErrorNoError" }
|
||
```
|
||
|
||
---
|
||
|
||
#### `NymeaEnergy.GetChargingSchedules`
|
||
Retourne le planning de recharge calculé (toutes les bornes, horizon ~24h).
|
||
|
||
**Params :** aucun
|
||
|
||
**Returns :**
|
||
```json
|
||
{
|
||
"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 :**
|
||
```json
|
||
{
|
||
"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 :**
|
||
```json
|
||
{
|
||
"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 :**
|
||
```json
|
||
{
|
||
"enabled": true,
|
||
"o:providerId": "5196b3cc-b2ee-46d6-b63a-7af2cf70ba67"
|
||
}
|
||
```
|
||
> Si `enabled: true`, `providerId` est obligatoire et doit être un UUID valide.
|
||
|
||
**Returns :**
|
||
```json
|
||
{ "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 :**
|
||
```json
|
||
{
|
||
"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`
|
||
```json
|
||
{ "phasePowerLimit": 25 }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.AcquisitionToleranceChanged`
|
||
```json
|
||
{ "acquisitionTolerance": 0.5 }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.BatteryLevelConsiderationChanged`
|
||
```json
|
||
{ "batteryLevelConsideration": 0.9 }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.LockOnUnplugChanged`
|
||
```json
|
||
{ "lockOnUnplug": true }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.ChargingInfoAdded`
|
||
Émis quand une nouvelle borne est détectée et sa `ChargingInfo` créée.
|
||
```json
|
||
{ "chargingInfo": { ... } }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.ChargingInfoRemoved`
|
||
Émis quand une borne est supprimée.
|
||
```json
|
||
{ "evChargerThingId": "uuid-de-la-borne" }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.ChargingInfoChanged`
|
||
Émis à chaque modification de la `ChargingInfo` (config ou état).
|
||
```json
|
||
{ "chargingInfo": { ... } }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.ChargingSchedulesChanged`
|
||
Émis à chaque recalcul du planning (cycle ~1 min).
|
||
```json
|
||
{ "chargingSchedules": [ ... ] }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.SpotMarketConfigurationChanged`
|
||
Émis quand le provider actif, l'état enabled ou l'état available change.
|
||
```json
|
||
{
|
||
"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).
|
||
```json
|
||
{ "enabled": true, "available": true }
|
||
```
|
||
|
||
---
|
||
|
||
### `NymeaEnergy.SpotMarketScoreEntriesChanged`
|
||
Émis quand les cotations sont mises à jour par le provider.
|
||
```json
|
||
{ "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 :**
|
||
```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 [0–1] | 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).
|