`sessionEnergy` est l'ACCUMULATEUR du plugin V2C, pas un compteur remis à zéro pour le moteur : l'écart avec `chargeEnergy` est constant au dix-millième (7,2044 kWh sur deux échantillons à deux heures d'écart), parce qu'il porte les incréments d'avant la dernière remise à zéro de la borne. Le lire directement ferait croire toute obligation éco tenue de 7,2 kWh dès le premier cycle — un nombre crédible et faux que rien ne signalerait. Contre-épreuve : lecture directe, le test annonce 7204. La base se prend à l'ouverture de l'OBLIGATION, jamais au démarrage de nymead : sinon un redémarrage en pleine session réinitialise l'avancement sur une valeur déjà accumulée, et la recharge de nuit relue au matin repart de zéro. Elle est RECAPTURÉE sur un recul franc de l'accumulateur — une nouvelle session — mais pas sur un recul infime, qui est du bruit de lecture et coûterait l'avancement acquis à chaque frémissement du compteur. Ce que le moteur ne refait PAS : la détection de remise à zéro de la BORNE vit dans le plugin, qui interroge à 30 s. Le moteur travaille à la minute et raterait des cycles entiers. Lire comment le plugin l'avait écrite a évité d'ajouter une seconde accumulation, moins fine, en concurrence de la première. Trois maillons manquants raccordés, tous déclarés et alimentés par personne : EvCharger n'exposait pas sessionEnergy ; LoadContextTelemetry::sessionWh n'était rempli nulle part ; et toLoadContext() ABANDONNAIT les besoins déclarés, si bien que LoadContext::needs n'était rempli par aucun adaptateur. L'obligation éco n'existait qu'en configuration. Mock : sessionEnergy ajouté à chargerPhaseSwitching UNIQUEMENT — `charger` reste sans, ce qui donne le cas unmeasurable nativement. La suite porte les deux régimes, comme le banc. Le régime est publié alors qu'aucune décision ne s'y appuie encore, et c'est délibéré : cela sépare publier le régime de décider avec, comme measurement l'a été de l'arbitrage, et rend R6 testable le jour où le motif naîtra au lieu d'un invariant posé sur du code que rien n'émet. Suite : simulation 56/56, charging 48/48 identique à la référence ligne à ligne, loadmodel 21/21, 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
116 lines
4.0 KiB
C++
116 lines
4.0 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 EVCHARGER_H
|
|
#define EVCHARGER_H
|
|
|
|
#include "integrations/thing.h"
|
|
#include "smartchargingmanager.h"
|
|
|
|
#include <hardware/electricity.h>
|
|
|
|
#include <QObject>
|
|
|
|
class ThingManager;
|
|
class ThingActionInfo;
|
|
|
|
class EvCharger : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit EvCharger(ThingManager *thingManager, Thing *parent = nullptr);
|
|
|
|
ThingId id() const;
|
|
Thing *thing() const;
|
|
QString name() const;
|
|
|
|
uint chargingEnabledLockDuration() const; // s
|
|
void setChargingEnabledLockDuration(uint chargingEnabledLockDuration);
|
|
bool chargingEnabledLocked(const QDateTime ¤tDateTime) const;
|
|
|
|
uint chargingCurrentLockDuration() const; // s
|
|
void setChargingCurrentLockDuration(uint chargingCurrentLockDuration);
|
|
bool chargingCurrentLocked(const QDateTime ¤tDateTime) const;
|
|
|
|
bool available() const;
|
|
|
|
bool chargingEnabled() const;
|
|
ThingActionInfo *setChargingEnabled(bool power, const QDateTime ¤tDateTime, bool force = false);
|
|
|
|
bool pluggedIn() const;
|
|
|
|
/*!
|
|
* \brief [ETM §10-C] La borne COMPTE-T-ELLE l'énergie de sa session ?
|
|
* \return Vrai si la ThingClass porte \c sessionEnergy — une CAPACITÉ, pas une valeur.
|
|
* \note Question posée à la ThingClass, jamais à la valeur du moment : une session qui
|
|
* démarre mesure 0 kWh et reste parfaitement mesurable. Même distinction que
|
|
* \c LoadMeasurement::available (\rule{LM-1106}), et pour la même raison — sans elle, le
|
|
* régime d'avancement basculerait d'un cycle à l'autre sur une installation inchangée.
|
|
*/
|
|
bool hasSessionEnergy() const;
|
|
|
|
/*!
|
|
* \brief [ETM §10-C] Énergie livrée dans la session courante (Wh).
|
|
* \return La valeur publiée par la borne, convertie en Wh ; 0 si l'état n'existe pas.
|
|
* \note C'est un ACCUMULATEUR de plugin, pas un compteur brut : côté V2C il est monotone à
|
|
* travers les remises à zéro de la borne, et **remis à la valeur brute à chaque nouvelle
|
|
* session**. Il peut donc RECULER d'une session à l'autre. Le moteur ne refait pas cette
|
|
* accumulation — il détecte le recul (\rule{LM-1012-b}).
|
|
*/
|
|
double sessionEnergyWh() const;
|
|
bool charging() const;
|
|
|
|
uint maxChargingCurrentMaxValue() const;
|
|
uint maxChargingCurrentMinValue() const;
|
|
uint maxChargingCurrent() const;
|
|
ThingActionInfo *setMaxChargingCurrent(uint maxChargingCurrent, const QDateTime ¤tDateTime, bool force = false);
|
|
|
|
bool hasPowerMeter() const;
|
|
double currentPower() const;
|
|
|
|
uint phaseCount() const;
|
|
Electricity::Phases phases() const;
|
|
Electricity::Phases meteredPhases() const;
|
|
|
|
bool canSetPhaseCount() const;
|
|
ThingActionInfo *setDesiredPhaseCount(int desiredPhases);
|
|
|
|
private:
|
|
ThingManager *m_thingManager = nullptr;
|
|
Thing *m_thing = nullptr;
|
|
|
|
uint m_chargingEnabledLockDuration = 300;
|
|
uint m_chargingCurrentLockDuration = 10;
|
|
|
|
QDateTime m_lastChargingEnabledAction;
|
|
QDateTime m_lastChargingCurrentAction;
|
|
};
|
|
|
|
class EvChargers: public QList<EvCharger*>
|
|
{
|
|
|
|
};
|
|
|
|
#endif // EVCHARGER_H
|