- evcharger.cpp: phases() now calls meteredPhases() instead of returning PhaseNone - smartchargingmanager: add chargerPhaseKey() with 3-level fallback 1. meteredPhases() when charger is active 2. effectivePhases from last known state 3. fallback 'A' + warning (previous behavior) - Remove 4 FIXME comments on lines 394, 477, 517
174 lines
6.0 KiB
Markdown
174 lines
6.0 KiB
Markdown
# Agent Plugin — `powersync-energy-plugin-etm` (GPL3)
|
|
> Lire aussi le `CLAUDE.md` du dossier parent avant de commencer.
|
|
|
|
---
|
|
|
|
## Mon rôle
|
|
Je suis le **plugin nymea Community** du HEMS ETM-PowerSync.
|
|
Je contiens toute la logique GPL3 : recharge EV sur surplus, tarif HP/HC,
|
|
protection surcharge, et le pont vers `powersync-optimizer` pour les tiers payants.
|
|
|
|
**Licence : GPL3** — tout mon code est open-source assumé.
|
|
Origine : fork de nymea-energy-plugin-nymea (source nymea/Chargebyte, GPL3).
|
|
Pas de remote upstream Git public — mises à jour via portage manuel depuis
|
|
`etm-nymea/nymea-energy-plugin-nymea`.
|
|
|
|
---
|
|
|
|
## Règle fondamentale
|
|
|
|
```
|
|
Ce repo = fonctionnalités Community UNIQUEMENT.
|
|
Zéro logique Auto / Predict AI dans ce repo.
|
|
Ces features passent exclusivement par PowerSyncClient → optimizer.
|
|
```
|
|
|
|
---
|
|
|
|
## Ce que je FOURNIS
|
|
|
|
### API JSON-RPC `EnergyPlugin.*`
|
|
| Méthode | Rôle | Tier |
|
|
|---|---|---|
|
|
| `GetChargingInfos(evChargerId)` | Config recharge EV | Community |
|
|
| `SetChargingInfo(chargingInfo)` | Mettre à jour config borne EV | Community |
|
|
| `GetChargingSchedules(evChargerId)` | Planning calculé | Community |
|
|
| `GetAvailableSpotMarketProviders()` | Liste providers tarifs | Community |
|
|
| `SetSpotMarketConfiguration(enabled, providerId)` | Activer provider | Community |
|
|
| `GetSpotMarketScoreEntries(date)` | Cotations horaires | Community |
|
|
| `SetPhasePowerLimit(Uint)` | Protection surcharge | Community |
|
|
| `SetAcquisitionTolerance(Double)` | Seuil surplus | Community |
|
|
| `SetBatteryLevelConsideration(Double)` | Facteur batterie | Community |
|
|
|
|
### Notifications push
|
|
`ChargingInfoAdded/Removed/Changed`, `ChargingSchedulesChanged`,
|
|
`SpotMarketConfigurationChanged`, `SpotMarketScoreEntriesChanged`,
|
|
`PhasePowerLimitChanged`
|
|
|
|
### `.so` produit
|
|
```
|
|
libnymea_energypluginnymea.so ← nom identique à l'upstream (drop-in replacement)
|
|
install : /usr/lib/nymea/energy/
|
|
```
|
|
|
|
---
|
|
|
|
## Ce que je CONSOMME
|
|
|
|
### Interfaces nymea (par interface, jamais par ThingClassId)
|
|
| Interface | États lus | Actions envoyées |
|
|
|---|---|---|
|
|
| `evcharger` | `chargingEnabled`, `maxChargingCurrent`, `pluggedIn`, `charging`, phases | `setChargingEnabled`, `setMaxChargingCurrent` |
|
|
| `electricvehicle` | `batteryLevel`, `maxChargingCurrent`, `capacity` | — |
|
|
| `rootmeter` / `energymeter` | `currentPowerPhaseA/B/C`, `currentPhaseA/B/C` | — |
|
|
| `energystorage` | `currentPower`, `batteryLevel` | — |
|
|
|
|
### Signal déclencheur
|
|
`PowerBalanceEntryAdded` depuis `nymea-experience-plugin-energy` → cycle ~1 min.
|
|
|
|
### Service propriétaire (optionnel)
|
|
`PowerSyncClient` → Unix socket `/run/powersync/optimizer.sock`
|
|
Si absent → mode Community local, aucune erreur.
|
|
|
|
---
|
|
|
|
## Architecture interne
|
|
|
|
```
|
|
powersync-energy-plugin-etm/
|
|
│
|
|
├── [code upstream nymea/Chargebyte] ← ne pas modifier directement
|
|
│ ├── SmartChargingManager.* ← à corriger (bugs phase EV)
|
|
│ ├── SpotMarketManager.* ← aWATTar AT/DE ✅
|
|
│ └── NymeaEnergyJsonHandler.* ← API JSON-RPC
|
|
│
|
|
└── etm/ ← tout notre code ETM ici
|
|
├── PowerSyncClient.* ← pont vers optimizer (Unix socket)
|
|
├── tariff/
|
|
│ └── StaticHcHpProvider.* ← HP/HC statique (Community)
|
|
└── [futures extensions Community]
|
|
```
|
|
|
|
---
|
|
|
|
## PowerSyncClient — le pont vers l'optimizer
|
|
|
|
```cpp
|
|
class PowerSyncClient : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
// Vérifie si powersync-optimizer tourne
|
|
bool isAvailable() const;
|
|
|
|
// Demande une décision d'optimisation (Auto/Predict AI)
|
|
OptimizationResult requestOptimization(const SurplusData &data);
|
|
|
|
// Récupère la météo J+1 (Auto)
|
|
WeatherForecast getWeatherForecast();
|
|
|
|
// Récupère le tarif dynamique courant (Predict AI)
|
|
TariffData getDynamicTariff();
|
|
|
|
signals:
|
|
void availabilityChanged(bool available);
|
|
void optimizationResultReceived(OptimizationResult result);
|
|
};
|
|
```
|
|
|
|
**Comportement du cycle principal :**
|
|
```cpp
|
|
void SmartChargingManager::runCycle() {
|
|
if (m_powerSyncClient->isAvailable()) {
|
|
// Auto / Predict AI — délègue à l'optimizer
|
|
auto result = m_powerSyncClient->requestOptimization(buildSurplusData());
|
|
applyOptimizationResult(result);
|
|
} else {
|
|
// Community — logique GPL3 locale
|
|
planSurplusCharging(); // EV sur surplus
|
|
planSpotMarketCharging(); // EV sur aWATTar
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## État actuel du code
|
|
|
|
### ✅ Fonctionnel
|
|
- SmartChargingManager : recharge EV surplus (mode Eco) + aWATTar AT/DE
|
|
- Overload protection triphasée
|
|
- API JSON-RPC `EnergyPlugin.*` complète
|
|
- Détection appareils par interface (zéro UUID hardcodé)
|
|
|
|
### ❌ À corriger en priorité
|
|
| Fichier | Problème | Priorité |
|
|
|---|---|---|
|
|
| `evcharger.cpp:171`, `smartchargingmanager.cpp:394,477,517` | Assume toujours phase A — faux pour EV sur phase B/C | 🔴 |
|
|
| `EnergyPluginNymea::init()` | Pas de guard si `EnergyManager*` null | 🟠 |
|
|
| `smartchargingmanager.cpp:59` | Récurrence hebdo non terminée | 🟠 |
|
|
| `smartchargingmanager.cpp:884` | Planification limitée à 24h | 🟠 |
|
|
| `smartchargingmanager.cpp:1835` | Actions EV non séquentielles, pas de retry | 🟠 |
|
|
|
|
### ❌ À créer (code ETM dans `etm/`)
|
|
- `PowerSyncClient` (pont Unix socket vers optimizer)
|
|
- `StaticHcHpProvider` (tarif HP/HC statique — Community)
|
|
|
|
---
|
|
|
|
## Règles de modification
|
|
|
|
- Tout code ETM va dans `etm/` — jamais dans le code upstream
|
|
- Modifier le code upstream uniquement pour corriger des bugs (FIXME existants)
|
|
- Tout changement d'API `EnergyPlugin.*` → mettre à jour `INTERFACE.md`
|
|
- Ne jamais ajouter de logique Auto/Predict AI dans ce repo
|
|
- Build : `qmake energyplugin.pro && make -j$(nproc)`
|
|
|
|
---
|
|
|
|
## Portage des mises à jour nymea/Chargebyte
|
|
|
|
Quand une nouvelle version est disponible dans `etm-nymea/nymea-energy-plugin-nymea` :
|
|
1. `diff -r etm-nymea/nymea-energy-plugin-nymea/ powersync-energy-plugin-etm/`
|
|
2. Porter manuellement les corrections hors dossier `etm/`
|
|
3. Ne jamais écraser `etm/`
|