3 Commits

Author SHA1 Message Date
Patrick Schurig
89f7bf0199 fix(sunspec): signe du compteur Fronius et batterie fantôme
Deux défauts constatés sur le GEN24 des beaux-parents (Primo GEN24 3.0,
Smart Meter TS 65A-3, sans batterie).

Signe du compteur. onMeterBlockUpdated() négociait le signe de tous les
modèles compteur sans distinction de fabricant. Sur Fronius la négation est
fausse : le Smart Meter émet déjà dans la convention nymea. L'onduleur étant
monophasé, il sert de référence de direction : le plugin rapportait la phase
portant l'onduleur en soutirage et les deux autres en injection, ce qui est
impossible sans source. L'arbitre en concluait « Surplus insuffisant
(-842 W) » et laissait chauffe-eau et PAC éteints en plein export.

La décision vit dans FroniusRules::meterPowerSign() et n'est annulée que sous
une froniusConnection. Les vendors generic et solarEdge sont inchangés, ce
qu'un antidote verrouille. Les compteurs d'énergie sont corrects et ne sont
pas permutés.

Batterie fantôme. Un GEN24 hybride publie le modèle 124 sans batterie câblée,
d'où un enfant storage bloqué sur batteryCritical.
FroniusRules::hasBattery() exige une grandeur physique non nulle (InBatV ou
StorAval), le SoC étant écarté car 0 % ne se distingue pas d'une batterie
vide. Le côté « batterie présente » reste INFÉRÉ : voir D-6, à valider sur un
GEN24 équipé avant tout déploiement.

Suite logique : 50 tests verts, dont six antidotes AC-16 et AC-17.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 08:29:16 +02:00
Patrick Schurig
4f2076f504 sunspec: decide whether a Fronius meter connection is wanted
A GEN24 answers for the inverter on one unit ID and for the Smart Meter
on another, behind the same host and port. Isolate the decision to open
that second connection as a pure function, so it can be pinned down
without nymea, and leave the logging of the refusal to the caller.

Refuses a meter slave ID out of the 0..247 range, treats 0 as "no meter
on this connection" as documented, and refuses a meter slave ID equal to
the inverter one: a second socket on the same unit ID would rediscover
the very same models and duplicate every child thing. That last case is
reachable, since the discovery writes the scanned slave ID into the
thing parameter.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 08:50:25 +02:00
Patrick Schurig
c2eccd96e5 sunspec: add a failing test that sets up a Fronius connection
The existing suite only exercises free functions and the plugin JSON, so it
cannot see whether a thing class is dispatched at all. A thing class missing
from the dispatch in setupThing() falls into the final Q_ASSERT_X: in a debug
build the process dies, in a release build the assert is compiled out and
setupThing() returns without ever calling info->finish(), leaving the pairing
stuck with no message.

Split the tests into two suites. The logic one keeps its former scope and its
single dependency on libnymea-sunspec. The new one instantiates the plugin
behind the real ThingManager of libnymea-core and a faked HardwareManager, so
the dispatch of setupThing(), postSetupThing() and thingRemoved() is covered.
No network access takes place: the faked monitor is never reachable, so the
plugin never attempts a Modbus connection.

The four new cases fail: froniusConnection is not dispatched yet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:18:41 +02:00