AC-7 asks for the meterSlaveId parameter to be advanced. That property does not exist on nymea 1.15.2 param types: the metadata verifier rejects unknown fields, so adding it makes the whole plugin fail to load rather than merely hiding a parameter. Measured by loading the plugin JSON, with and without the flag, into a PluginMetadata linked against the installed libnymea, rather than read from an upstream tree that may differ from the package. Also records the three other divergences the multi unit ID work runs into, two of which predate it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.3 KiB
Divergences — vendor Fronius du plugin SunSpec
Écarts assumés entre ce que demandent specs/fronius-sunspec.md et le contrat
d'une part, et ce que le code fait d'autre part. Chaque entrée dit pourquoi
et comment la lever.
Deux étiquettes :
- MESURÉ — l'écart repose sur une observation faite sur du matériel ou sur le code de la plateforme, reproductible.
- INFÉRÉ — l'écart repose sur un raisonnement, faute de donnée. À reprendre dès qu'une mesure existe.
D-1 — meterSlaveId n'est pas marqué advanced (MESURÉ)
Ce que demande AC-7. Le paramètre meterSlaveId de la thingClass
froniusConnection doit être advanced.
Ce que fait le code. Rien : le paramètre n'a pas ce drapeau.
Pourquoi. advanced n'est pas une propriété de paramType dans nymea 1.15.2.
ParamType::typeProperties() énumère exactement id, name, displayName,
type, defaultValue, inputType, unit, minValue, maxValue, stepSize,
allowedValues, readOnly. Le vérificateur de métadonnée refuse tout champ
inconnu :
Param type "meterSlaveId" has unknown fields: "advanced"
et PluginMetadata::isValid() passe à false. Ce n'est pas un paramètre mal
affiché : le plugin ne se charge plus du tout, et les erreurs suivantes en
cascade (le paramType est abandonné, donc froniusConnection ne satisfait plus
l'interface networkdevice) rendent le diagnostic trompeur.
Vérifié en chargeant le JSON, avec et sans le drapeau, dans un
PluginMetadata lié à la libnymea installée — pas seulement lu dans une
source amont qui pourrait diverger du paquet.
Comment lever. Rien à faire côté plugin. Il faut soit que nymea ajoute la
propriété, soit que AC-7 soit corrigé. Un test de garde
(test_F3_meter_slave_id_is_not_marked_advanced) empêche qu'on ajoute le
drapeau sans refaire la mesure.
D-2 — délai de garde du balayage des enfants orphelins (INFÉRÉ)
Contexte. processDiscoveryResult() fait disparaître les things enfants
dont le modèle n'est plus annoncé. Avec deux connexions sous le même parent,
chacune ne voit que la moitié du tableau : balayer sur cette moitié ferait
disparaître les enfants de l'autre à chaque découverte. Le balayage attend donc
que toutes les connexions du parent aient réussi une découverte, puis
confronte les enfants à l'union de leurs modèles.
L'écart. Une connexion dont la découverte n'aboutit jamais bloquerait le
balayage pour toujours. Un délai de garde le débloque :
OrphanSweepGraceSeconds = 600 (10 minutes).
Pourquoi cette valeur, et pourquoi elle est INFÉRÉE. Aucune donnée ne la fixe. Le choix est asymétrique et volontairement paresseux : un balayage trop tardif laisse traîner un thing périmé affiché déconnecté, un balayage trop précoce supprime un thing de l'utilisateur. À conséquences inégales, réglage prudent. 10 minutes est très au-delà de tout cycle de découverte observé, sans être infini.
Comment lever. Mesurer, sur le banc puis sur matériel, le temps que met une
découverte SunSpec à échouer définitivement sur un unit ID qui ne répond pas
(timeout × retries × nombre de registres de base balayés). Le délai de garde
doit valoir quelques fois cette durée, pas dix minutes arbitraires. La valeur
est un seul const dans integrationpluginsunspec.cpp ; la changer n'a
d'effet sur rien d'autre.
D-3 — la configuration du plugin écrase les défauts de cadence Fronius (MESURÉ, préexistant)
Contexte. createConnection() impose timeout et numberOfRetries du
vendor Fronius (AC-8) à la création. Mais onPluginConfigurationChanged()
réapplique ensuite les valeurs globales du plugin à toutes les connexions,
Fronius comprise.
L'écart. Il est antérieur à F3 et affecte déjà la connexion onduleur seule.
F3 ne le corrige pas ; il l'étend symétriquement à la connexion compteur, pour
que les deux connexions d'un même thing se comportent identiquement. Le
plancher d'intervalle d'interrogation d'AC-8, lui, reste appliqué : il vit dans
effectiveUpdateInterval(), pas ici.
Comment lever. Hors périmètre de F3 : cela demande de décider si les réglages globaux du plugin doivent pouvoir passer outre un défaut vendor, ce que ni le contrat ni la spec ne tranchent.
D-4 — connexion détruite par ThingSetupInfo::aborted et laissée dans la table (MESURÉ, préexistant, amont)
Contexte. setupThing() relie ThingSetupInfo::aborted à
SunSpecConnection::deleteLater(), alors que createConnection() a déjà inséré
la connexion dans m_sunSpecConnections. Un setup avorté laisse donc un
pointeur pendant dans la table ; le setup suivant du même thing prend la branche
« reconfiguration » et appelle deleteLater() sur un objet déjà détruit.
L'écart. F3 ne corrige pas ce chemin pour la connexion primaire : il est
commun aux trois vendors, y compris solarEdge dont aucun test ne couvre le
comportement, et le périmètre du lot est explicitement « generic et
solarEdgeConnection ne changent pas de comportement ». La connexion compteur
ajoutée par F3, elle, se retire proprement de sa table à la destruction.
Comment lever. Relier QObject::destroyed au retrait de la table pour les
deux connexions, dans un lot qui assume de toucher le chemin commun, avec une
couverture de test pour solarEdge.