[3c-6] degradedMode() + notification ChargingSchedulesChanged + invariant zéro-cloud
virtual degradedMode() dans SmartChargingManager (base false, [ETM] additif), override EnergyArbitrator. Champ o:degradedMode (additif) dans la notification NymeaEnergy.ChargingSchedulesChanged, émise aussi aux transitions du mode dégradé (planif suspendue → push du flag via emit chargingSchedulesChanged()). INTERFACE.md : champ degradedMode documenté. SAFETY.md : notification réconciliée (ChargingSchedulesChanged, pas EnergyManagerChanged) + limite "valeur figée non détectée". Correction ZÉRO CLOUD : suppression de la section "Alertes externes" / mécanisme n8n, remplacée par une signalisation 100% locale (notification nymea in-app + buzzer/relais via règle nymea, aucun canal réseau sortant). Invariant 10 "ZÉRO cloud" gravé dans AGENTS.md. Build 0 erreur / 0 warning. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f36395f07f
commit
a524599b6f
@ -88,13 +88,35 @@ indépendante de la défaillance du contrôleur est le rôle de L3 (watchdog sys
|
|||||||
|
|
||||||
### Notification client (dans ce repo)
|
### Notification client (dans ce repo)
|
||||||
|
|
||||||
- Une notification nymea `EnergyManagerChanged` est émise avec un flag `degradedMode: true`.
|
- La notification JSON-RPC `NymeaEnergy.ChargingSchedulesChanged` porte un champ additif
|
||||||
|
`degradedMode` (bool). Elle est émise aux **transitions** du mode dégradé (entrée/sortie),
|
||||||
|
en plus des recalculs de planning. Voir `INTERFACE.md`.
|
||||||
- L'application affiche : *"Supervision compteur perdue — charge EV maintenue au minimum"*.
|
- L'application affiche : *"Supervision compteur perdue — charge EV maintenue au minimum"*.
|
||||||
|
|
||||||
### Alertes externes (hors de ce repo)
|
### Limite — détection par fraîcheur uniquement
|
||||||
|
|
||||||
Les notifications push/mail/SMS sont déclenchées via l'infra ETM (n8n) sur réception
|
Le watchdog L2 détecte l'**absence de mise à jour** du compteur (plus de signal
|
||||||
de l'événement nymea. Aucun code de notification externe dans ce plugin.
|
`powerBalanceChanged` depuis > 90 s), pas une **valeur figée**. Un compteur qui continue
|
||||||
|
d'émettre une valeur strictement constante (capteur bloqué mais lien vivant) n'est **pas**
|
||||||
|
détecté par cette couche — `m_lastMeterUpdate` reste frais. Détecter une valeur figée
|
||||||
|
(variance nulle sur fenêtre) est hors scope L2 ; le cas est couvert au niveau matériel/L0
|
||||||
|
et par la supervision externe.
|
||||||
|
|
||||||
|
### Signalisation locale (zéro cloud)
|
||||||
|
|
||||||
|
ETM PowerSync est **100 % autonome, zéro cloud** : aucune alerte ne sort vers un service
|
||||||
|
distant (ni n8n, ni mail, ni push tiers). Le système est conçu pour fonctionner **sans
|
||||||
|
internet** (argument produit : autoconsommation, local-first). Le `degradedMode` est
|
||||||
|
signalé par deux canaux strictement locaux :
|
||||||
|
|
||||||
|
- **Notification nymea in-app** (déjà implémentée : champ `degradedMode`) — canal principal
|
||||||
|
vers le client connecté à l'application.
|
||||||
|
- **Signal sonore local optionnel** (buzzer GPIO ou canal relais) piloté par une **Règle
|
||||||
|
nymea** déclenchée sur `degradedMode` — pour le client sur place, sans application.
|
||||||
|
Aucun code buzzer dans ce repo : le moteur **expose** l'état, la signalisation est une
|
||||||
|
Thing nymea + une règle (configuration d'installation, cf. `## Signalisation locale`).
|
||||||
|
|
||||||
|
**Aucun canal sortant réseau.** Voir l'invariant « ZÉRO cloud » dans `AGENTS.md`.
|
||||||
|
|
||||||
### Sortie du mode dégradé
|
### Sortie du mode dégradé
|
||||||
|
|
||||||
@ -169,6 +191,10 @@ déclenchée sur ces événements — configuration installation, documentée da
|
|||||||
Aucun code buzzer/relais dans ce repo. Principe : le moteur émet, la configuration
|
Aucun code buzzer/relais dans ce repo. Principe : le moteur émet, la configuration
|
||||||
d'installation décide quoi signaler.
|
d'installation décide quoi signaler.
|
||||||
|
|
||||||
|
**Zéro cloud** : toute la signalisation est locale (notification nymea in-app +
|
||||||
|
signalisation physique). Aucun appel réseau sortant vers un service distant — le système
|
||||||
|
fonctionne sans internet. Invariant gravé dans `AGENTS.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Correspondance couches / scénarios de défaillance
|
## Correspondance couches / scénarios de défaillance
|
||||||
|
|||||||
@ -38,6 +38,7 @@ EnergyArbitrator::EnergyArbitrator(EnergyManager *em, ThingManager *tm,
|
|||||||
if (m_degradedMode) {
|
if (m_degradedMode) {
|
||||||
qCInfo(dcNymeaEnergy()) << "[Arbitre] Compteur de nouveau actif — sortie du mode dégradé L2.";
|
qCInfo(dcNymeaEnergy()) << "[Arbitre] Compteur de nouveau actif — sortie du mode dégradé L2.";
|
||||||
m_degradedMode = false;
|
m_degradedMode = false;
|
||||||
|
emit chargingSchedulesChanged(); // pousse degradedMode=false (planif reprend au cycle suivant)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// QTimer (et non signal) : doit rester actif quand le compteur est muet.
|
// QTimer (et non signal) : doit rester actif quand le compteur est muet.
|
||||||
@ -223,6 +224,7 @@ void EnergyArbitrator::onMeterWatchdogTick()
|
|||||||
void EnergyArbitrator::applyDegradedMode(const QDateTime &now)
|
void EnergyArbitrator::applyDegradedMode(const QDateTime &now)
|
||||||
{
|
{
|
||||||
m_degradedMode = true;
|
m_degradedMode = true;
|
||||||
|
emit chargingSchedulesChanged(); // pousse degradedMode=true (notification client L2)
|
||||||
const QString reason =
|
const QString reason =
|
||||||
QStringLiteral("Compteur muet depuis >90 s — consigne de repli (L2 watchdog)");
|
QStringLiteral("Compteur muet depuis >90 s — consigne de repli (L2 watchdog)");
|
||||||
|
|
||||||
|
|||||||
@ -84,6 +84,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void registerEcsAdapter(EcsRelayAdapter *adapter);
|
void registerEcsAdapter(EcsRelayAdapter *adapter);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Mode dégradé L2 actif (compteur muet > 90 s) — override de SmartChargingManager.
|
||||||
|
* \return \c true tant que les consignes de repli L2 tiennent ; \c false en régime normal.
|
||||||
|
* \note Exposé dans la notification \c NymeaEnergy.ChargingSchedulesChanged (champ
|
||||||
|
* \c degradedMode), émise aussi aux transitions de ce flag.
|
||||||
|
*/
|
||||||
|
bool degradedMode() const override { return m_degradedMode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
* \brief Boucle principale ETM — surcharge SmartChargingManager::update().
|
* \brief Boucle principale ETM — surcharge SmartChargingManager::update().
|
||||||
|
|||||||
@ -197,6 +197,9 @@ NymeaEnergyJsonHandler::NymeaEnergyJsonHandler(SpotMarketManager *spotMarketMana
|
|||||||
params.clear();
|
params.clear();
|
||||||
description = "Emitted whenever the planed charging schedules have changed.";
|
description = "Emitted whenever the planed charging schedules have changed.";
|
||||||
params.insert("chargingSchedules", QVariantList() << objectRef<ChargingSchedule>());
|
params.insert("chargingSchedules", QVariantList() << objectRef<ChargingSchedule>());
|
||||||
|
// [ETM] degradedMode : true quand le watchdog L2 a basculé en repli (compteur muet).
|
||||||
|
// Optionnel (additif, rétro-compatible) ; émis aussi aux transitions du mode dégradé.
|
||||||
|
params.insert("o:degradedMode", enumValueName(Bool));
|
||||||
registerNotification("ChargingSchedulesChanged", description, params);
|
registerNotification("ChargingSchedulesChanged", description, params);
|
||||||
|
|
||||||
// Charing manager
|
// Charing manager
|
||||||
@ -223,6 +226,7 @@ NymeaEnergyJsonHandler::NymeaEnergyJsonHandler(SpotMarketManager *spotMarketMana
|
|||||||
schedules << pack<ChargingSchedule>(schedule);
|
schedules << pack<ChargingSchedule>(schedule);
|
||||||
}
|
}
|
||||||
params.insert("chargingSchedules", schedules);
|
params.insert("chargingSchedules", schedules);
|
||||||
|
params.insert("degradedMode", m_smartChargingManager->degradedMode()); // [ETM] L2
|
||||||
emit ChargingSchedulesChanged(params);
|
emit ChargingSchedulesChanged(params);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -72,6 +72,10 @@ public:
|
|||||||
|
|
||||||
ChargingSchedules chargingSchedules() const;
|
ChargingSchedules chargingSchedules() const;
|
||||||
|
|
||||||
|
// [ETM] Mode dégradé L2 (watchdog fraîcheur compteur). Base = false ;
|
||||||
|
// overridé dans EnergyArbitrator. Exposé pour la notification JSON-RPC.
|
||||||
|
virtual bool degradedMode() const { return false; }
|
||||||
|
|
||||||
SpotMarketManager *spotMarketManager() const;
|
SpotMarketManager *spotMarketManager() const;
|
||||||
|
|
||||||
#ifdef ENERGY_SIMULATION
|
#ifdef ENERGY_SIMULATION
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user