# 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/`