fix(v2c): la Trydan déclare phaseCount, et il est SAISI à l'appairage

Aucun registre de phases n'existe dans la carte Modbus V2C : la borne ne sait
pas dire si elle est câblée en mono ou en tri. La ThingClass ne le déclarait pas
non plus, et le repli du moteur pour un état absent est SILENCIEUX —
EvCharger::phaseCount() rend 1.

Sur une Trydan triphasée, cela publie un plancher de 1 380 W au lieu de 4 140
(6 A × 230 V × 1 au lieu de × 3) et convertit l'enveloppe allouée en un courant
trois fois trop élevé. La borne démarre, au mauvais courant, sans qu'aucun
journal ne le dise.

C'est la famille de défaut que le moteur vient de fermer en 3g-2 — un plancher
annoncé qui n'est pas celui qui gouverne le démarrage — rouverte côté plugin.
Trouvée la veille de la pose, en lisant la déclaration de classe plutôt qu'en
l'exécutant.

La valeur vient donc d'un RÉGLAGE (1 ou 3, défaut 1), recopié dans l'état que le
moteur lit, et réappliqué sur settingChanged pour qu'une borne recâblée se
corrige sans recréer le Thing. Le défaut 1 est celui du repli du moteur : une
installation qui ne renseigne rien se comporte exactement comme avant.

L'état porte minValue 1 / maxValue 3 — l'interface nymea evcharger définit
phaseCount avec ces bornes, et le validateur refuse la classe sans elles. S'y
conformer, c'est être lu par le moteur À TRAVERS l'interface, pas par une
convention propre au plugin.

Compile amd64 0 erreur / 0 warning.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017TVywtayEeoRJ2yWUW4iZj
This commit is contained in:
Patrick Schurig 2026-08-27 15:15:31 +02:00
parent 5dd9bf7ca5
commit 1bf0b675c6
3 changed files with 80 additions and 0 deletions

35
debian/changelog vendored
View File

@ -1,3 +1,38 @@
etm-powersync-plugins-modbus (1.15.2+etm12) trixie; urgency=medium
* v2c: the Trydan now declares phaseCount, and it is ENTERED at pairing.
There is no phase register anywhere in the V2C Modbus map (0x0BC2-0x0BD5,
0x177A-0x1783): the charger cannot tell whether it is wired single or three
phase. The thing class did not declare phaseCount either, and the energy
engine's fallback for a missing state is SILENT -- EvCharger::phaseCount()
returns 1. On a three-phase Trydan that publishes a 1380 W floor instead of
4140 (6 A x 230 V x 1 instead of x 3) and converts an allocated envelope
into a current three times too high. The charger starts, at the wrong
current, with nothing in any log to say so.
That is the same defect family the energy plugin closed in 3g-2 -- a floor
that is announced but is not the one governing the start -- reopened on the
plugin side. Found the evening before the charger was due on the wall, by
reading the class declaration rather than by running it.
The value therefore comes from a SETTING (1 or 3, default 1), mirrored into
the state the engine reads, and re-applied on settingChanged so a rewired
charger can be corrected without recreating the thing. Default 1 matches the
engine's own fallback, so an installation that never sets it behaves exactly
as it did before this change.
The state carries minValue 1 / maxValue 3: the nymea evcharger interface
defines phaseCount with those bounds, and the plugin validator rejects the
class without them. Conforming means the engine reads it through the
interface, not through a plugin-specific convention.
* v2c: still no sessionEnergy, deliberately. ChargeEnergy (0x0BC4) stays a
diagnostic state -- see the plugin brief and evcc-io/evcc#28047. To be
re-examined with the charger and a reference meter in hand.
-- Patrick Schurig <etm.schurig@gmail.com> Thu, 27 Aug 2026 15:20:00 +0200
etm-powersync-plugins-modbus (1.15.2+etm11) trixie; urgency=medium
* sunspec: stop warning about a missing battery channel on a machine that has

View File

@ -67,6 +67,30 @@ void IntegrationPluginV2c::setupThing(ThingSetupInfo *info)
connect(info, &ThingSetupInfo::aborted, master, &TrydanModbusTcpMaster::deleteLater);
// --- Nombre de phases : SAISI, parce que la borne ne sait pas le dire -------------------
//
// Il n'existe aucun registre de phases dans la carte Modbus V2C (0x0BC2-0x0BD5,
// 0x177A-0x1783) : le câblage mono/tri n'est pas lisible sur la borne. Or le moteur
// energy-etm en a besoin, et son repli est SILENCIEUX — EvCharger::phaseCount() retourne 1
// quand l'état est absent. Sur une Trydan triphasée, cela publierait un plancher de
// 6 A x 230 V x 1 = 1 380 W au lieu de 4 140, et convertirait les watts alloués en un
// courant trois fois trop élevé. La borne démarrerait, au mauvais courant, sans erreur.
//
// Le nombre de phases vient donc d'un RÉGLAGE, modifiable si la borne est recâblée, et il
// est recopié dans l'état que le moteur lit. Défaut 1 : le même que le repli du moteur,
// pour qu'une installation non renseignée se comporte comme avant ce correctif.
auto appliquerNombreDePhases = [](Thing *t) {
const uint phases = t->setting(trydanSettingsPhaseCountParamTypeId).toUInt();
t->setStateValue(trydanPhaseCountStateTypeId, (phases == 3 ? 3u : 1u));
};
appliquerNombreDePhases(thing);
connect(thing, &Thing::settingChanged, thing, [thing, appliquerNombreDePhases](
const ParamTypeId &paramTypeId, const QVariant &/*value*/) {
if (paramTypeId == trydanSettingsPhaseCountParamTypeId) {
appliquerNombreDePhases(thing);
}
});
// Reachability is driven by Modbus poll results (not TCP state directly).
// initialize() is now called from TrydanModbusTcpMaster::onConnectionStateChanged(true)
// so we no longer need to call it here — this handler only updates the UI.

View File

@ -63,6 +63,17 @@
"displayName": "Suspend internal V2C optimizer when HEMS takes control",
"type": "bool",
"defaultValue": true
},
{
"id": "ff07260e-1583-51a3-a536-483ce513a218",
"name": "phaseCount",
"displayName": "Number of connected phases (1 or 3)",
"type": "uint",
"defaultValue": 1,
"allowedValues": [
1,
3
]
}
],
"stateTypes": [
@ -112,6 +123,16 @@
"defaultValue": 16,
"writable": true
},
{
"id": "1435a5cd-7054-5ef3-8511-51b09df6a148",
"name": "phaseCount",
"displayName": "Connected phases",
"type": "uint",
"defaultValue": 1,
"minValue": 1,
"maxValue": 3,
"cached": false
},
{
"id": "2570c0d7-f9a5-4e24-9242-6d79253004ec",
"name": "currentPower",