@impact0815/node-red-contrib-alphaess-modbus 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,317 @@
1
+ <script type="text/html" data-help-name="alphaess-modbus-config">
2
+ <p>Modbus-TCP-Verbindung zu einem Alpha-ESS-System (EMS). Wird von einer oder mehreren <b>AlphaESS-Modbus</b>-Nodes genutzt.</p>
3
+
4
+ <h3>Einstellungen</h3>
5
+ <dl class="message-properties">
6
+ <dt>Host <span class="property-type">IP / Hostname</span></dt>
7
+ <dd>Adresse des EMS im Netzwerk. Eine feste IP-Adresse (DHCP-Reservierung im Router) wird empfohlen.
8
+ Die aktuell genutzte Adresse steht in <code>details.systemConfig.localIp</code>.</dd>
9
+ <dt>Port <span class="property-type">Zahl</span></dt>
10
+ <dd>Modbus-TCP-Port, normalerweise <code>502</code>.</dd>
11
+ <dt>Unit-ID <span class="property-type">Zahl</span></dt>
12
+ <dd>Modbus-Slave-Adresse. Alpha ESS nutzt standardmäßig <code>85</code> (0x55), sichtbar in
13
+ <code>details.systemConfig.modbusAddress</code>.</dd>
14
+ <dt>Timeout <span class="property-type">ms</span></dt>
15
+ <dd>Maximale Wartezeit pro Anfrage (Standard 2000 ms). Bei WLAN- oder Powerline-Verbindungen auf 3000–5000 ms erhöhen.
16
+ Nach einem Timeout wird die Verbindung geschlossen und mit der nächsten Anfrage neu aufgebaut.</dd>
17
+ <dt>Pause <span class="property-type">ms</span></dt>
18
+ <dd>Pause zwischen zwei Anfragen (Standard 20 ms). Auf 50–100 ms erhöhen, wenn das EMS Timeouts
19
+ oder <i>Slave device busy</i> meldet.</dd>
20
+ </dl>
21
+
22
+ <h3>Details</h3>
23
+ <ul>
24
+ <li>Alle Nodes mit dieser Konfiguration teilen sich <b>eine</b> TCP-Verbindung. Anfragen werden nacheinander gesendet,
25
+ nie gleichzeitig.</li>
26
+ <li>Das EMS nimmt meist <b>nur eine Modbus-TCP-Verbindung gleichzeitig</b> an. Weitere Verbindungen werden abgelehnt.</li>
27
+ <li>Modbus TCP muss am System aktiviert sein. Nach Firmware-Updates prüfen, ob es noch aktiv ist.</li>
28
+ </ul>
29
+
30
+ <h3>Fehlersuche</h3>
31
+ <dl class="message-properties">
32
+ <dt><code>ECONNREFUSED</code></dt>
33
+ <dd>Das System ist erreichbar, lehnt die Verbindung aber ab. Fast immer ist noch ein anderer Modbus-Client verbunden:
34
+ <ul>
35
+ <li>alte <code>modbus-getter</code>- / <code>modbus-write</code>-Nodes in anderen Tabs (mit Strg+F nach <code>modbus</code> suchen),</li>
36
+ <li>eine <b>ungenutzte</b> <code>modbus-client</code>-Konfiguration von <i>node-red-contrib-modbus</i> – Node-RED startet
37
+ Konfigurationsnodes auch ohne Nutzer. Unter <i>Konfigurationsnodes</i> löschen und mit <i>Vollständig</i> deployen,</li>
38
+ <li>andere Programme wie Home Assistant, ioBroker, evcc oder ein Wallbox-Lastmanagement.</li>
39
+ </ul>
40
+ Ist nichts anderes verbunden, prüfen, ob Modbus TCP aktiviert ist, oder das EMS neu starten.</dd>
41
+ <dt><code>Timeout</code> / <code>Connect timeout</code></dt>
42
+ <dd>Falsche IP-Adresse, System nicht erreichbar (Netzwerk, Firewall, Docker-Netzwerk) oder eine langsame Verbindung.
43
+ Test vom Node-RED-Rechner aus: <code>nc -zv &lt;ip&gt; 502</code>.</dd>
44
+ <dt><code>Modbus exception 2 (Illegal data address)</code></dt>
45
+ <dd>Das System unterstützt einen Registerblock nicht. Den Block in der Node abschalten (z. B. <i>PV-Zähler</i> bei Anlagen ohne PV-Zähler).
46
+ Blöcke, die in der neueren Registerliste erweitert wurden, fallen automatisch auf die ältere Länge zurück.</dd>
47
+ </dl>
48
+
49
+ <h3>Haftungsausschluss</h3>
50
+ <p>Unabhängiges Community-Projekt, nicht mit Alpha ESS verbunden und nicht von Alpha ESS unterstützt. Bereitgestellt
51
+ „wie besehen“, ohne Gewährleistung – siehe Hilfe der Node <i>AlphaESS Modbus</i> und die LICENSE.</p>
52
+ </script>
53
+
54
+ <script type="text/html" data-help-name="alphaess-modbus">
55
+ <p>Liest Echtzeitdaten eines Alpha-ESS-Speichersystems (SMILE, Storion) lokal per Modbus TCP, berechnet Hausverbrauch,
56
+ Autarkie, Tageswerte und Alarme und sendet auf Wunsch alles per MQTT.
57
+ Steuerbefehle (Dispatch, Einspeisegrenze, Zeitfenster) sind vorhanden, aber <b>standardmäßig abgeschaltet</b>.</p>
58
+
59
+ <h3>Schnellstart</h3>
60
+ <ol>
61
+ <li>Eine Verbindung mit der IP-Adresse des Systems anlegen (Port 502, Unit-ID 85).</li>
62
+ <li>Die Standardblöcke und das Intervall von 15 s beibehalten. An Ausgang 1 eine Debug-Node anschließen.</li>
63
+ <li>Deployen. Nach wenigen Sekunden zeigt der Status <code>PV … | Netz … | SOC … | Last …</code>.</li>
64
+ <li>Optional: einen dauerhaften Kontextspeicher für die Tageswerte einrichten und einen MQTT-Broker auswählen.</li>
65
+ </ol>
66
+ <p>Bleibt der Status rot mit <code>ECONNREFUSED</code>, ist noch ein anderer Modbus-Client verbunden – siehe Hilfe der Verbindungs-Node.</p>
67
+
68
+ <h3>Eingänge</h3>
69
+ <p>Der Befehl wird über <code>msg.topic</code> gewählt. Ohne Topic liest die Node alle Blöcke.</p>
70
+ <dl class="message-properties">
71
+ <dt>topic <span class="property-type">string</span></dt>
72
+ <dd>Einer der Befehle unten.</dd>
73
+ <dt class="optional">payload <span class="property-type">Zahl | Objekt</span></dt>
74
+ <dd>Parameter des Befehls.</dd>
75
+ </dl>
76
+
77
+ <h4>Lesebefehle</h4>
78
+ <dl class="message-properties">
79
+ <dt><code>read</code> (oder kein Topic)</dt>
80
+ <dd>Liest sofort alle aktivierten Blöcke, auch die langsamen. Ergebnis auf Ausgang 1. Nützlich mit Intervall <code>0</code>,
81
+ um die Abfrage über eine eigene Inject-Node zu steuern.</dd>
82
+ <dt><code>readInfo</code></dt>
83
+ <dd>Liest Seriennummern und Firmware-Versionen erneut. Ergebnis auf Ausgang 3.</dd>
84
+ <dt><code>readRaw</code></dt>
85
+ <dd>Liest Rohwerte von Holding-Registern, z. B. um einen Wert mit der Registerdokumentation abzugleichen. Ergebnis auf Ausgang 3.
86
+ <pre>{ "topic": "readRaw", "payload": { "address": 2128, "count": 1 } }</pre>
87
+ <code>address</code> ist dezimal (oder <code>0x0850</code> in einem JSON-Ausdruck), <code>count</code> 1–125.</dd>
88
+ </dl>
89
+
90
+ <h4>Schreibbefehle</h4>
91
+ <p>Benötigen <b>Schreibzugriff erlauben</b>. Ergebnis auf Ausgang 3. Fehler (ungültige Werte, Schreibschutz, Mindestabstand)
92
+ sind Node-Fehler und lassen sich mit einer <i>catch</i>-Node abfangen. Vor der Nutzung bitte den <i>Haftungsausschluss</i> unten lesen.</p>
93
+ <dl class="message-properties">
94
+ <dt><code>timePeriod</code></dt>
95
+ <dd>Ändert die Lade-/Entladezeitfenster und SOC-Grenzen. <b>Nur die angegebenen Felder werden geändert</b>, alles andere bleibt.
96
+ <pre>{ "topic": "timePeriod", "payload": { "upsReserveSoc": 20 } }</pre>
97
+ <pre>{
98
+ "topic": "timePeriod",
99
+ "payload": {
100
+ "flag": 1,
101
+ "chargeCutSoc": 90,
102
+ "charge1": { "start": "01:00", "stop": "05:00" }
103
+ }
104
+ }</pre>
105
+ <ul>
106
+ <li><code>flag</code>: 0 = aus, 1 = Ladefenster aktiv, 2 = Entladefenster aktiv, 3 = beide</li>
107
+ <li><code>upsReserveSoc</code>: SOC in %, der als Reserve bleibt (darunter wird nicht entladen)</li>
108
+ <li><code>chargeCutSoc</code>: SOC in %, bis zu dem in einem Ladefenster aus dem Netz geladen wird</li>
109
+ <li><code>charge1</code>, <code>charge2</code>, <code>discharge1</code>, <code>discharge2</code>:
110
+ <code>{ "start": "HH:MM", "stop": "HH:MM" }</code>, Start oder Stopp allein ist möglich</li>
111
+ </ul>
112
+ Ein niedrigerer <code>upsReserveSoc</code> wirkt sofort: Der Akku kann direkt bis zum neuen Wert entladen.
113
+ Soll das erst zu einer bestimmten Uhrzeit passieren, den Befehl erst dann senden.</dd>
114
+ <dt><code>feedIn</code></dt>
115
+ <dd>Maximale Einspeisung ins Netz in %. Eine Einspeisebegrenzung kann von deinem Netzbetreiber vorgeschrieben sein –
116
+ nur ändern, wenn das zulässig ist.
117
+ <pre>{ "topic": "feedIn", "payload": 70 }</pre>
118
+ <code>{ "percent": 70 }</code> wird ebenfalls akzeptiert.</dd>
119
+ <dt><code>dispatch</code></dt>
120
+ <dd>Lässt den Akku für eine begrenzte Zeit laden oder entladen.
121
+ <pre>{ "topic": "dispatch", "payload": { "power": -3000, "soc": 90, "duration": 900 } }</pre>
122
+ <ul>
123
+ <li><code>power</code> in W: <b>negativ = laden</b>, positiv = entladen (gleiches Vorzeichen wie <code>payload.battery</code>)</li>
124
+ <li><code>soc</code>: Ziel-SOC in %, Standard 100 beim Laden, 10 beim Entladen</li>
125
+ <li><code>duration</code> in s, Standard 300 – danach kehrt das System von selbst in den Normalbetrieb zurück.
126
+ Kurz halten und bei Bedarf wiederholen; ein abgestürzter Flow kann das System dann nicht im Dispatch-Modus zurücklassen.</li>
127
+ <li><code>mode</code>: Standard 2 = <i>State of Charge control</i>. Erlaubt: 1–10 und 19 (<i>No Battery Charge</i>);
128
+ Test- und Inselmodi werden abgelehnt.</li>
129
+ </ul></dd>
130
+ <dt><code>dispatchStop</code></dt>
131
+ <dd>Beendet einen Dispatch sofort. Wird nie durch den <i>Mindestabstand</i> blockiert.</dd>
132
+ </dl>
133
+
134
+ <h3>Ausgänge</h3>
135
+ <ol class="node-ports">
136
+ <li>Daten – eine Nachricht pro Abfragezyklus
137
+ <dl class="message-properties">
138
+ <dt>payload.consumption <span class="property-type">Zahl</span></dt><dd>Hausverbrauch in W</dd>
139
+ <dt>payload.grid <span class="property-type">Zahl</span></dt><dd>Netzleistung in W, <b>+ Bezug / − Einspeisung</b></dd>
140
+ <dt>payload.modules <span class="property-type">Zahl</span></dt><dd>PV-Leistung in W</dd>
141
+ <dt>payload.battery <span class="property-type">Zahl</span></dt><dd>Batterieleistung in W, <b>+ Entladen / − Laden</b></dd>
142
+ <dt>payload.soc <span class="property-type">Zahl</span></dt><dd>Ladezustand in %</dd>
143
+ <dt>payload.gridImport / gridExport / batteryCharge / batteryDischarge <span class="property-type">Zahl</span></dt>
144
+ <dd>dieselben Werte nach Richtung getrennt, immer ≥ 0</dd>
145
+ <dt>payload.autarky <span class="property-type">Zahl</span></dt><dd>Anteil des Hausverbrauchs, der nicht aus dem Netz kommt, in %</dd>
146
+ <dt>payload.selfConsumptionRate <span class="property-type">Zahl</span></dt><dd>Anteil der PV-Leistung, der selbst genutzt wird, in %</dd>
147
+ <dt>payload.daily <span class="property-type">Objekt</span></dt>
148
+ <dd>Energie in kWh seit Mitternacht (Ortszeit): <code>pv</code>, <code>gridFeed</code>, <code>gridImport</code>,
149
+ <code>batteryCharge</code>, <code>batteryDischarge</code>, <code>batteryChargeFromGrid</code>, <code>consumption</code>,
150
+ dazu <code>autarky</code>, <code>selfConsumptionRate</code>, <code>since</code> und <code>complete</code></dd>
151
+ <dt>payload.yesterday <span class="property-type">Objekt</span></dt><dd>die Tageswerte des Vortags</dd>
152
+ <dt>payload.alarms / warnings <span class="property-type">Array</span></dt><dd>aktive Fehler und Warnungen als Text (immer Englisch)</dd>
153
+ <dt>payload.blocks <span class="property-type">Objekt</span></dt>
154
+ <dd>pro Block: <code>age</code> in s seit dem letzten erfolgreichen Lesen, <code>stale</code>, letzter <code>error</code>
155
+ und <code>registers</code>, falls der Block auf die ältere Registerlänge zurückgefallen ist</dd>
156
+ <dt>payload.details <span class="property-type">Objekt</span></dt>
157
+ <dd>alle dekodierten Register pro Block (<code>grid</code>, <code>battery</code>, <code>inverter</code>, …)</dd>
158
+ <dt class="optional">payload.info <span class="property-type">Objekt</span></dt><dd>Seriennummern (Wechselrichter, EMS, WLAN, Batteriemodule) und Firmware-Versionen</dd>
159
+ <dt class="optional">errors <span class="property-type">Objekt</span></dt><dd>Lesefehler dieses Zyklus pro Block</dd>
160
+ </dl>
161
+ <p><code>consumption = modules + grid + battery</code>. Die Felder <code>consumption</code>, <code>grid</code>, <code>modules</code>,
162
+ <code>battery</code> und <code>soc</code> heißen wie in der Cloud-Node <i>node-red-contrib-alphaess</i>.</p>
163
+ </li>
164
+ <li>Alarm – nur bei Änderung von Alarmen oder Warnungen und einmal nach dem Start
165
+ <pre>{ "active": true, "alarms": ["System: Grid_Meter_Lost"], "warnings": [], "timestamp": "…" }</pre>
166
+ <code>active</code> ist <code>true</code>, wenn mindestens ein Alarm aktiv ist. Warnungen allein setzen <code>active</code> nicht.
167
+ Diesen Ausgang mit dem eigenen Benachrichtigungs-Flow verbinden.</li>
168
+ <li>Befehlsantwort – Antwort auf jeden Befehl außer <code>read</code>
169
+ <dl class="message-properties">
170
+ <dt>payload <span class="property-type">Objekt | Array</span></dt>
171
+ <dd>der betroffene Block, nach dem Befehl zurückgelesen (Rohwerte bei <code>readRaw</code>)</dd>
172
+ <dt class="optional">written <span class="property-type">Array</span></dt>
173
+ <dd>geschriebene Register, z. B. <code>[{ "address": "0x0850", "values": [200] }]</code>; leer, wenn nichts geschrieben wurde</dd>
174
+ <dt class="optional">unchanged <span class="property-type">boolean</span></dt>
175
+ <dd><code>true</code>, wenn <code>timePeriod</code> / <code>feedIn</code> die gewünschten Werte schon hatten</dd>
176
+ </dl>
177
+ Alle anderen Eigenschaften der Eingangsnachricht bleiben erhalten.</li>
178
+ </ol>
179
+
180
+ <h3>Einstellungen</h3>
181
+ <dl class="message-properties">
182
+ <dt>Intervall <span class="property-type">s</span></dt>
183
+ <dd>Abfrageintervall für Netz, Batterie, Wechselrichter und Systemdaten. 10–30 s sind sinnvoll. <code>0</code> = nur bei Eingang.</dd>
184
+ <dt>Langsame Blöcke <span class="property-type">s</span></dt>
185
+ <dd>Intervall für Systemkonfiguration, Zeitfenster und Dispatch-Status (Standard 300 s). Diese Werte ändern sich selten.
186
+ Nach einem Schreibbefehl wird der betroffene Block sofort gelesen.</dd>
187
+ <dt>Veraltet nach <span class="property-type">s</span></dt>
188
+ <dd>Zeit ohne erfolgreiches Lesen, nach der ein Block als veraltet gilt (Standard 180 s). Einzelne Lesefehler werden mit dem
189
+ letzten Wert überbrückt; veraltete Blöcke lösen einen Alarm aus und werden aus <code>details</code> entfernt.
190
+ Mindestens das Dreifache des <i>Intervalls</i> wählen.</dd>
191
+ <dt>Topic</dt>
192
+ <dd><code>msg.topic</code> der Datennachrichten. Der Alarm-Ausgang nutzt <code>&lt;topic&gt;/alarm</code>.</dd>
193
+ <dt>EMS</dt>
194
+ <dd>Wählt die Texte für Batteriefehler und -warnungen. Die EMS-Version steht in <code>info.systemInfo.emsVersion</code>.</dd>
195
+ <dt>Blöcke lesen</dt>
196
+ <dd>
197
+ <ul>
198
+ <li><b>Netzzähler</b>, <b>Batterie</b>, <b>Wechselrichter</b>: nötig für Hausverbrauch, Autarkie und Tageswerte.</li>
199
+ <li><b>PV-Zähler (AC-gekoppelt)</b>: nur für Anlagen mit einem zusätzlichen, externen PV-Wechselrichter, der ins Hausnetz einspeist.
200
+ Standardmäßig aus, weil Anlagen ohne PV-Zähler sonst Fehler oder Nullen liefern. Prüfen in <code>details.systemConfig</code>:
201
+ <code>systemMode.text</code> = <code>AC</code> / <code>Hybrid</code> oder <code>pvCapacityGridInverter</code> &gt; 0
202
+ sprechen für einen PV-Zähler; bei <code>DC</code> und <code>0</code> ausgeschaltet lassen.</li>
203
+ <li><b>Systemlaufdaten</b>: Systemfehler (z. B. <i>Grid_Meter_Lost</i>, <i>BMS_Lost</i>) und die Energie des externen PV-Wechselrichters.</li>
204
+ <li><b>Systemkonfiguration</b>, <b>Zeitfenster</b>, <b>Dispatch-Status</b>: aktuelle Einstellungen; nötig, um die Wirkung von Schreibbefehlen zu sehen.</li>
205
+ <li><b>Geräteinfos</b>: Seriennummern und Firmware-Versionen, beim Start und einmal täglich gelesen.</li>
206
+ </ul></dd>
207
+ <dt>PV-Zähler zu PV-Leistung / Tages-PV-Energie addieren</dt>
208
+ <dd>Rechnet den externen PV-Wechselrichter in <code>modules</code>, <code>consumption</code> und <code>daily.pv</code> ein.
209
+ Benötigt die Blöcke <i>PV-Zähler</i> und <i>Systemlaufdaten</i>.</dd>
210
+ <dt>Tageswerte-Speicher</dt>
211
+ <dd>Kontextspeicher für die Tageswerte. Die Liste zeigt die in <code>settings.js</code> konfigurierten Speicher.
212
+ Mit dem Standard-Arbeitsspeicher beginnen die Tageswerte nach jedem Node-RED-Neustart neu – siehe <i>Tageswerte</i>.</dd>
213
+ <dt>MQTT-Broker / Präfix / QoS / Retain</dt>
214
+ <dd>Sendet direkt über eine vorhandene MQTT-Broker-Konfiguration, ohne MQTT-out-Node. Siehe <i>MQTT</i>.</dd>
215
+ <dt>Blockdetails als JSON senden</dt>
216
+ <dd>Sendet zusätzlich jeden Block als JSON an <code>&lt;Präfix&gt;/details/&lt;Block&gt;</code>. Größere Nachrichten; standardmäßig aus.</dd>
217
+ <dt>Schreibzugriff erlauben</dt>
218
+ <dd>Schaltet die Schreibbefehle frei. Ohne diese Option schlagen Schreibbefehle mit einem Fehler fehl und es wird nichts geschrieben.
219
+ Ist sie aktiv, schreibt die Node beim Start einen Hinweis ins Log.</dd>
220
+ <dt>Max. Leistung <span class="property-type">W</span></dt>
221
+ <dd>Obergrenze für die Leistung bei <code>dispatch</code>. Empfohlen: die maximale Lade-/Entladeleistung deiner Batterie
222
+ (<code>details.battery.maxChargePower</code>).</dd>
223
+ <dt>Mindestabstand <span class="property-type">s</span></dt>
224
+ <dd>Mindestzeit zwischen zwei tatsächlichen Schreibvorgängen desselben Befehls (Standard 10 s, <code>0</code> = aus).
225
+ Schützt das EMS vor Schleifen im Flow. Anfragen ohne Änderung und <code>dispatchStop</code> werden nicht blockiert.</dd>
226
+ <dt>SOC-Skalierung <span class="property-type">%/bit</span></dt>
227
+ <dd>Auflösung von <code>upsReserveSoc</code> und <code>chargeCutSoc</code>. Laut Dokumentation 0,1 %/bit, es gibt aber Anlagen
228
+ mit 1 %/bit. <b>Vor dem ersten Schreiben prüfen:</b> <code>readRaw</code> mit <code>{"address": 2128, "count": 1}</code> senden.
229
+ Ist die Reserve in der App 10 % und der Rohwert <code>10</code>, <code>1</code> einstellen; ist er <code>100</code>, bei <code>0.1</code> bleiben.</dd>
230
+ </dl>
231
+
232
+ <h3>Tageswerte</h3>
233
+ <p>Das System liefert nur Gesamtzähler. Die Node merkt sich die Zählerstände um Mitternacht (Ortszeit) und berechnet die Differenz.</p>
234
+ <ul>
235
+ <li><code>daily.since</code>: Beginn der Zählung. <code>daily.complete</code>: <code>true</code>, wenn die Zählung höchstens
236
+ 15 Minuten nach Mitternacht begonnen hat – nur dann ist der ganze Tag erfasst. Damit lassen sich unvollständige Tage in Statistiken ignorieren.</li>
237
+ <li>Damit die Werte einen Neustart überstehen, in <code>settings.js</code> einen dauerhaften Speicher eintragen, Node-RED neu starten,
238
+ den Editor neu laden und ihn als <i>Tageswerte-Speicher</i> auswählen:
239
+ <pre>contextStorage: {
240
+ default: { module: "memory" },
241
+ file: { module: "localfilesystem" }
242
+ },</pre>
243
+ Im Docker-Container (offizielles Image) liegt die Datei unter <code>/data/settings.js</code>.</li>
244
+ <li>Existiert der gewählte Speicher nicht, nutzt Node-RED stillschweigend den Arbeitsspeicher. Die Node erkennt das und zeigt einen
245
+ gelben Status und eine Warnung.</li>
246
+ <li>Der laufende Tag lässt sich nachträglich nicht korrigieren: Korrekte Werte gibt es ab der nächsten Mitternacht.</li>
247
+ </ul>
248
+
249
+ <h3>MQTT</h3>
250
+ <p>Topics mit dem Standard-Präfix <code>alphaess</code>:</p>
251
+ <ul>
252
+ <li><code>alphaess/consumption</code>, <code>/grid</code>, <code>/modules</code>, <code>/battery</code>, <code>/soc</code>,
253
+ <code>/gridImport</code>, <code>/gridExport</code>, <code>/batteryCharge</code>, <code>/batteryDischarge</code>,
254
+ <code>/autarky</code>, <code>/selfConsumptionRate</code> – Zahlen, in jedem Zyklus</li>
255
+ <li><code>alphaess/daily/&lt;Feld&gt;</code> – Tageswerte, <code>alphaess/daily/complete</code> – <code>true</code>/<code>false</code></li>
256
+ <li><code>alphaess/status</code> – <code>ok</code> oder <code>alarm</code></li>
257
+ <li><code>alphaess/alarm</code> – JSON wie auf Ausgang 2, nur bei Änderung</li>
258
+ <li><code>alphaess/info</code> – JSON, immer mit Retain</li>
259
+ <li><code>alphaess/details/&lt;Block&gt;</code> – JSON, optional</li>
260
+ </ul>
261
+ <p>Wenn du Werte schon über eigene MQTT-Nodes weiterleitest, den Broker leer lassen, sonst kommen Nachrichten doppelt.</p>
262
+
263
+ <h3>Beispiele</h3>
264
+ <h4>Wert setzen mit Rückmeldung (link call)</h4>
265
+ <p>Befehle aus anderen Tabs mit einer <i>link call</i>-Node an eine <i>link in</i>-Node vor dieser Node schicken.
266
+ Für die Antwort Ausgang 3 mit einer <i>switch</i>-Node auf <code>msg._linkSource</code> (<i>ist nicht leer</i>) verbinden,
267
+ danach eine <i>link out</i>-Node im Modus <i>Return to calling link node</i>. Antworten auf Befehle, die nicht per link call
268
+ kamen (z. B. von einer Inject-Node), gehen auf den Ausgang <i>sonst</i>.</p>
269
+ <h4>Reserve-SOC abhängig von der Wetterprognose</h4>
270
+ <pre>// Function-Node vor dem link call
271
+ const sun = Number(global.get("sunhourstomorrow"));
272
+ if (!Number.isFinite(sun)) return null;
273
+ return { topic: "timePeriod",
274
+ payload: { upsReserveSoc: sun >= 3 ? 10 : 20 } };</pre>
275
+ <p>Der Befehl darf beliebig oft gesendet werden: Ist der Wert schon gesetzt, wird nichts geschrieben und die Antwort enthält
276
+ <code>unchanged: true</code>.</p>
277
+ <h4>Werte in anderen Flows nutzen</h4>
278
+ <pre>// Function-Node hinter Ausgang 1
279
+ global.set("alphaess", msg.payload);
280
+ return { payload: msg.payload.consumption };</pre>
281
+ <h4>Einzelnes Register prüfen</h4>
282
+ <pre>{ "topic": "readRaw", "payload": { "address": 1024, "count": 10 } }</pre>
283
+
284
+ <h3>Sprachen</h3>
285
+ <p>Editor und Hilfe gibt es auf Englisch und Deutsch; sie folgen der Spracheinstellung des Editors.
286
+ Statustexte und Log-Meldungen folgen der Sprache des Node-RED-Servers. Daten in <code>msg.payload</code>
287
+ (Feldnamen, Alarm- und Warnungstexte) sind immer Englisch, damit Flows unabhängig von der Sprache funktionieren.</p>
288
+
289
+ <h3>Haftungsausschluss</h3>
290
+ <ul>
291
+ <li>Dies ist ein unabhängiges Community-Projekt. Es ist <b>nicht mit Alpha ESS verbunden und wird von Alpha ESS weder
292
+ unterstützt noch empfohlen</b>. Produktnamen dienen nur zur Beschreibung der Kompatibilität; Marken gehören ihren Inhabern.</li>
293
+ <li>Die Software wird <b>„wie besehen“ und ohne jede Gewährleistung</b> bereitgestellt (MIT-Lizenz). Die Nutzung erfolgt
294
+ <b>auf eigene Gefahr</b>; eine Haftung ist ausgeschlossen, soweit gesetzlich zulässig.</li>
295
+ <li>Das Lesen von Daten verändert das System nicht. <b>Schreibbefehle schon</b>: Falsche Werte können zu ungewolltem Netzbezug,
296
+ zu tiefer oder zu flacher Entladung, fehlender Notstromreserve oder einer Einspeisung entgegen den Vorgaben des Netzbetreibers
297
+ führen und die Herstellergarantie berühren.</li>
298
+ <li>Schreibzugriff nur aktivieren, wenn die Wirkung jedes Befehls klar ist. Mit kurzen <code>duration</code>-Werten beginnen
299
+ und das Ergebnis in der Hersteller-App prüfen.</li>
300
+ <li>Registeradressen und Skalierungen beruhen auf der Herstellerdokumentation und Tests an einzelnen Anlagen.
301
+ Dein Modell oder deine Firmware kann sich anders verhalten.</li>
302
+ </ul>
303
+
304
+ <h3>Hinweise</h3>
305
+ <ul>
306
+ <li>Nach der Installation einer neuen Version Node-RED neu starten und den Editor neu laden (F5), sonst fehlen neue Ausgänge und Einstellungen.</li>
307
+ <li>Sicherheitstest, Reset, CT-Kalibrierung, Netzwerk-/Modbus-Einstellungen und die MOS-Steuerung der Batterie sind bewusst nicht beschreibbar.</li>
308
+ <li>Registeradressen und Skalierung: <i>AlphaESS Household Modbus Register Parameter List</i>. Ältere Firmware, die nur die
309
+ Registerliste V1.1 kennt, wird automatisch erkannt.</li>
310
+ </ul>
311
+
312
+ <h3>Weitere Informationen</h3>
313
+ <ul>
314
+ <li><a href="https://github.com/impact0815/node-red-contrib-alphaess-modbus/blob/main/README.de.md">Deutsche README mit allen Feldern und Registerblöcken</a></li>
315
+ <li><a href="https://nodered.org/docs/user-guide/context#context-stores">Node-RED: Kontextspeicher (englisch)</a></li>
316
+ </ul>
317
+ </script>
@@ -0,0 +1,106 @@
1
+ {
2
+ "alphaess-modbus": {
3
+ "label": {
4
+ "connection": "Verbindung",
5
+ "host": "Host",
6
+ "port": "Port",
7
+ "unitId": "Unit-ID",
8
+ "timeout": "Timeout",
9
+ "delay": "Pause",
10
+ "interval": "Intervall",
11
+ "slowInterval": "Langsame Blöcke",
12
+ "staleAfter": "Veraltet nach",
13
+ "topic": "Topic",
14
+ "platform": "EMS",
15
+ "blocks": "Blöcke lesen",
16
+ "includePvMeter": "PV-Zähler zu PV-Leistung / Tages-PV-Energie addieren",
17
+ "contextStore": "Tageswerte-Speicher",
18
+ "mqttBroker": "Broker",
19
+ "mqttPrefix": "Präfix",
20
+ "mqttQos": "QoS",
21
+ "mqttRetain": "Retain",
22
+ "mqttDetails": "Blockdetails als JSON senden",
23
+ "allowWrite": "Schreibzugriff erlauben",
24
+ "maxPower": "Max. Leistung",
25
+ "writeInterval": "Mindestabstand",
26
+ "socScale": "SOC-Skalierung"
27
+ },
28
+ "unit": {
29
+ "unitId": "(Standard 85 = 0x55)",
30
+ "ms": "ms",
31
+ "delay": "ms zwischen Anfragen",
32
+ "interval": "s (0 = nur bei Eingang)",
33
+ "slowInterval": "s (Konfiguration, Zeitfenster, Dispatch)",
34
+ "staleAfter": "s ohne erfolgreiches Lesen",
35
+ "allowWrite": "(Dispatch, Einspeisung, Zeitfenster)",
36
+ "maxPower": "W (Dispatch-Grenze)",
37
+ "writeInterval": "s zwischen zwei Schreibvorgängen desselben Befehls (0 = aus)",
38
+ "socScale": "%/bit für die SOC-Werte der Zeitfenster"
39
+ },
40
+ "placeholder": {
41
+ "host": "192.168.1.100",
42
+ "maxPower": "z. B. 5000"
43
+ },
44
+ "block": {
45
+ "grid": "Netzzähler",
46
+ "pvMeter": "PV-Zähler (AC-gekoppelt)",
47
+ "battery": "Batterie",
48
+ "inverter": "Wechselrichter",
49
+ "systemRun": "Systemlaufdaten / Systemfehler",
50
+ "systemConfig": "Systemkonfiguration (langsam)",
51
+ "timePeriod": "Zeitfenster (langsam)",
52
+ "dispatch": "Dispatch-Status (langsam)",
53
+ "info": "Geräteinfos (beim Start, dann täglich)"
54
+ },
55
+ "section": {
56
+ "mqtt": "MQTT",
57
+ "control": "Steuerung"
58
+ },
59
+ "outputs": {
60
+ "data": "Daten",
61
+ "alarm": "Alarm (bei Änderung)",
62
+ "response": "Befehlsantwort"
63
+ },
64
+ "store": {
65
+ "default": "Standard (__store__)",
66
+ "notConfigured": "__store__ (nicht in settings.js konfiguriert)",
67
+ "missing": "Dieser Speicher existiert nicht – die Tageswerte werden nicht dauerhaft gespeichert.",
68
+ "onlyMemory": "Es ist nur der Arbeitsspeicher konfiguriert. Trage in settings.js unter contextStorage einen dauerhaften Speicher ein (z. B. \"file\"), damit die Tageswerte einen Neustart überstehen."
69
+ },
70
+ "tip": {
71
+ "writeWarning": "Schreibbefehle verändern, wie dein Speichersystem lädt, entlädt und ins Netz einspeist. Nutzung auf eigene Gefahr – es gibt keine Gewährleistung. Stelle sicher, dass die Änderungen mit der Herstellergarantie und den Vorgaben deines Netzbetreibers vereinbar sind.",
72
+ "disclaimer": "Unabhängiges Community-Projekt, nicht mit Alpha ESS verbunden. Bereitgestellt wie besehen, ohne Gewährleistung."
73
+ },
74
+ "status": {
75
+ "noConnection": "keine Verbindung konfiguriert",
76
+ "polling": "Abfrage alle __interval__ s",
77
+ "manual": "manueller Modus",
78
+ "storeMissing": "Kontextspeicher \"__store__\" fehlt in settings.js",
79
+ "storeMissingShort": "Speicher \"__store__\" fehlt",
80
+ "pv": "PV __value__W",
81
+ "grid": "Netz __value__W",
82
+ "soc": "SOC __value__%",
83
+ "load": "Last __value__W",
84
+ "ok": "ok",
85
+ "unchanged": "__command__: unverändert",
86
+ "written": "__command__: __count__ Register geschrieben",
87
+ "dispatch": "Dispatch __power__W",
88
+ "dispatchStopped": "Dispatch gestoppt"
89
+ },
90
+ "warn": {
91
+ "storeMissing": "Tageswerte: Kontextspeicher \"__store__\" ist nicht in settings.js konfiguriert – die Tageswerte werden nicht dauerhaft gespeichert und beginnen nach jedem Node-RED-Neustart neu",
92
+ "writeEnabled": "Schreibzugriff ist aktiviert. Schreibbefehle verändern das Verhalten des Speichersystems – Nutzung auf eigene Gefahr.",
93
+ "pollRunning": "Abfrage läuft bereits – Anfrage übersprungen"
94
+ },
95
+ "log": {
96
+ "fallback": "__block__: erweiterte Register werden von diesem System nicht unterstützt, lese __min__ statt __count__ Register",
97
+ "unsupported": "__block__: wird von diesem System nicht unterstützt"
98
+ },
99
+ "errors": {
100
+ "writeDisabled": "Schreiben ist deaktiviert – aktiviere \"Schreibzugriff erlauben\" in den Einstellungen der Node",
101
+ "rateLimited": "__command__: Schreiben blockiert, nächster Schreibvorgang in __wait__ s möglich (Mindestabstand __interval__ s)",
102
+ "unknownTopic": "Unbekanntes Topic \"__topic__\"",
103
+ "addressRange": "payload.address muss zwischen 0 und 65535 liegen"
104
+ }
105
+ }
106
+ }