applyRelayStage faisait déjà du set-cible complet (delta correct, gère le non-cascadé) : durcissement off-before-on (anti sur-puissance transitoire quand monter de palier éteint des relais, ex. 3 résistances 500/1000/2000 : 1500→2000 commute 3 relais) + intention documentée (comme SG-Ready). testEcsRelayTopologies : ECS simple 1 relais (on/off) + ECS 3 relais non-cascadé (transition 1500→2000 → set final r2000 SEUL, r500/r1000 coupés). Couvre les 2 topologies du test terrain vendredi. Suite simulation 20/20, plugin prod 0/0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
87 lines
2.9 KiB
C++
87 lines
2.9 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/>.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include <QtTest>
|
|
#include <QDateTime>
|
|
|
|
#include "simulationbase.h"
|
|
|
|
using namespace nymeaserver;
|
|
|
|
class ChargerPlugEvent
|
|
{
|
|
public:
|
|
ChargerPlugEvent() = default;
|
|
ChargerPlugEvent(const QDateTime &dt, bool pi = false, int pu = 0)
|
|
: dateTime{dt},
|
|
pluggedIn{pi},
|
|
percentageUsed{pu}
|
|
{}
|
|
QDateTime dateTime;
|
|
bool pluggedIn;
|
|
int percentageUsed = 0;
|
|
};
|
|
|
|
class Simulation: public SimulationBase
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit Simulation(QObject *parent = nullptr) : SimulationBase(parent) { };
|
|
|
|
typedef QList<ChargerPlugEvent> ChargerPlugEvents;
|
|
typedef QList<int> DetailsStepList;
|
|
|
|
private slots:
|
|
void run_data();
|
|
void run();
|
|
|
|
// Waterfall ECS (EcsRelayAdapter) : cascade surplus, anti-clignotement (recrédit),
|
|
// et protection compresseur (import < minOn → RESTE ; import > minOn → déleste).
|
|
void testEcsSurplusPV();
|
|
|
|
// Watchdog L2 : compteur muet >90 s → mode dégradé (ECS off force=true, bypass minOn),
|
|
// planification suspendue (ECS reste 0 sur N cycles), reprise au retour du compteur.
|
|
void testMeterSilentFallback();
|
|
|
|
// SG-Ready (PAC) : montée d'états sur surplus, hystérésis 3↔4, protection court-cycling,
|
|
// et interaction budget PARTAGÉ ECS↔PAC (preuve du waterfall unifié 3e).
|
|
void testSgReadySurplus();
|
|
|
|
// ECS topologies : 1 relais (simple) + 3 relais valeurs différentes (mapping NON-CASCADÉ,
|
|
// transition 1500→2000 qui commute 3 relais) — vérifie le set de relais final correct.
|
|
void testEcsRelayTopologies();
|
|
|
|
void printStates(Thing *thing);
|
|
void updateChargerMeter(Thing *thing);
|
|
|
|
QStringList plotOriginalData(int powerBalanceCount);
|
|
QStringList plotSimulation(const QString &title, int powerBalanceCount);
|
|
QStringList plotSpotMarketData(int powerBalanceCount);
|
|
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(ChargerPlugEvent)
|
|
Q_DECLARE_METATYPE(Simulation::ChargerPlugEvents)
|
|
Q_DECLARE_METATYPE(Simulation::DetailsStepList)
|