- 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
6.0 KiB
Agent Plugin — powersync-energy-plugin-etm (GPL3)
Lire aussi le
CLAUDE.mddu 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
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 :
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 à jourINTERFACE.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 :
diff -r etm-nymea/nymea-energy-plugin-nymea/ powersync-energy-plugin-etm/- Porter manuellement les corrections hors dossier
etm/ - Ne jamais écraser
etm/