Deux champs optionnels de même forme sur LoadConfig — o:meterThingId, o:sensorThingId — et leur publication en télémétrie. Rien d'autre : l'arbitre ne s'en sert pas pour décider, et le §12 comme le §10 restent à faire. « Aucun effet sur les décisions » est vrai par CONSTRUCTION, pas par discipline : les adaptateurs ne voient jamais ces Things. attachMeasurements() les résout au moment de publier, dans les deux chemins de télémétrie — y compris le mode dégradé, où un exploitant veut précisément voir ce que la charge fait pendant que l'arbitre ne décide plus rien. measuredW est publié À CÔTÉ de allocatedW et jamais fondu dedans : l'un est ce que le waterfall a alloué, l'autre ce qu'un compteur a vu. Les confondre rendrait la somme des allocations irréconciliable avec budget.allocatedW — et injecter une mesure en retard sur la commande réintroduirait l'oscillation que le recrédit a supprimée. claimedThingIds() les exclut, et l'exclusion est maintenant commentée sur place : LM-201 vaut pour ce qui commande, ceux-ci mesurent. Sans ce commentaire, la symétrie avec relays[] invitait à les ajouter — ce qui ferait refuser un compteur divisionnaire partagé ou une sonde de pièce commune. spec 0.2.1 : la précondition de livraison du §10 (extension du délestage au waterfall, même lot ou avant, jamais après) est écrite comme CONDITION et non comme conseil — la protection de surcharge ne déleste que les bornes, et des planchers éco qui s'additionnent un matin sans soleil sur un branchement 6 kVA feraient disjoncter l'installation. Et LM-1008 tranche la cible de confort : saisie en degrés, frontière de l'arbitre en énergie, conversion à la couche domaine — et aucune conversion nécessaire aujourd'hui, un comparateur suffit, c'est l'arrêt qui compte et pas le dosage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XPUo3RMr8SzK6qbFtfBm8H
52 lines
2.0 KiB
C++
52 lines
2.0 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#ifndef TESTLOADMODEL_H
|
|
#define TESTLOADMODEL_H
|
|
|
|
#include <QObject>
|
|
|
|
/*!
|
|
* \brief Logique pure du modèle de charge : table de paliers et identité matérielle.
|
|
*
|
|
* Aucun serveur nymea ici. Ce qui est éprouvé ne dépend ni d'un ThingManager ni d'un
|
|
* cycle d'arbitrage : la dérivation des paliers est une combinatoire, et
|
|
* \c EnergyArbitrator::sameHardware() une comparaison.
|
|
*/
|
|
class TestLoadModel : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
//! La table dérive de TOUTES les sommes de sous-ensembles, triées, 0 compris.
|
|
void testStageTableIsDerivedFromSubsetSums();
|
|
|
|
//! Puissances distinctes : l'ordre de déclaration n'a aucun effet observable.
|
|
void testRelayOrderIsInertWhenPowersAreDistinct();
|
|
|
|
//! Puissances égales : l'ordre décide QUEL contact sert le palier — et ça se voit.
|
|
void testRelayOrderDecidesWhichContactServesATiedStage();
|
|
|
|
//! Un réordonnancement sans effet ne doit PAS coûter une reconstruction.
|
|
void testReorderingDistinctRelaysKeepsTheAdapter();
|
|
|
|
//! Mais un échange de contacts à puissance égale, si.
|
|
void testSwappingTiedRelaysRebuilds();
|
|
|
|
//! Libellé, rang et besoins se mettent à jour en place : jamais de reconstruction.
|
|
void testSoftFieldsNeverRebuild();
|
|
|
|
// ── §11 — compteur et sonde par charge ─────────────────────────────────
|
|
//! Les deux champs traversent l'aller-retour, et sont OMIS quand ils sont vides.
|
|
void testMeasurementThingsRoundTrip();
|
|
|
|
//! Ils ne sont pas des canaux de commande : ils n'entrent pas dans claimedThingIds().
|
|
void testMeasurementThingsAreNotClaimed();
|
|
|
|
//! Donc deux charges peuvent partager le même compteur et la même sonde.
|
|
void testTwoLoadsMayShareAMeter();
|
|
|
|
//! Et les changer ne reconstruit rien : ils n'ont aucun effet sur le matériel.
|
|
void testMeasurementThingsAreSoftFields();
|
|
};
|
|
|
|
#endif // TESTLOADMODEL_H
|