Patrick Schurig 04852c518a test(mock): le compteur intègre enfin, et purchasedWh gagne un second usage
totalEnergyConsumed n'était écrit par personne : il valait sa valeur par
défaut, indéfiniment. Un compteur figé est un compteur qui n'existe pas pour
tout ce qui l'intègre — deliveredWh restait à 0, remainingWh à 4 000, et
l'étalement adaptatif n'était jamais exercé. Le comportement se confondait
avec unmeasurable pour une raison entièrement différente et bénigne.

Quatrième occurrence d'un mock plus homogène que la réalité, après les six
états cohérents du rootmeter, les classes portant toutes une puissance, et la
triphasée équilibrée.

En export il ne recule pas — il ne bouge pas : un compteur de consommation
est monotone, et le faire reculer produirait un cas que le terrain ne produit
pas, celui-là même que la garde de sémantique traite comme une anomalie. Le
mock fabriquerait le défaut que le moteur est censé détecter.

LM-1014-b appliquée au mock, question posée et répondue : le cumul est
déclaré `cached`, donc il continue au redémarrage. Repartir de zéro ferait
reculer un cumul monotone.

Et purchasedWh gagne un second usage, sous `measured` cette fois. Mesuré sur
le banc : il accumule pendant que deliveredWh peut rester plat, et cette
divergence est un contrôle que l'écran n'aurait pas su fabriquer — de
l'acheté qui monte avec du livré plat signifie soit que la charge ne consomme
pas ce qu'on paie, soit que le compteur ne compte pas. C'est écrit au contrat
parce que le jour où les deux coïncideront, quelqu'un jugera le champ
redondant : c'est précisément quand ils divergent que la paire devient
informative, et un champ qui ne sert que dans l'anomalie n'a pas l'air utile
le reste du temps.

La borne basse du test de cumul est large, et délibérément : il ne contrôle
ni la cadence du minuteur ni l'alignement du premier tic, qui n'intègre rien.
Une borne serrée en ferait un test instable — qu'on relancerait jusqu'à ce
qu'il passe.

Suite : simulation 66/66, loadmodel 22/22, charging 48/48 identique à la
référence, spotmarket 32/32, doxygen 0 avertissement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p
2026-09-04 06:19:08 +02:00

85 lines
3.4 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-energy-plugin-nymea.
*
* nymea-energy-plugin-nymea.s free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nymea-energy-plugin-nymea.s distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with nymea-energy-plugin-nymea. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef INTEGRATIONPLUGINENERGYMOCKS_H
#define INTEGRATIONPLUGINENERGYMOCKS_H
#include "integrations/integrationplugin.h"
#include <QTimer>
#include <QDateTime>
#include <QObject>
#include "extern-plugininfo.h"
class EnergyMockController;
class IntegrationPluginEnergyMocks: public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginenergymocks.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginEnergyMocks(QObject *parent = nullptr);
void setupThing(ThingSetupInfo *info) override;
void thingRemoved(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
private:
QHash<Thing*, EnergyMockController *> m_controllers;
/*!
* \brief Intègre `currentPower` dans `totalEnergyConsumed`, pour TOUS les compteurs.
*
* \par Pourquoi le mock doit le faire
* Le compteur du banc valait **10 kWh depuis le 1er septembre** : une constante, pas un
* cumul. `deliveredWh` restait donc à 0 et `remainingWh` à 4 000 — l'étalement adaptatif
* n'était **jamais exercé**, et le comportement se confondait avec `unmeasurable` pour une
* raison entièrement différente et bénigne.
*
* **Un compteur figé est un compteur qui n'existe pas pour tout ce qui l'intègre.** Quatrième
* occurrence d'un mock plus homogène que la réalité (`docs/INVENTAIRE_MOCK.md`).
*
* \note `totalEnergyConsumed` est déclaré **`cached`** : c'est un compteur de VIE, il
* **continue** au redémarrage du mock et ne repart pas de zéro (\rule{LM-1014-b} : la
* question posée, et la réponse choisie explicitement). Repartir de zéro ferait reculer un
* cumul monotone, ce que la garde de sémantique traite justement comme une anomalie —
* le mock produirait alors un cas que le terrain ne produit pas.
*/
void integrerEnergie();
//! Instant de la dernière intégration, par Thing. Absent = première passe, qui n'intègre
//! rien : sans durée derrière elle, elle fabriquerait de l'énergie.
QHash<Thing*, QDateTime> m_derniereIntegration;
QTimer *m_integrateur = nullptr;
// Update the meter data of the charger based on the current max charging current, connected, power and plugged in state
void updateChargerMeter(Thing *thing);
};
#endif // INTEGRATIONPLUGINENERGYMOCKS_H