25 KiB
AGENTS.md — plugin Eastron (compteurs SDM)
Repo :
etm-powersync-plugins-modbus· Dossier :eastron/· Branche :mainCompteurs d'énergie Eastron SDM (SDM72, SDM120, SDM220, SDM230, SDM630). Comm : Modbus RTU / RS485 uniquement (pas de variante TCP dans ce plugin). Statut cible : Supporté / prod — SDM72 (principal) + SDM120 (PV) en prod suretm-nymea-dev. Paquet :eastron 1.15.0+etm3(amd64 + cross arm64, canaux nightly/testing/stable). Plugin id :2078c2fc-c4cd-46bb-95ab-e9a55ef0a281· Vendoreastron33529c0d-67e6-441e-b0bb-6e76e9d4bc1c.Nature du plugin (à comprendre AVANT toute modif) : c'est un plugin généré par le modbus-tool de nymea, pas un plugin écrit à la main. La carte de registres et le décodage sont déclaratifs (
*-registers.json) ; le.cpp/.hest en grande partie du code généré + un peu de glue (discovery, setup, câblage des states). On édite le JSON, pas les classes de connexion générées.Sources de vérité (lues juin 2026, commit
b1da668) :
sdm72-registers.json— carte SDM72 (triphasé). ✅ lue intégralement.sdm120-registers.json— carte SDM120 (monophasé). ✅ lue intégralement.integrationplugineastron.json— ThingClasses, interfaces, params, states. ✅ lue (tronquée en toute fin sursdm230Producer, mais les 5 familles de modèles sont vues).- Protocoles constructeur (datasheets Eastron, lus juin 2026) : SDM120-Modbus V2.4, SDM230-Modbus V1.2, SDM72D-M-2 V1.1.1 (2023). ✅ croisés avec les
*-registers.json— adresses, FC04, endianness confirmées (voir §4).- Non encore relus dans ce brief :
integrationplugineastron.cpp/.h(discovery + glue),eastron.pro,meta.json,sdm630-registers.json,sdm220-registers.json,sdm230-registers.json(contenu JSON ; les adresses SDM230 sont confirmées par le datasheet). → voir « À vérifier dans le code » en fin de fichier.
1. RÔLE
Exposer des compteurs Eastron SDM lus en Modbus RTU comme Things nymea implémentant les
interfaces énergie (energymeter / smartmeterconsumer / smartmeterproducer), consommées par
le moteur energy-etm (EnergyArbitrator) pour le bilan de puissance/énergie (point de
livraison, production PV).
Read-only. Un compteur ne se pilote pas : aucune action, aucun registre en écriture, aucun
paramRegisters d'écriture. Tout est inputRegister access: RO. Toute tentative d'ajouter une
écriture est hors périmètre (et faux pour ce matériel).
2. ARCHITECTURE — la séparation à ne jamais oublier
Le point central de ce plugin (équivalent de la « règle d'or transport » du brief V2C, mais inversé) : le plugin ne possède PAS le port série.
nymead
└─ ModbusRtuMaster (objet nymea, configuré HORS plugin)
• /dev/ttyUSB0 ← le port physique appartient au master, pas au plugin
• 9600 8N1, timeout, retries ← configurés sur le MASTER
• un seul master = un seul maître sur le bus RS485
└─ Thing « SDM72 » (slaveAddress 1) ─┐ partagent le même
└─ Thing « SDM120 » (slaveAddress 2) ─┘ master via modbusMasterUuid
- Chaque ThingClass a deux
paramTypesclés :slaveAddress(uint, défaut 1) — l'unit ID Modbus du compteur sur le bus.modbusMasterUuid(QUuid, readOnly) — pointe vers leModbusRtuMasternymea qui porte le port série. Renseigné par le mécanisme de setup/discovery, jamais saisi à la main.
- 🔴 Conséquence directe : le baud (9600), la parité (N), le timeout (500 ms) et les retries
(3) ne sont PAS dans ce plugin. Ils vivent dans la config du
ModbusRtuMaster(côté nymea-app → Modbus RTU, ou config nymead). Chercher un bug de baud/timeout danseastron/est une perte de temps : c'est au niveau du master. (Localisation exacte du réglage à confirmer selon la version de nymea-app, mais ce n'est pas dans ce dossier.) - 🔴 Bus mono-maître : tous les SDM partagent le même master = le même
/dev/ttyUSB0. nymead est le seul maître. Voir §7 (discipline de bus) — c'est la cause racine n°1 des timeouts intermittents.
3. THINGCLASSES, RÔLES ÉNERGIE & CONVENTION ETM
3.1 Matrice complète du plugin (ce qui existe)
5 modèles × 3 variantes de rôle = 15 ThingClasses (toutes en createMethods: ["discovery"],
toutes avec connectable + une interface énergie selon la variante) :
| Modèle | « — Energy Meter » | « — Producer Meter » | « — Consumer Meter » |
|---|---|---|---|
| SDM72 (3φ) | sdm72 (energymeter) |
sdm72Producer (smartmeterproducer) |
sdm72Consumer (smartmeterconsumer) |
| SDM120 (1φ) | sdm120 (energymeter) |
sdm120Producer (smartmeterproducer) |
sdm120Consumer (smartmeterconsumer) |
| SDM220 (1φ) | sdm220 (energymeter) |
sdm220Producer (smartmeterproducer) |
sdm220Consumer (smartmeterconsumer) |
| SDM230 (1φ) | sdm230 (energymeter) |
sdm230Producer (smartmeterproducer) |
sdm230Consumer (smartmeterconsumer) |
| SDM630 (3φ) | sdm630 (energymeter) |
sdm630Producer (smartmeterproducer) |
sdm630Consumer (smartmeterconsumer) |
States par variante : Energy Meter = riche (tension/courant/puissance ± par phase +
totalEnergyConsumed + totalEnergyProduced) ; Producer = currentPower,
totalEnergyProduced, frequency ; Consumer = currentPower, totalEnergyConsumed,
frequency. Toutes ont connected (bool, cached:false).
3.2 Comment nymea attribue le rôle (source energymanagerimpl.cpp)
🔴 Le rôle énergie d'un compteur = son INTERFACE, lue statiquement par l'EnergyManager. Il
n'y a aucun paramètre runtime « rôle » côté plugin. La logique du manager :
- Root meter (grid) :
setRootMeter()refuse un thing qui n'a pas l'interfaceenergymeter. Le compteur réseau doit être unenergymeter, et il n'y en a qu'un. SoncurrentPowersigné (+ = consommé / − = produit) et ses deux totaux donnent l'échange réseau dans les deux sens → un seul thing couvre import ET export. - Producteurs : production =
configuredThings().filterByInterface("smartmeterproducer"). Seuls les thingssmartmeterproducercomptent comme production (onduleur/PV). - Consommateurs :
filterByInterface("smartmeterconsumer")(charge dédiée, PAC…). - ⚠️ Gotcha auto-root : si aucun root meter n'est défini, le manager promeut
automatiquement le premier
energymeterqui apparaît. Ne pas laisser traîner unenergymeterparasite qui raflerait le rôle de root à la place du bon compteur.
🔴 Pourquoi on ne peut PAS fusionner en une seule ThingClass par modèle : un thing portant à
la fois energymeter + smartmeterproducer + smartmeterconsumer serait ramassé par les deux
boucles filterByInterface → double comptage du bilan (compté en prod ET en conso). Le modèle
interface-driven impose donc une ThingClass par rôle. C'est une limite de l'energy experience,
pas du plugin eastron.
3.3 Le rôle dépend de l'INSTALLATION, pas du modèle (convention ETM)
Le même modèle sert à des rôles différents selon le chantier (ex. onduleur 3 kW → SDM120, onduleur 10 kW → SDM230 ; en triphasé SDM72/SDM630 en compteur réseau, onduleur ou conso PAC). La matrice modèle×rôle est donc irréductible : aucune variante n'est « jamais utilisée », ne pas élaguer (on casserait des cas réels). Couverture ETM des (modèle × rôle) effectivement déployés :
| Modèle | Root meter (energymeter) |
Producteur (smartmeterproducer) |
Consommateur (smartmeterconsumer) |
|---|---|---|---|
| SDM72 (3φ) | ✅ | ✅ | ✅ |
| SDM630 (3φ) | ✅ | ✅¹ | ✅¹ |
| SDM230 (1φ) | ✅ | ✅ | ✅ |
| SDM120 (1φ) | —² | ✅ | ✅ |
| SDM220 (1φ) | —³ | —³ | —³ |
¹ SDM630 en producteur/consommateur = gros onduleur ou PAC triphasés (selon la remarque
triphasé : SDM72/SDM630 couvrent les trois rôles en 3φ).
² SDM120 n'est pas déployé comme compteur réseau (trop petit / dédié branche). La ThingClass
sdm120 (energymeter) existe et serait techniquement acceptée comme root par nymea, mais
hors convention ETM — et attention au gotcha auto-root.
³ SDM220 : présent dans le plugin, hors convention de déploiement ETM listée (à traiter comme
les autres 1φ si un cas se présente).
3.4 Convention displayName par fonction (action court terme, ZÉRO risque)
La liste « ajouter un thing » montre les ThingClasses par displayName. Renommer uniquement le
displayName (jamais l'id ni le name) ne casse aucun thing appairé en prod — c'est
l'action sûre et disponible tout de suite pour rendre la liste lisible (l'installateur choisit par
fonction, pas par « Producer/Consumer/Energy Meter »). Convention ETM proposée :
ThingClass (name) |
displayName proposé |
|---|---|
sdm72 / sdm230 / sdm630 |
Compteur réseau — Eastron SDMxx (Nφ) |
sdm72Producer / sdm230Producer / sdm120Producer / sdm630Producer |
Onduleur / PV — Eastron SDMxx (Nφ) |
sdm72Consumer / sdm230Consumer / sdm120Consumer / sdm630Consumer |
Consommateur (PAC/charge) — Eastron SDMxx (Nφ) |
Édition à faire dans integrationplugineastron.json (champ displayName de chaque ThingClass).
Regrouper les libellés par rôle aide à scanner les 15 entrées en 3 blocs. Ça ne réduit pas le
nombre d'entrées (15 restent 15) — ça les rend intentionnelles.
3.5 Le vrai fix de fond (hors périmètre plugin — feature request nymea)
Réduire à « 1 entrée par modèle, rôle choisi après » suppose de modifier
nymea-experience-plugin-energy, pas ce plugin. Demande à porter à l'équipe nymea :
Permettre d'assigner le rôle énergie (root/grid, producteur, consommateur) à un seul thing
energymeterbidirectionnel depuis l'energy experience — sur le modèle desetRootMeter()déjà existant, étendu à producteur/consommateur — au lieu d'imposer une ThingClass par interface. Motivation : le rôle dépend de l'installation, pas du modèle ; la matrice modèle×rôle explose la liste d'ajout côté installateur. C'est additif → ne casse rien des setups existants.
Si nymea suit, la matrice eastron se simplifie d'elle-même (une ThingClass energymeter par
modèle, rôle réglé en réglages énergie). Pas pour aujourd'hui ni le mois prochain.
3.6 Config prod ETM (etm-nymea-dev, 192.168.1.120)
- SDM72 = compteur principal / réseau, unit ID 1 → ThingClass
sdm72(energymeter), désigné root meter dans les réglages énergie. - SDM120 = compteur PV, unit ID 2 → ThingClass
sdm120Producer(smartmeterproducer). (Unsdm120energymeter non-root ne serait PAS agrégé en production — il faut bien la variante Producer.) - ⚠️ Vérifier sur le Thing réel que ces variantes sont bien celles instanciées (convention ETM
« pas de valeur inventée »), via
nymea-appou la conf nymead.
4. CARTES DE REGISTRES (confirmées depuis les *-registers.json)
Communes aux deux : protocol: "RTU", endianness: "BigEndian", type: "float" (32 bits, 2
registres), registerType: "inputRegister" (FC04), access: "RO",
errorLimitUntilNotReachable: 15. Adresses en base 0 (registre Modbus, pas l'offset 3xxxx).
✅ Adresses, FC04 et word order Big-endian (MSR first) confirmés contre les protocoles
constructeur (SDM72D-M-2 V1.1.1, SDM120 V2.4, SDM230 V1.2).
🔎
totalEnergyConsumed/totalEnergyProduced= Import/Export, PAS le « Total » du compteur. Le plugin litImport active energy(reg 72) etExport active energy(reg 74), et non le registre « Total active energy » (reg 342). C'est volontaire et correct : sur SDM120/SDM230 le « total » dépend du réglage interne Measurement mode (mode 2 = import+export par défaut, mode 1 = import seul, mode 3 = import−export) ; sur SDM72 le « total » = import+export. Lire import et export séparément contourne cette ambiguïté de mode. Ne pas « simplifier » en lisant reg 342.
SDM72 — className: "Sdm72" · checkReachableRegister: "totalCurrentPower"
| addr | id | unité | groupé en block ? |
|---|---|---|---|
| 52 | totalCurrentPower (puissance système totale, 30053) |
W | non (registre seul, sonde reachable) |
| 0 / 2 / 4 | voltagePhaseA/B/C (30001/03/05) |
V | block phaseVoltageAndCurrent |
| 6 / 8 / 10 | currentPhaseA/B/C (30007/09/11) |
A | block phaseVoltageAndCurrent |
| 12 / 14 / 16 | powerPhaseA/B/C (30013/15/17) |
W | block phasePower |
| 70 | frequency (30071) |
Hz | block frequencyAndTotalEnergy |
| 72 | totalEnergyConsumed = Import active energy (30073) |
kWh | block frequencyAndTotalEnergy |
| 74 | totalEnergyProduced = Export active energy (30075) |
kWh | block frequencyAndTotalEnergy |
SDM120 — className: "Sdm120" · checkReachableRegister: "activePower"
| addr | id | unité | groupé en block ? |
|---|---|---|---|
| 0 | voltage (30001) |
V | non |
| 6 | current (30007) |
A | non |
| 12 | activePower (30013) |
W | non (sonde reachable) |
| 70 | frequency (30071) |
Hz | block frequencyAndTotalEnergy |
| 72 | totalEnergyConsumed = Import active energy (30073) |
kWh | block frequencyAndTotalEnergy |
| 74 | totalEnergyProduced = Export active energy (30075) |
kWh | block frequencyAndTotalEnergy |
SDM230 — className: "Sdm230" (JSON non relu, adresses confirmées par datasheet V1.2)
Layout identique au SDM120 (monophasé) : voltage(0), current(6), activePower(12),
frequency(70), import→totalEnergyConsumed(72), export→totalEnergyProduced(74). Le
sdm230-registers.json doit donc être la copie du SDM120 avec className: "Sdm230" — à vérifier
sur le fichier réel.
⚠️ Block reads = OK ici (contrairement au piège V2C). Les
blocksregroupent des registres contigus et non chevauchants (le SDM expose des floats sur des adresses pairement espacées). Le modbus-tool lit chaque block en une transaction groupée — comportement voulu et sûr sur SDM. Ne PAS « casser » les blocks en lectures individuelles pour imiter V2C : c'est inutile et ça multiplie les transactions sur un bus déjà partagé.📏 Limite de transaction par modèle (datasheets) : SDM72 = 30 paramètres / 60 registres max par requête ; SDM120 et SDM230 = 40 / 80. Les blocks actuels sont très en dessous, mais à respecter si on ajoute des registres à un block (un block trop large lit aussi des registres réservés inutiles).
4bis. PARAMÈTRES SÉRIE DU COMPTEUR (réglés sur le compteur, vus dans les datasheets)
Confirmé par les manuels (utile au commissioning ; rappel : ces valeurs sont côté compteur,
le ModbusRtuMaster nymea doit matcher — cf. §2) :
- Baud supportés : SDM72D-M-2 = 1200/2400/4800/9600/19200 (défaut 9600) ; SDM120 & SDM230 = 1200/2400/4800/9600 (défaut 2400, pas de 19200).
- 🔴 Cap bus = 9600 : un SDM120/SDM230 ne peut pas dépasser 9600. Le bus partagé est donc plafonné à 9600 tant qu'un de ces modèles y est. Inutile d'espérer accélérer le bus au-delà.
- 🔧 Commissioning : un SDM120/SDM230 sorti d'usine est à 2400 → le passer à 9600 (et régler son adresse Modbus unique) via le menu façade avant de le brancher au bus prod.
- Parité/stop : défaut None / 1 stop. Le bus prod est en 9600 8N1 → cohérent.
- Word order : MSR first (Big-endian) par défaut sur les trois ; SDM72 l'auto-détecte et ne
l'expose pas au menu. Le plugin suppose
BigEndian→ ne pas changer ce réglage sur le compteur.
5. SÉMANTIQUE DE REACHABILITY (lien direct avec les timeouts)
errorLimitUntilNotReachable: 15 + checkReachableRegister définissent comment le plugin gère
les erreurs Modbus :
- Le générateur lit périodiquement le
checkReachableRegister(totalCurrentPowerpour SDM72,activePowerpour SDM120) pour juger si le device répond. - Il faut 15 erreurs consécutives (timeouts/exceptions) avant que le Thing bascule
connected = false. En dessous, les valeurs continuent d'être servies (d'où « parfois ça répond, parfois rafales » sans que le Thing tombe forcément). - 🔎 Implication debug : des rafales < 15 sont absorbées silencieusement côté state
connected, mais polluent les logs (SdmXXModbusRtuConnection: ... TimeoutError) et trouent la mesure. Le seuil masque le symptôme, il ne le corrige pas. La cause se traite au niveau bus (§7), pas en montant ce seuil.
6. DISCOVERY
createMethods: ["discovery"],discoveryParamTypes: [ slaveAddress (int, défaut 1) ].- La discovery sonde le bus (via le
ModbusRtuMastercourant) à l'adresse demandée et tente de lire lecheckReachableRegister; si ça répond, le device est proposé. - ⚠️ La discovery émet du trafic sur le bus partagé : lancer une discovery pendant que les SDM prod tournent ajoute des transactions. Pas bloquant, mais à savoir pour le diagnostic.
- (Détail d'implémentation discovery — choix du master, gestion multi-master, dédoublonnage —
à lire dans
integrationplugineastron.cpp, non couvert ici.)
7. DISCIPLINE DE BUS RS485 — la cause racine n°1 des timeouts (OPÉRATIONNEL)
Cette section encode une leçon de prod (incident timeouts SDM apparu pendant une session de debug
v2c/Trydan avec mbpoll sur /dev/ttyUSB0). À lire avant tout diagnostic de timeout.
- Un seul maître. Le RS485 est mono-maître ; nymead l'est. Ne jamais lancer
mbpoll/modpollsur/dev/ttyUSB0pendant que nymead tourne → deux maîtres → collisions de trames → timeouts intermittents par rafales. Pour sonder aumbpoll, arrêter nymead d'abord (sudo systemctl stop nymead), puis le relancer. - Pas de process série résiduel. Après une session de debug, vérifier qu'aucun
mbpollzombie ne tient le port :pgrep -a mbpoll ; sudo lsof /dev/ttyUSB0(doit ne montrer que nymead). - Épingler le port par identité, pas par
ttyUSBn: leModbusRtuMasterdoit pointer un/dev/serial/by-id/usb-Silicon_Labs_CP2102...-if00-port0(cp210x), sinon renommage possible au reboot (ttyUSB0 ↔ ttyUSB1) si un 2e adaptateur est branché. - Stabilité cp210x : surveiller
dmesg | grep -i cp210x(disconnect/reset) — un adaptateur qui décroche donne aussi des rafales, indépendamment du bus. - Charge VM : sous forte charge CPU, nymead peut ne pas tenir la cadence du master → pseudo-
timeouts. Contributeur, rarement cause unique. Mécanisme (confirmé par le protocole Eastron,
§3.3) : une trame RTU doit être un flux continu ; un silence > 1,5 temps-caractère
(≈ 1,6 ms à 9600 8N1) en milieu de trame fait jeter la trame par le SDM → pas de réponse →
timeout côté master. Le latency timer du cp210x (défaut 16 ms) combiné au jitter
d'ordonnancement de la VM peut fragmenter une trame au-delà de ce seuil. Pistes : baisser le
latency timer du cp210x (
/sys/bus/usb-serial/devices/ttyUSB0/latency_timer), réduire la charge, ou prioriser nymead. À traiter seulement si le bus est propre par ailleurs (1–4 ci-dessus). - Réglages bus (au niveau master, pas plugin) : A/B non inversés, GND commun adaptateur↔SDM, borniers serrés, terminaison 120 Ω peu critique sur bus court 2 nœuds à 9600. Topologie en daisy-chain, pas d'étoile ni de stub (réflexions → corruption ; protocole §2.2).
8. CLASSES GÉNÉRÉES & LECTURE DES LOGS
Le modbus-tool génère, à partir du className, une classe de connexion <ClassName>ModbusRtuConnection :
Sdm72→Sdm72ModbusRtuConnectionSdm120→Sdm120ModbusRtuConnection
D'où les lignes de log Sdm72ModbusRtuConnection: ModbusRtu reply error ... TimeoutError. Un log
préfixé par une de ces classes = couche transport générée, pas la glue du plugin. Utile pour
router un bug : préfixe SdmXXModbusRtuConnection → registre/transport/bus ; messages du plugin
eastron lui-même → setup/discovery/câblage des states.
9. POUR ÉTENDRE (ajouter un modèle ou un registre)
Workflow déclaratif, dans l'ordre :
- Ajouter/éditer
<modele>-registers.json(className unique, registresinputRegisterfloat Big-endian, choisir uncheckReachableRegisterqui répond toujours, garder les blocks contigus). Réutiliser les conventions SDM72/SDM120 ci-dessus. - Ajouter la/les ThingClass(es) dans
integrationplugineastron.json(3 variantes de rôle si pertinent), avec lesparamTypesslaveAddress+modbusMasterUuid(readOnly) et le stateconnected(cached: false). - Générer de nouveaux UUID pour chaque nouvel id (plugin/thingclass/param/state). Ne jamais réutiliser un UUID existant.
- Régénérer via le modbus-tool nymea (cible du
.pro), recompiler amd64 puis cross arm64. - Tester en mono-maître (nymead arrêté,
mbpoll -1 ...) que le device répond, puis via nymead. - Mettre à jour
PORTING_STATUS*/ doc catalogue (badge canal/origine/stabilité) si applicable.
10. INTERDIT
- Éditer les classes de connexion générées (
SdmXXModbusRtuConnection) à la main — elles sont régénérées, toute modif sera écrasée. Corriger dans les*-registers.json. - Mettre la config série (baud/parité/timeout/retries) dans le plugin — elle appartient au
ModbusRtuMasternymea (§2). - Ajouter de l'écriture (action/registre
access: WO/RW) — un SDM est read-only. - Changer/réutiliser les UUID de ThingClasses ou de plugin publiés (casse l'appairage des Things existants en prod).
- Casser les blocks en lectures individuelles pour copier le pattern V2C — non pertinent ici (registres contigus, pas de chevauchement firmware).
- Lancer
mbpollsur le bus pendant que nymead tourne (§7). - Monter
errorLimitUntilNotReachablepour « régler » des timeouts — masque, ne corrige pas. - Toucher aux autres plugins du repo (
abbterra,abbb2x,waveshare-relay-d8, …).
11. BUILD / DEPLOY
- Paquet
eastronversionné1.15.0+etm3. Cross-compilation arm64 via le containerbuild-cross-arm64(Debian trixie amd64 +crossbuild-essential-arm64). - Publié sur les canaux APT
powersync-nightly/powersync-testing/powersync-stable(reprepro, GPG77033A6E…9D1B4986). Recette complète dansDEPLOY.mddu projet. - Déployé sur le RPi
hems(192.168.1.75, canalpowersync-testing) et en prod suretm-nymea-dev(192.168.1.120).
12. DEFINITION OF DONE (pour une modif de ce plugin)
- Le plugin compile (amd64 + cross arm64) et reste cohérent avec le
.pro. - Toute nouvelle valeur passe par un
*-registers.json(déclaratif), pas par du code à la main. - Reachability conservée :
checkReachableRegistervalide,errorLimitUntilNotReachableinchangé sans justification. - UUID neufs pour tout nouvel élément ; UUID existants intacts.
- Testé d'abord en mono-maître (nymead arrêté) au
mbpoll -1, puis intégré via nymead, sur le bus réel. - États visibles et cohérents dans
nymea-app(valeurs qui évoluent,connected=truestable). PORTING_STATUS*/ doc catalogue à jour si le périmètre modèle change.
13. À VÉRIFIER DANS LE CODE (non lu dans ce brief)
Honnêteté sur le périmètre lu : ce brief s'appuie sur les 2 cartes de registres (SDM72/SDM120) + le JSON du plugin + les 3 protocoles constructeur (SDM72/SDM120/SDM230). Restent à confirmer en lisant le dépôt :
integrationplugineastron.cpp/.h: logique de discovery, sélection duModbusRtuMaster, câblage des states, gestion de la reconnexion.eastron.pro: invocation exacte du modbus-tool, liste des*-registers.jsoncompilés.meta.json: packaging (nom, deps, version).sdm230-registers.json: adresses confirmées par le datasheet V1.2 (= SDM120) ; reste à vérifier que le fichier JSON existe bien et porteclassName: "Sdm230".sdm220-registers.json,sdm630-registers.json: non vérifiés — ni le JSON ni le datasheet fournis (SDM630 = 3φ riche type SDM72, SDM220 = 1φ type SDM120/230). Vérifier adresses,checkReachableRegisteret blocks avant de s'y fier.- Variante réellement instanciée pour le SDM72 (principal) et le SDM120 (PV) sur
etm-nymea-dev(cf. §3) — à lire sur le Thing réel, pas à supposer.
14. RÉFÉRENCES
- Source plugin :
git.etm-powersync.fr/ETM-Schurig/etm-powersync-plugins-modbus, dossiereastron/(commitb1da668). - Cartes registres :
eastron/sdm72-registers.json,eastron/sdm120-registers.json(+ 630/220/230). - ThingClasses/interfaces/states :
eastron/integrationplugineastron.json. - Modèle de structure dans le repo :
abbterra(evcharger Modbus TCP),eastronlui-même (pattern registres RTU déclaratif) — cités comme références dans le brief V2C. - Datasheets/protocoles constructeur : Eastron SDM72D-M-2 User Manual V1.1.1 (2023, meter code
00 89), SDM120-Modbus Protocol V2.4, SDM230-Modbus User Manual + Protocol V1.2. Registres input float IEEE754 Big-endian (MSR first), FC04 ; limites de transaction 30 (SDM72) / 40 (SDM120/230) paramètres ; baud max 9600 (SDM120/230) vs 19200 (SDM72).