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
85 lines
3.4 KiB
C++
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
|