# Modbus-TCP-Dokumentation

> Dieses Dokument beschreibt die Modbus-TCP-Schnittstelle der eCharge-EVCS-Firmware: die vollständige Registerbelegung, Transport- und Sitzungsregeln, Zeit- und Failsafe-Verhalten sowie durchgerechnete Integrationsbeispiele. Es gilt für die lokale Ladestation (EVCS) unter Unit ID `1`.

> **Dokumentversion:** 2.1.1 (Registerbelegung `MapVersion 2.1.0`). **Firmware-Basis:** das Release, das `MapVersion 2.1.0` trägt – zur Bestätigung `MapVersion` (`40001`) auf der Station lesen. **Zuletzt aktualisiert:** 2026-08-26. Was sich gegenüber der vorherigen Revision (`2.1.0`) geändert hat, steht in der **Dokumenthistorie** am Ende.

> **Umstieg von einer Integration auf Basis von** `MapVersion 2.0.0`. Kein Register ist umgezogen und nichts wurde entfernt, ein bestehender Client funktioniert also weiter. Vier Verhaltensweisen haben sich geändert und ein Block ist neu: Die Grenzen des Ladestroms werden jetzt aus dem Fenster der Station selbst übernommen, ein Start mit Stromsollwert null wird mit `0x03` statt `0x04` gemeldet, `EVCS_State` meldet CHARGING auch für Sitzungen, die nicht vom EMS gestartet wurden, Übertemperatur löscht sich von selbst, und der tatsächliche Lademodus / EcoPlus / Pausenzustand der Station ist unter IR `30601-30603` lesbar. Jede Änderung ist unten an Ort und Stelle beschrieben und in der **Dokumenthistorie** zusammengefasst.

---

## Überblick

Die Firmware stellt eine standardkonforme Modbus-TCP-Schnittstelle über Ethernet zur Fernüberwachung und Fernsteuerung von Ladevorgängen bereit. Externe Systeme (z. B. EMS/SCADA) lesen Telemetrie und schreiben Konfiguration oder Sollwerte über eine zusammenhängende, überlappungsfreie Registerbelegung: **Input-Register** für Nur-Lese-Daten und **Holding-Register** für Lese-/Schreibdaten.

### Geltungsbereich

Diese Spezifikation gilt für eine **unidirektionale AC**-Ladestation (EVCS) mit optionaler **1↔3-Phasen-Umschaltung**. **DC-Laden** und **bidirektionaler (V2G)** Betrieb werden **nicht unterstützt**.

**Abgedeckte Register**

* **Identifikation**: Seriennummer, Modell, Hersteller, Firmware-Version.
* **Konfiguration**: Stromgrenzen, Eco-/Effizienzmodi und die eigenen aktuellen Einstellungen der Station, getrennt rücklesbar von dem, was das EMS angefordert hat.
* **Betriebszustand**: Stationszustand, Steckverbinderzustand, Autorisierungsstatus, Fehlercodes, Daemon-Gesundheit.
* **EVSE- und CP-Parameter**: Verfügbarkeit, Stromgrenzen je Anschluss, CP-Status, Schütz-/Steckerstatus, Status der Phasenumschaltung.
* **Zähler-Telemetrie**: Spannung, Strom, Leistung, Energie, Temperatur je Phase und gesamt.
* **Netz-/Batterie-Telemetrie**: Netz- und Speicherdaten aus der Station.
* **Steuerregister**: Stromsollwert, Ladung starten/stoppen, Failsafe-Timeout und Rückfallstrom, Phasenwahl.

---

## Protokoll – Transport und Sitzung

### Verbindung

* **Server-Rolle**: Die Ladestation implementiert einen **Modbus-TCP-Server** auf **TCP-Port 502**.
* **Clients**: Externe Systeme (EMS/SCADA) agieren als **Clients/Master** und initiieren alle Anfragen; die Ladestation antwortet als Server/Slave.
* **IP-Konfiguration**: DHCP (Standard) oder statische IP.
* **Unit ID**: Standard `0x01`. Die Unit ID ist konfigurierbar (gültiger Bereich `1-247`). Dieses Dokument beschreibt die Ladestation unter Unit ID `1`. Dasselbe Gateway kann unter anderen Unit IDs auch weitergeleitete nachgelagerte Slave-Geräte und einen Fronius-SMEM-Emulator bedienen – diese haben ihre eigene Dokumentation.

### Verbindung und Inbetriebnahme

Bevor Ihre Integration mit der Ladestation sprechen kann, sollten Sie die Zugriffskontrollen auf Verbindungsebene kennen (Details unter **Sicherheitshinweise**):

* **IP-Allow-List (optional).** Wenn Ihr Installateur sie aktiviert hat, dürfen nur eingetragene Quell-IP-Adressen verbinden. Eine Verbindung von einer nicht eingetragenen IP wird **sofort ohne Modbus-Antwort geschlossen** – das sieht genauso aus wie ein Gerät, das offline ist (TCP-Reset). Wenn Sie gar keine Verbindung bekommen, prüfen Sie, ob Ihre Client-IP auf der Allow-List steht.
* **Verbindungslimits.** Bis zu **32** gleichzeitige Verbindungen insgesamt und **4** je Quell-IP. Überzählige Verbindungsversuche werden beim Accept verworfen (wieder ohne Modbus-Antwort).
* **Ratenbegrenzung.** Bis zu **50 Anfragen/Sekunde** je Quell-IP (Burst **100**). Anfragen über dem Limit erhalten auf einer offenen Verbindung Exception `0x06` (Server Device Busy) – warten und erneut versuchen.
* **Startvorgang.** Solange der Daemon noch startet, wird jede Anfrage mit Exception `0x06` beantwortet. Fragen Sie **DaemonStatus** (`30050`) ab und machen Sie die Automatisierung von der Bereitschaft abhängig.

### Nachrichtenformat (MBAP + PDU)

Jede Modbus-TCP-ADU besteht aus:

* **MBAP-Header**

    * **Transaction Identifier**
    * **Protocol Identifier** (bei Modbus immer `0x0000`)
    * **Length** (Anzahl der folgenden Bytes)
    * **Unit Identifier**
    
* **PDU (Protocol Data Unit)**

    * **Funktionscode**
    * **Nutzdaten**
    

### Transporteigenschaften

* TCP/IP sorgt für zuverlässige, geordnete Zustellung und Flusskontrolle.
* Die maximale MBAP-Länge beträgt **254 Bytes** (gemäß Modbus-TCP-Spezifikation).

### Unterstützte Funktionscodes

| Funktion | Code (hex/dez) | Zweck | Hinweise |
| --- | --- | --- | --- |
| Read Holding Registers  | `0x03 / 3`  | Ein oder mehrere Holding-Register lesen (Konfiguration und Sollwerte).  | Liest bis zu **125** zusammenhängende Register je Anfrage.  |
| Read Input Registers  | `0x04 / 4`  | Ein oder mehrere Input-Register lesen (Nur-Lese-Telemetrie).  | Die Daten stammen aus einem **konsistenten Snapshot**.  |
| Write Single Register  | `0x06 / 6`  | Ein einzelnes Holding-Register schreiben.  | Werte außerhalb des Bereichs werden mit Exception `0x03` abgelehnt.  |
| Write Multiple Registers  | `0x10 / 16`  | Mehrere zusammenhängende Holding-Register **atomar** schreiben.  | Akzeptiert **1-123** Register; falsch ausgerichtete oder Teilwort-Telegramme liefern Exception `0x03`.  |

**Hinweise**

* Nicht unterstützte Funktionscodes liefern Exception `0x01` (Illegal Function). Die optionalen Discovery-Funktionen Report Slave ID (`0x11`) und Read Device Identification (`0x2B/0x0E`) werden **nicht unterstützt** und liefern `0x01`.
* „Konsistenter Snapshot“ stellt sicher, dass Mehrregister-Lesezugriffe auf denselben Wert (z. B. einen 32-Bit-Float) nicht über Aktualisierungen hinweg vermischt werden.
* „Atomarer Schreibzugriff“ stellt sicher, dass entweder alle Register der Anfrage gemeinsam übernommen werden oder keines.

### Exception-Codes

Kann die Ladestation eine Anfrage nicht erfüllen, liefert sie eine Modbus-**Exception-Antwort** (Funktionscode ODER-verknüpft mit `0x80`) mit einem Ein-Byte-Exception-Code:

| Code (hex/dez) | Name | Wann er auftritt |
| --- | --- | --- |
| `0x01 / 1`  | Illegal Function  | Der angeforderte Funktionscode wird nicht unterstützt (z. B. Discovery-FCs `0x11`/`0x2B`).  |
| `0x02 / 2`  | Illegal Data Address  | Die Adresse (oder der Bereich) liegt außerhalb der implementierten Belegung, oder ein Schreibzugriff zielt auf eine gültige, aber nicht beschreibbare Holding-Adresse.  |
| `0x03 / 3`  | Illegal Data Value  | Der Wert liegt außerhalb des Bereichs, das Ziel ist nur lesbar, oder ein Mehrregister-Schreibzugriff ist fehlerhaft aufgebaut (falsch ausgerichtet/falsche Länge).  |
| `0x04 / 4`  | Slave Device Failure  | Ein interner Fehler hat die Ausführung verhindert – der Befehl hat das Gerät erreicht, konnte aber nicht an die Ladesteuerung übergeben werden. Er weist **nicht** auf einen ungültigen Wert hin; ein abgelehnter Wert ist immer `0x03`.  |
| `0x06 / 6`  | Server Device Busy  | Sie werden ratenbegrenzt (kurz warten und erneut versuchen), oder der Daemon schließt noch den Startvorgang ab (erneut versuchen und DaemonStatus prüfen).  |
| `0x0A / 10`  | Gateway Path Unavailable  | Nur beim Adressieren eines über das Gateway weitergeleiteten **Slave**-Geräts: Der entfernte Slave ist nicht erreichbar. Die lokale Ladestation (Unit ID `1`) liefert dies nie.  |
| `0x0B / 11`  | Gateway Target Device Failed to Respond  | Die adressierte **Unit ID** wird von diesem Gateway nicht bedient – prüfen Sie Ihre Unit ID.  |

> **Hinweis zu abgewiesenen Verbindungen.** Eine Blockierung durch die IP-Allow-List oder ein Verbindungslimit ist **keine** Modbus-Exception – die TCP-Verbindung wird ohne PDU geschlossen. Meldet Ihr Client „connection refused/reset“ statt einer Modbus-Exception, liegt der Verdacht auf der Allow-List oder einem Verbindungslimit, nicht auf einem Gerätefehler.

### Sitzungsverhalten und Zeitverhalten

* **Antwortformat**: Alle Antworten folgen der Modbus-TCP-ADU-Struktur (MBAP-Header + PDU) mit korrekter Modbus-Byte-/Wortreihenfolge.
* **Latenzziel**: p95 &lt; **200 ms** unter nominalen LAN-Bedingungen.
* **Konsistenz**: Mehrregister-Lesezugriffe werden aus einem kohärenten Snapshot beantwortet; Mehrregister-Schreibzugriffe sind atomar.
* **Client-Abfrage**: Telemetrie in einem Intervall von **≤ 5 s** abfragen; Steuersollwerte (oder den Heartbeat) häufiger auffrischen als das konfigurierte Failsafe-Timeout (siehe **Zeitregeln**).
* **Validierung**: Werte außerhalb des Bereichs werden mit Exception `0x03` **abgelehnt**; das Register behält seinen vorherigen Wert (kein Begrenzen auf den Randwert).
* **Timeouts**: Eine Verbindung wird nach **5 Minuten** Leerlauf geschlossen; jede Anfrage-/Antwort-Operation hat eine Frist von **15 s**.

---

## Datendarstellung und Endianness

### Endianness

* **Wortreihenfolge**: Werte über mehrere Register verwenden **Big-Endian-Wortreihenfolge** (höherwertiges Wort an der niedrigeren Registeradresse).
* **Bytereihenfolge**: Jedes 16-Bit-Register verwendet **Big-Endian-Bytereihenfolge** (MSB zuerst).

### Datentypen

* `float32` (IEEE-754): Leistung, Spannung, Strom, Energie, CP-Tastverhältnis, Netz-/Batteriewerte.
* `uint16` (u16): Aufzählungen, Bitfelder, kleine Zahlenwerte.
* `uint32` (u32): Zähler (Uptime) und **Temperature** (ganzzahlige Grad Celsius – siehe Hinweis).
* **Bitfelder**: Sofern nicht anders angegeben, ist Bit `0` das LSB des Registers.

> **Die Temperatur ist eine `u32`-Ganzzahl, kein Float.** `Temperature` (`30025`) ist ein Big-Endian-`u32` in ganzen Grad Celsius (Werte unter null werden als `0` gelesen). Nicht als IEEE-754 dekodieren.

### Zeichenketten

* ASCII, **zwei Zeichen je 16-Bit-Register** (MSB = erstes Zeichen).
* Unbenutzte Bytes sind `0x00`. Zeichenketten haben feste Länge und sind über das Auffüllen hinaus nicht nullterminiert; Clients müssen abschließende Nullen abschneiden.

### Skalierung

* Register führen **fertige Werte in technischen Einheiten** (V, A, W, Hz, kWh, Grad C) mit **Skalierung 1.0**. Der Daemon hat die internen Milli-/Centi-Einheiten der Firmware bereits umgerechnet, clientseitig ist also keine weitere Skalierung nötig.

### Validierung

* Jedes beschreibbare Register definiert gültige Grenzen; Werte außerhalb dieser Grenzen werden mit Exception `0x03` **abgelehnt**, und das Register bleibt **unverändert**. Es gibt kein Begrenzen auf den nächstgelegenen Wert, ein erneutes Lesen nach einem abgelehnten Schreibzugriff zeigt also den vorherigen Wert.

### Nebenläufigkeit und Atomarität

* **Single-Writer-Semantik**: Register-Commits werden intern serialisiert und nacheinander übernommen; Schreibzugriffe scheitern nie aus Gründen der Nebenläufigkeit. Seiteneffekte laufen nach dem Commit, wenn also zwei Clients dasselbe Register nahezu gleichzeitig schreiben, gewinnt der spätere Commit – eine an den früheren Client zurückgegebene Exception garantiert nicht, dass das Register seinen vorherigen Wert behalten hat. Lesen Sie das Register zurück, wenn Sie den resultierenden Zustand sicher kennen müssen.
* **Atomare Mehrregister-Schreibzugriffe**: Ein Mehrregister-Schreibzugriff (FC16) wird ganz oder gar nicht übernommen. Falsch ausgerichtete oder Teilwort-Telegramme werden mit Exception `0x03` abgelehnt.
* **Wechselwirkung Lesen/Schreiben**: Lesezugriffe blockieren keine Schreibzugriffe. Ein Lesezugriff kann kurz verzögert werden, um einen kohärenten Snapshot zu liefern, während ein laufender Schreibzugriff abgeschlossen wird.

### Sicherheitshinweise

Modbus TCP selbst bietet weder Vertraulichkeit noch Integrität oder Authentifizierung – der Transport ist **Klartext** (kein TLS, keine Client-Authentifizierung). Betreiben Sie die Ladestation in einem isolierten/vertrauenswürdigen Netz oder hinter einem sicheren Gateway. Zusätzlich setzt die Ladestation die folgenden Kontrollen auf Transportebene durch:

| Kontrolle | Verhalten |
| --- | --- |
| IP-Allow-List  | Optional. Wenn aktiviert, werden Verbindungen von nicht eingetragenen Quell-IPs beim Accept geschlossen (keine Modbus-Antwort). Die Aktivierung erfordert mindestens einen gültigen Adressbereich.  |
| Ratenbegrenzung je IP  | 50 Anfragen/Sekunde je Quell-IP, Burst 100. Anfragen über dem Limit liefern Exception `0x06`.  |
| Verbindungslimits  | Maximal 32 gleichzeitige Verbindungen insgesamt und 4 je Quell-IP. Überzählige Versuche werden beim Accept verworfen.  |
| Leerlauf-/IO-Timeouts  | Leerlaufverbindungen werden nach 5 Minuten geschlossen; jede Operation hat eine Frist von 15 s (Schutz vor hängenden Clients).  |
| Startsperre  | Anfragen werden mit Exception `0x06` beantwortet, bis der Daemon den Startvorgang abgeschlossen hat.  |

> IP-Allow-List, Unit ID, Rolle und zugehörige Einstellungen werden von Ihrem eCharge-Installateur/-Betreiber konfiguriert (über die Web-Konfiguration der Ladestation). Bitten Sie ihn, die Quell-IP Ihres EMS vor der Integration in die Allow-List aufzunehmen.

---

## Adressierungskonventionen

* **PDU-Adressierung**: Modbus-Registeradressen in der PDU sind **nullbasiert**.
* **Lesbare Schreibweise**: Die Dokumentation zeigt `30001+` (Input) und `40001+` (Holding). Adresse = `Offset + 30001` (Input) bzw. `Offset + 40001` (Holding).
* **Breite**: Alle Adressen beziehen sich auf 16-Bit-Register; Mehrwortwerte belegen aufeinanderfolgende Register mit dem höherwertigen Wort an der niedrigeren Adresse.
* **Reservierte Bereiche**: Reservierte Einträge sind aus den Registertabellen weggelassen, sofern ihr Verhalten nicht relevant ist (`40077`, `40108`, `30051-30059`, `30604-30610`); sie dürfen nicht angesprochen werden. Lesezugriffe auf reservierte Bereiche liefern `0`, Schreibzugriffe können Exception `0x02` liefern.

| Klasse | Nullbasierter Offset | Lesbare Schreibweise |
| --- | --- | --- |
| Input  | `0`  | `30001`  |
| Input  | `15`  | `30016`  |
| Holding  | `0`  | `40001`  |
| Holding  | `42`  | `40043`  |

---

## Geräteidentität und Versionierung

Die Ladestation stellt eine stabile Identitätsschnittstelle bereit – Seriennummer, Modellkennung, Hersteller und Firmware-Version – für Registrierung, Kompatibilitätsprüfungen und Fernverwaltung. Identitätsfelder sind reine Lese-**Holding**-Register (FC03), ASCII-Zeichenketten mit zwei Zeichen je Register.

* **Seriennummer** – eindeutig je Gerät; über die Gerätelebensdauer konstant.
* **Modellkennung** – Produktfamilie.
* **Hersteller** – Herstellername.
* **Firmware-Version** – der laufende Software-Build, als Zeichenkette und als gepackter `u32`.
* **Version der Registerbelegung** – `MapVersion` gibt die Revision dieser Modbus-Belegung an. Lesen Sie `MapVersion` zusammen mit `FirmwareVersion`, um die Kompatibilität zu prüfen; ein Wechsel der Hauptversion von `MapVersion` kann Register verschieben.

> `MapVersion` (`2.1.0`) und `ModelType` (`EV_CHARGING_STATION`) sind feste Firmware-Konstanten und variieren nicht je Station. Eine Station, die noch `2.0.0` meldet, läuft mit einer älteren Firmware: Die Registerbelegung ist dieselbe, aber die im Umstiegshinweis am Anfang dieses Dokuments aufgeführten Verhaltensweisen weichen ab.

**Discovery** – Die optionalen Modbus-Funktionen Report Slave ID (`0x11`) und Read Device Identification (`0x2B/0x0E`) werden **noch nicht unterstützt**; beide liefern Exception `0x01`.

---

## Übersicht der Registerbelegung

Jede Zeile beschreibt ein Feld. Spalten: **Dok.-Register** (lesbare Schreibweise `3xxxx`/`4xxxx`), **PDU-Adr.** (nullbasierter Offset), **Name**, **Typ**, **Länge** (Anzahl der 16-Bit-Register), **Einheit**, **Zugriff** (`R` = nur lesen, `RW` = lesen/schreiben, `W` = nur schreiben – Lesezugriffe auf ein `W`-Register werden nicht abgelehnt; sie liefern den zuletzt gespeicherten Wert, der keine Bedeutung hat), **Persistenz** (`NV` = nichtflüchtig, `VOL` = flüchtig), **Hinweise**.

> Alle Offsets beziehen sich auf 16-Bit-Register; Mehrwortwerte belegen aufeinanderfolgende Register mit Big-Endian-Wort- und -Bytereihenfolge (höherwertiges Wort an der niedrigeren Adresse). Reservierte Einträge dürfen nicht angesprochen werden; einige sind unten aufgeführt, wo ihr Verhalten relevant ist.

### Registerblöcke im Überblick

| Block | Adressbereich | Funktionscode | Zugriff |
| --- | --- | --- | --- |
| EVCS-Identität  | `40001-40077`  | FC03  | R  |
| EVCS-Konfiguration  | `40101-40108`  | FC03 / FC06 / FC16  | R, mit RW-Sollwerten `40104-40107`  |
| Allgemeiner Zustand + Daemon-Gesundheit  | `30001-30059`  | FC04  | R  |
| EVSE (angebotene Grenzen)  | `30101-30115`  | FC04  | R  |
| Laden – CP / Stecker / Schütz  | `30201-30229`  | FC04  | R  |
| Phasenumschaltung  | `30301-30306`  | FC04  | R  |
| Tatsächlicher Konfigurationszustand  | `30601-30603`  | FC04  | R  |
| RFID  | `30401-30433`  | FC04  | R  |
| Netz / Batterie  | `30501-30527`  | FC04  | R  |
| Zähler-Identität  | `41001-41026`  | FC03  | R  |
| Zähler-Telemetrie  | `31001-31024`  | FC04  | R  |
| Steuerregister  | `40201-40225`  | FC03 / FC06 / FC16  | RW / W  |

### EVCS-Identität

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `40001`  | `0`  | MapVersion  | ASCII\[16\]  | 8  | --  | R  | NV  | Fest `2.1.0`; 2 Zeichen/Reg.; mit Nullen aufgefüllt  |
| `40009`  | `8`  | Model  | ASCII\[32\]  | 16  | --  | R  | NV  | z. B. `cPH22T22`  |
| `40025`  | `24`  | SerialNumber  | ASCII\[16\]  | 8  | --  | R  | NV  | z. B. `102178283`  |
| `40033`  | `32`  | Manufacturer  | ASCII\[32\]  | 16  | --  | R  | NV  | z. B. `eCharge Hardy Barth`  |
| `40049`  | `48`  | FirmwareVersionStr  | ASCII\[16\]  | 8  | --  | R  | NV  | z. B. `2.3.75`  |
| `40057`  | `56`  | FirmwareVersionU32  | u32  | 2  | --  | R  | NV  | z. B. `0x0203004B` für Firmware `2.3.75` (`2 -> 0x02`, `3 -> 0x03`, `75 -> 0x004B`; reines Binärformat, kein BCD); Wortreihenfolge High-Low  |
| `40065`  | `64`  | ModelType  | ASCII\[24\]  | 12  | --  | R  | NV  | Fest `EV_CHARGING_STATION`  |
| `40077`  | `76`  | _reserviert_  | u16  | 1  | --  | R  | NV  | Reserviertes Ende des Identitätsblocks; liest `0`  |

### EVCS-Konfiguration

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `40101`  | `100`  | FuseRating  | u16  | 1  | A  | R  | NV  | Absicherung  |
| `40102`  | `101`  | EcoPlusTimeout  | u16  | 1  | s  | R  | NV  | Konfiguriertes EcoPlus-Timeout  |
| `40103`  | `102`  | EcoReference  | u16  | 1  | --  | R  | NV  | Auslöseschwelle für PV-Überschuss  |
| `40104`  | `103`  | MinCurrent  | u16  | 1  | A  | RW  | NV  | Minimaler Ladestrom; gültig `6-32`. Folgt der Station: wird auch aktualisiert, wenn die Grenze außerhalb von Modbus geändert wird  |
| `40105`  | `104`  | MaxCurrent  | u16  | 1  | A  | RW  | NV  | Maximaler Ladestrom; gültig `6-32`. Folgt der Station: wird auch aktualisiert, wenn die Grenze außerhalb von Modbus geändert wird  |
| `40106`  | `105`  | EcoPlus  | u16  | 1  | bool  | RW  | NV  | `0 = aus`, `1 = ein`. Nur EMS-Sollwert; der tatsächliche Wert der Station steht in IR `30602`  |
| `40107`  | `106`  | ChargeMode  | u16  | 1  | enum  | RW  | NV  | Siehe **Aufzählungen -> Lademodus** (`0-2`). Nur EMS-Sollwert; der tatsächliche Wert der Station steht in IR `30601`  |
| `40108`  | `107`  | _reserviert_  | u16  | 1  | --  | R  | NV  | Nicht beschreibbar; ein FC06-/FC16-Schreibzugriff liefert Exception `0x02`  |

> Der reine Lese-Konfigurationsblock ist `40101-40103`; die beschreibbaren Sollwerte sind der zusammenhängende Block `40104-40107`. Ein FC06-/FC16-Schreibzugriff auf ein reines Lese-Konfigurationsregister (`40101-40103`) liefert Exception `0x03`.

**Sollwerte und tatsächliche Werte.** Die vier beschreibbaren Konfigurationsregister verhalten sich nicht alle gleich, weil eine Ladestation auch über ihr Web-Oberfläche, über die App oder per RFID-Karte verändert werden kann.

* `MinCurrent` (`40104`) und `MaxCurrent` (`40105`) sind Sollwert und Rücklesewert zugleich. Sie definieren das Ladestromfenster, das dieses Gerät akzeptiert (siehe **Steuerregister**), und geben daher immer das tatsächlich wirksame Fenster an. Wird das Fenster außerhalb von Modbus geändert, erscheinen die neuen Werte hier innerhalb eines Telemetriezyklus (**≤ 2 s**), und der akzeptierte Bereich wandert mit. Ein EMS-Schreibzugriff wird sofort wirksam und nie stillschweigend zurückgenommen.
* `EcoPlus` (`40106`) und `ChargeMode` (`40107`) sind reine EMS-Sollwerte. Das Gerät überschreibt sie nie, ein Rücklesen liefert also immer Ihren eigenen letzten Schreibzugriff. Um herauszufinden, was die Station _tatsächlich_ ausführt, lesen Sie den Block **Tatsächlicher Konfigurationszustand** (IR `30601-30603`). Der Vergleich der beiden ist der Weg, um zu erkennen, dass die Station einen Sollwert überstimmt oder ignoriert hat.

> **Ein neues Stromfenster schreiben.** `MinCurrent` darf `MaxCurrent` nicht überschreiten. Um das Fenster über das aktuelle Maximum hinaus nach oben zu verschieben (zum Beispiel von `6-16` auf `20-32`), schreiben Sie beide Register in einem **einzigen FC16-Telegramm**; das Telegramm wird als Ganzes geprüft und mit `0x03` abgelehnt, wenn es `MinCurrent > MaxCurrent` hinterlassen würde. Zwei getrennte FC06-Schreibzugriffe scheitern am ersten.

### EVCS-Zustand

#### Allgemeiner Zustand

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30001`  | `0`  | EVCS_State  | u16  | 1  | enum  | R  | VOL  | Siehe **Aufzählungen -> EVCS_State**  |
| `30002`  | `1`  | Connector_State  | u16  | 1  | enum  | R  | VOL  | Siehe **Aufzählungen -> Connector_State**  |
| `30003`  | `2`  | StatusWord  | u16  | 1  | bitfield  | R  | VOL  | Reserviert (alle Bits `0`); für die Daemon-Gesundheit DaemonStatus (`30050`) verwenden  |
| `30004`  | `3`  | ErrorCode  | u16  | 1  | enum  | R  | VOL  | `0 = OK`; siehe **Aufzählungen -> ErrorCode**  |
| `30005`  | `4`  | ChargingInfo  | ASCII\[32\]  | 16  | --  | R  | VOL  | Freitext (z. B. aktueller Modus, Stoppgrund)  |
| `30021`  | `20`  | AuthorizationStatus  | u16  | 1  | bool  | R  | VOL  | `0 = nein`, `1 = ja`  |
| `30022`  | `21`  | AuthType  | u16  | 1  | enum  | R  | NV  | Siehe **Aufzählungen -> Autorisierungstyp**  |
| `30023`  | `22`  | Uptime  | u32  | 2  | s  | R  | VOL  | Sekunden seit dem Start; Wortreihenfolge High-Low  |
| `30025`  | `24`  | Temperature  | u32  | 2  | celsius  | R  | VOL  | Ganzzahlige Grad C; Wortreihenfolge High-Low  |
| `30027`  | `26`  | Failsafe_Active  | u16  | 1  | bool  | R  | VOL  | `1`, solange der Failsafe wegen Kommunikations-Timeout aktiv ist; wird intern geschrieben (kein Funktionscode kann es setzen)  |
| `30050`  | `49`  | DaemonStatus  | u16  | 1  | bitfield  | R  | VOL  | Daemon-Gesundheit; siehe **Aufzählungen -> DaemonStatus**  |
| `30051..30059`  | `50..58`  | _reserviert_  | --  | --  | --  | --  | --  | Reserviert für künftige Erweiterung der Daemon-Gesundheit; Lesezugriffe liefern `0`  |

#### EVSE (angebotene Grenzen)

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30101`  | `100`  | Availability  | u16  | 1  | bool  | R  | VOL  | `1`, wenn die Station „operative“ meldet, sonst `0`  |
| `30102`  | `101`  | GridCurrentLimit  | u16  | 1  | A  | R  | VOL  | Netzseitig auferlegte Grenze  |
| `30103`  | `102`  | PhaseCount  | u16  | 1  | count  | R  | VOL  | `1` oder `3`  |
| `30104`  | `103`  | PhysicalCurrentLimit  | u16  | 1  | A  | R  | VOL  | Hardware-Grenze  |
| `30105`  | `104`  | OfferedCurrentLimit  | u16  | 1  | A  | R  | VOL  | Angebotene Grenze  |
| `30106`  | `105`  | CurrentOfferedTotal  | f32  | 2  | A  | R  | VOL  | Wortreihenfolge High-Low  |
| `30108`  | `107`  | CurrentOfferedL1  | f32  | 2  | A  | R  | VOL  | --  |
| `30110`  | `109`  | CurrentOfferedL2  | f32  | 2  | A  | R  | VOL  | --  |
| `30112`  | `111`  | CurrentOfferedL3  | f32  | 2  | A  | R  | VOL  | --  |
| `30114`  | `113`  | PowerOffered  | f32  | 2  | W  | R  | VOL  | --  |

#### Laden – CP / Stecker / Schütz

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30201`  | `200`  | EV_Present  | u16  | 1  | bool  | R  | VOL  | --  |
| `30202`  | `201`  | Charging  | u16  | 1  | bool  | R  | VOL  | --  |
| `30203`  | `202`  | CP_Status  | u16  | 1  | enum  | R  | VOL  | A-F; siehe **Aufzählungen -> CP_Status**  |
| `30204`  | `203`  | CP_PWM_State  | u16  | 1  | bool  | R  | VOL  | `0 = aus`, `1 = ein`  |
| `30205`  | `204`  | CP_Duty_Cycle  | f32  | 2  | %  | R  | VOL  | Wortreihenfolge High-Low  |
| `30220`  | `219`  | Plug_Lock_Status  | u16  | 1  | enum  | R  | VOL  | `0 = entriegelt`, `1 = verriegelt`, `2 = unbekannt`  |
| `30221`  | `220`  | Plug_State_Actual  | u16  | 1  | enum  | R  | VOL  | `0 = entriegeln`, `1 = verriegeln`  |
| `30222`  | `221`  | Plug_State_Target  | u16  | 1  | enum  | R  | VOL  | `0 = entriegeln`, `1 = verriegeln`  |
| `30223`  | `222`  | Plug_Error  | u16  | 1  | enum  | R  | VOL  | Firmware-spezifischer Fehlercode der Steckerverriegelung; `0` = kein Fehler, ungleich null = Fehler (nicht die ErrorCode-Aufzählung aus Tabelle B)  |
| `30224`  | `223`  | Contactor_Status  | u16  | 1  | enum  | R  | VOL  | `0 = geöffnet`, `1 = geschlossen`, `2 = unbekannt`  |
| `30225`  | `224`  | Contactor_State_Actual  | u16  | 1  | enum  | R  | VOL  | `0 = öffnen`, `1 = schließen`  |
| `30226`  | `225`  | Contactor_State_Target  | u16  | 1  | enum  | R  | VOL  | `0 = öffnen`, `1 = schließen`  |
| `30227`  | `226`  | Contactor_Error  | u16  | 1  | enum  | R  | VOL  | Firmware-spezifischer Schütz-Fehlercode; `0` = kein Fehler, ungleich null = Fehler (nicht die ErrorCode-Aufzählung aus Tabelle B)  |
| `30228`  | `227`  | PWM_Status  | f32  | 2  | %  | R  | VOL  | Spiegel von CP_Duty_Cycle  |

#### Phasenumschaltung

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30301`  | `300`  | PhaseSwitchingEnabled  | u16  | 1  | bool  | R  | NV  | `0/1`  |
| `30302`  | `301`  | PhaseSwitchingStatus  | u16  | 1  | enum  | R  | VOL  | Siehe **Aufzählungen -> Phasenumschaltungsstatus**  |
| `30303`  | `302`  | ActualPhase  | u16  | 1  | count  | R  | VOL  | `0`, `1` oder `3`; die tatsächlich auf das Schütz geschaltete Phasenzahl. `0` = keine Phase verbunden (keine Sitzung aktiv) und der normale Lesewert an einer Station im Leerlauf  |
| `30304`  | `303`  | TargetPhase  | u16  | 1  | count  | R  | VOL  | `0`, `1` oder `3`; die zuletzt an die Leistungsstufe kommandierte Phasenzahl. `0` = noch nicht gemeldet  |
| `30305`  | `304`  | PhaseSwitchDelay  | u16  | 1  | s  | R  | NV  | Nicht für Zeitberechnungen verwenden – siehe Hinweis unter **Phasenwahl**  |
| `30306`  | `305`  | PhaseSwitchDuration  | u16  | 1  | s  | R  | NV  | Nicht für Zeitberechnungen verwenden – siehe Hinweis unter **Phasenwahl**  |

#### Tatsächlicher Konfigurationszustand

Reine Lesespiegel von Einstellungen, die der **Station** gehören – egal, wer sie geändert hat: das Web-Oberfläche, die App, eine RFID-Karte oder ein EMS-Schreibzugriff. Verwenden Sie sie, um zu bestätigen, was die Ladestation wirklich tut, im Gegensatz zu dem, was zuletzt über `40106`/`40107` angefordert wurde.

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30601`  | `600`  | ChargeMode_Actual  | u16  | 1  | enum  | R  | VOL  | Der Modus, in dem die Station läuft; siehe **Aufzählungen -> Lademodus**. Mit dem Sollwert in HR `40107` vergleichen  |
| `30602`  | `601`  | EcoPlus_Actual  | u16  | 1  | bool  | R  | VOL  | `0 = aus`, `1 = ein`. Mit dem Sollwert in HR `40106` vergleichen  |
| `30603`  | `602`  | PauseCharging_Actual  | u16  | 1  | bool  | R  | VOL  | `1`, wenn das Laden über das Web-Oberfläche oder die App pausiert ist. Es gibt kein Modbus-Register, das dies setzt  |

> `PauseCharging_Actual` hat kein Sollwert-Gegenstück: Die Pause ist eine lokale Benutzeraktion, kein EMS-Befehl. `Start_Stop_Charging` (`40203`) bleibt die eigene Start-/Stopp-Steuerung des EMS und wird davon nicht beeinflusst. Wenn eine Sitzung nicht startet und alle Ihre Sollwerte korrekt aussehen, prüfen Sie dieses Register – eine lokale Pause überstimmt einen EMS-Start.

> Die Adressen `30604-30610` sind reserviert und dürfen nicht angesprochen werden.

#### RFID

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30401`  | `400`  | RFID_Available  | u16  | 1  | bool  | R  | VOL  | --  |
| `30418`  | `417`  | RFID_LastTag  | ASCII\[32\]  | 16  | --  | R  | VOL  | Zuletzt gesehener Tag (leer, falls nicht vorhanden)  |

### Netz

Der Netz-/Batterie-Block führt Netz- und Speicherdaten aus der Station. Die Felder lesen `0`, bis die Station sie veröffentlicht (Batteriefelder bleiben bei Ladestationen ohne Speicher `0`).

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `30501`  | `500`  | MainsType  | u16  | 1  | enum  | R  | NV  | Typ des angeschlossenen Wechselrichters  |
| `30502`  | `501`  | MainsAvailable  | u16  | 1  | bool  | R  | VOL  | --  |
| `30503`  | `502`  | MainsPower_Total  | f32  | 2  | W  | R  | VOL  | --  |
| `30505`  | `504`  | MainsCurrent_Total  | f32  | 2  | A  | R  | VOL  | --  |
| `30507`  | `506`  | MainsCurrent_L1  | f32  | 2  | A  | R  | VOL  | --  |
| `30509`  | `508`  | MainsCurrent_L2  | f32  | 2  | A  | R  | VOL  | --  |
| `30511`  | `510`  | MainsCurrent_L3  | f32  | 2  | A  | R  | VOL  | --  |
| `30513`  | `512`  | MainsPower_L1  | f32  | 2  | W  | R  | VOL  | --  |
| `30515`  | `514`  | MainsPower_L2  | f32  | 2  | W  | R  | VOL  | --  |
| `30517`  | `516`  | MainsPower_L3  | f32  | 2  | W  | R  | VOL  | --  |
| `30519`  | `518`  | BatteryAvailable  | u16  | 1  | bool  | R  | VOL  | --  |
| `30520`  | `519`  | BatterySOC  | f32  | 2  | %  | R  | VOL  | --  |
| `30522`  | `521`  | BatteryPower  | f32  | 2  | W  | R  | VOL  | `+` Entladen / `-` Laden  |
| `30524`  | `523`  | BatterySOC_Start  | f32  | 2  | %  | R  | NV  | --  |
| `30526`  | `525`  | BatterySOC_Stop  | f32  | 2  | %  | R  | NV  | --  |

### Zähler-Identität

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `41001`  | `1000`  | MeterType  | ASCII\[16\]  | 8  | --  | R  | NV  | --  |
| `41009`  | `1008`  | MeterName  | ASCII\[16\]  | 8  | --  | R  | NV  | --  |
| `41017`  | `1016`  | MeterSerial  | ASCII\[16\]  | 8  | --  | R  | NV  | --  |
| `41025`  | `1024`  | MeterPhaseCount  | u16  | 1  | count  | R  | NV  | `1` oder `3`  |
| `41026`  | `1025`  | MeterAvailable  | u16  | 1  | bool  | R  | VOL  | --  |

### Zähler-Telemetrie

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `31001`  | `1000`  | MeterFrequency  | f32  | 2  | Hz  | R  | VOL  | Wortreihenfolge High-Low  |
| `31003`  | `1002`  | Voltage_L1  | f32  | 2  | V  | R  | VOL  | --  |
| `31005`  | `1004`  | Voltage_L2  | f32  | 2  | V  | R  | VOL  | --  |
| `31007`  | `1006`  | Voltage_L3  | f32  | 2  | V  | R  | VOL  | --  |
| `31009`  | `1008`  | Current_L1  | f32  | 2  | A  | R  | VOL  | --  |
| `31011`  | `1010`  | Current_L2  | f32  | 2  | A  | R  | VOL  | --  |
| `31013`  | `1012`  | Current_L3  | f32  | 2  | A  | R  | VOL  | --  |
| `31015`  | `1014`  | Power_Total  | f32  | 2  | W  | R  | VOL  | --  |
| `31017`  | `1016`  | Power_L1  | f32  | 2  | W  | R  | VOL  | --  |
| `31019`  | `1018`  | Power_L2  | f32  | 2  | W  | R  | VOL  | --  |
| `31021`  | `1020`  | Power_L3  | f32  | 2  | W  | R  | VOL  | --  |
| `31023`  | `1022`  | Energy_Total  | f32  | 2  | kWh  | R  | NV  | --  |

### Steuerregister

| Dok.-Register | PDU-Adr. | Name | Typ | Länge | Einheit | Zugriff | Persistenz | Hinweise |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `40201`  | `200`  | Set_Charge_Power_Target  | u16  | 1  | W  | RW  | VOL  | Nicht implementiert; Schreibzugriffe werden angenommen und gespeichert, bleiben aber wirkungslos  |
| `40202`  | `201`  | Set_Charge_Current_Target  | u16  | 1  | A  | RW  | VOL  | Gültig `0` oder innerhalb des Stationsfensters `MinCurrent`-`MaxCurrent` (HR `40104`/`40105`); `0` stoppt die Ladung  |
| `40203`  | `202`  | Start_Stop_Charging  | u16  | 1  | bool  | RW  | VOL  | `1 = Start`, `0 = Stopp`  |
| `40204`  | `203`  | Failsafe_Timeout  | u16  | 1  | s  | RW  | NV  | Gültig `0` oder `10-3600`; Standard `20`; `0` deaktiviert den Failsafe  |
| `40205`  | `204`  | Failsafe_Power_Target  | u16  | 1  | W  | RW  | VOL  | Nicht implementiert; Schreibzugriffe werden angenommen und gespeichert, bleiben aber wirkungslos  |
| `40206`  | `205`  | Failsafe_Current_Target  | u16  | 1  | A  | RW  | NV  | Gültig `0` oder innerhalb des Stationsfensters `MinCurrent`-`MaxCurrent` (HR `40104`/`40105`); Standard `0`  |
| `40207`  | `206`  | Reserved_Control_206  | u16  | 1  | --  | RW  | VOL  | Reserviertes beschreibbares No-op; der Failsafe_Active-Status ist nach IR `30027` umgezogen  |
| `40208`  | `207`  | Heartbeat  | u16  | 1  | --  | W  | VOL  | Periodisch einen beliebigen Wert schreiben, damit der Failsafe nicht auslöst  |
| `40209`  | `208`  | Target_Phase  | u16  | 1  | count  | RW  | VOL  | Gültig `1` oder `3`; erfordert aktivierte Phasenumschaltung in der Gerätekonfiguration  |
| `40210`  | `209`  | RFID_AuthorizeReq  | ASCII\[32\]  | 16  | --  | RW  | VOL  | Nicht implementiert; Schreibzugriffe auf `40210-40225` werden angenommen und gespeichert, bleiben aber wirkungslos  |

> **Angenommene, aber wirkungslose Register.** `Set_Charge_Power_Target` (`40201`), `Failsafe_Power_Target` (`40205`), `Reserved_Control_206` (`40207`) und `RFID_AuthorizeReq` (`40210-40225`) nehmen Schreibzugriffe an (sodass ein FC16-Telegramm den gesamten Steuerblock überspannen kann), haben aber noch keinen Seiteneffekt. Verlassen Sie sich nicht darauf, dass ihre gespeicherten Werte das Laden beeinflussen.

> **Die Stromgrenzen kommen von der Station, nicht aus diesem Dokument.** `Set_Charge_Current_Target` und `Failsafe_Current_Target` werden gegen das Fenster in `MinCurrent`/`MaxCurrent` (HR `40104`/`40105`) validiert, wie es im Moment des Schreibzugriffs gilt. Auf einer für `6-16 A` konfigurierten Station wird ein Schreibzugriff mit `20` mit `0x03` abgelehnt, obwohl `20` innerhalb des von der Hardware unterstützten Bereichs `6-32 A` liegt. Lesen Sie `40104`/`40105` beim Start und erneut, wann immer ein Strom-Schreibzugriff unerwartet abgelehnt wird, statt von einem festen Bereich auszugehen. Die absolute Grenze `6-32 A` gilt nur für Schreibzugriffe auf `40104`/`40105` selbst.

---

## Aufzählungen und Fehlercodes

### Tabelle A – EVCS-Stationszustände

| Code | Zustand | Beschreibung |
| --- | --- | --- |
| 0  | NOT_READY  | Nicht ladebereit (Laden deaktiviert oder Autorisierung erforderlich).  |
| 1  | READY  | Ladebereit; Kabel kann angeschlossen sein oder nicht.  |
| 2  | CHARGING  | Aktiver Ladevorgang läuft, egal wer die Sitzung gestartet hat.  |
| 3  | CHARGING_INTERRUPTED  | Laden aufgrund einer EMS-Anforderung oder eines Fehlers unterbrochen.  |
| 4  | ERROR  | Ein Fehler ist aktiv (`ErrorCode != 0`).  |
| 5  | AUTH_REJECTED  | Reserviert; wird derzeit nicht von der Firmware ausgegeben.  |
| 6  | RESERVED  | Reserviert für künftige Verwendung.  |
| 7  | PHASE_SWITCHING  | Umschaltung zwischen 1-phasigem und 3-phasigem Betrieb.  |

> Die Firmware gibt die Codes `0-4` und `7` aus. Die Codes `5` und `6` sind reserviert und werden derzeit nicht erzeugt – bauen Sie keine Logik, die auf sie wartet.

> **CHARGING hängt nicht vom EMS-Startbefehl ab.** `EVCS_State = 2` bedeutet, dass die Station tatsächlich fließende Energie meldet, unabhängig davon, wie die Sitzung begann – per EMS-Start, Web-Oberfläche oder RFID-Karte. Zwei Folgen für eine bestehende Integration: Eine Sitzung, die Sie nicht gestartet haben, erscheint jetzt als CHARGING statt NOT_READY, und nachdem Sie `Start_Stop_Charging = 0` geschrieben haben, verlässt der Zustand CHARGING erst, wenn die Station tatsächlich gestoppt hat (innerhalb eines Telemetriezyklus, **≤ 2 s**), nicht im Moment der Annahme Ihres Schreibzugriffs. Um zu bestätigen, dass der Befehl selbst angenommen wurde, lesen Sie `Start_Stop_Charging` (`40203`) zurück. CHARGING_INTERRUPTED und READY berücksichtigen den Befehl weiterhin und sind unverändert. Siehe **Wie die Zustandssignale abgeleitet werden**.

### Tabelle B – Fehlercodes

| Code | Bedeutung |
| --- | --- |
| 0  | Kein Fehler.  |
| 1  | Interner Hardwarefehler (Selbsttest fehlgeschlagen).  |
| 2  | Überstrom oder Kurzschluss erkannt.  |
| 3  | Überspannung oder Unterspannung erkannt.  |
| 4  | Übertemperatur erkannt (Elektronik; siehe Hinweis unten).  |
| 5  | Kommunikationsfehler mit Zähler oder RFID-Leser.  |
| 6  | Verriegelungs-/Steckerfehler.  |
| 7  | Failsafe aktiv.  |
| 8-65535  | Reserviert.  |

> **Priorität.** Sind mehrere Bedingungen gleichzeitig aktiv, meldet das Gerät die mit der höchsten Priorität in dieser Reihenfolge: `7` Failsafe aktiv > `1` Interner Hardwarefehler > `2` Überstrom > `3` Spannungsanomalie > `4` Übertemperatur > `5` Kommunikationsfehler > `6` Verriegelungs-/Steckerfehler. (Die Priorität ist die Auswertungsreihenfolge, nicht der numerische Codewert.)

**Erkennungsbedingungen**

| Code | Wird gesetzt, wenn |
| --- | --- |
| 1  | Ein Schützfehler gemeldet wird, eine Notabschaltung signalisiert wird oder ein erwarteter Rückmeldekanal der Fehlerstromschutzeinrichtung nicht verfügbar wird.  |
| 2  | Die Fehlerstromschutzeinrichtung ausgelöst hat, ein Fehlerstromfehler gemeldet wird oder ein Phasenstrom **32 A** überschreitet.  |
| 3  | Eine Phasenspannung unter **195 V** oder über **253 V** liegt (nominal 230 V, `-15 %` / `+10 %`). Wird erst ausgewertet, sobald eine Spannung ungleich null gelesen wurde.  |
| 4  | Die Elektroniktemperatur die Übertemperaturschwelle erreicht; siehe Hinweis unten.  |
| 5  | Der Energiezähler nicht verfügbar ist, obwohl einer erwartet wird, oder der RFID-Leser nicht verfügbar ist, obwohl einer erwartet wird.  |
| 6  | Ein Fehler der Steckerverriegelung gemeldet wird oder ein Proximity-Fehler erkannt wird (kein Kabel, ungültiger Widerstand).  |

**Zur Übertemperatur (Code** `4`)

* **Sie löscht sich von selbst.** Der Code wird aus der **aktuellen** Elektroniktemperatur gesetzt und gelöscht, sobald der Messwert **5 K** unter die Schwelle zurückgefallen ist, damit eine Station genau auf der Grenze nicht flackert. Die Erholung braucht keinen Neustart, Reboot oder Stromzyklus: Sobald die Station abkühlt, geht der Code innerhalb eines Telemetriezyklus auf `0` zurück. Ältere Firmware bewertete dies gegen einen Spitzenwert seit dem Start, der nie sank, sodass der Code gesetzt blieb, bis die Station neu gestartet wurde – wenn Ihre Integration das umgeht, ist dieser Workaround nicht mehr nötig.
* **Die Schwelle variiert je Station und ist nicht konfigurierbar.** Jede Station liest beim Start den Drosselungs-Auslösepunkt ihres eigenen Controllers und verwendet diesen, der genaue Wert hängt also von der Temperaturklasse des verbauten Bauteils ab – üblicherweise **95 °C** bei Industrie-Hardware und **85 °C** bei Commercial-Grade-Hardware, mit **90 °C** als Rückfallwert, falls der Auslösepunkt nicht gelesen werden kann. Codieren Sie keine feste Schwelle; behandeln Sie den Code selbst als Signal.
* **Was gemessen wird.** Code `4` spiegelt die Temperatur der Steuerelektronik der Ladestation wider – derselbe Messwert, der unter `Temperature` (`30025`) bereitgestellt wird. Es ist keine Messung von Steckverbinder, Schütz, Kabel oder Gehäuse; nichts in dieser Schnittstelle meldet diese.
* **Was die Ladestation dagegen tut: nichts.** Die Station drosselt, reduziert oder stoppt das Laden bei Code `4` nicht. Er ist informativ, und jede Reaktion ist Entscheidung des EMS.

> Ein `ErrorCode` ungleich null treibt außerdem `EVCS_State` (`30001`) auf `4 = ERROR`. Ein EMS, das Übertemperatur als informativ behandelt, sollte dennoch damit rechnen, dass der Stationszustand ihr folgt.

### Tabelle C – Control-Pilot-(CP-)Statuscodes

Das CP-Signal (IEC 61851) zeigt den Verbindungszustand des Fahrzeugs über die Buchstaben A-F an, codiert als `u16`.

| Code | IEC-61851-Zustand | Bedeutung |
| --- | --- | --- |
| 0  | A  | Standby; kein Fahrzeug vorhanden.  |
| 1  | B  | Fahrzeug verbunden; EV fordert kein Laden an.  |
| 2  | C  | Fahrzeug verbunden und fordert Laden an.  |
| 3  | D  | Laden erlaubt, Belüftung erforderlich.  |
| 4  | E  | Fehler (EV/EVSE).  |
| 5  | F  | EVSE-Fehler.  |
| 6-65535  | --  | Reserviert / unbekannt.  |

### Tabelle D – Steckverbinderzustand (Connector State)

| Code | Bezeichnung | Bedeutung |
| --- | --- | --- |
| 0  | UNPLUGGED  | Kein Stecker in Fahrzeug oder Station.  |
| 1  | PLUGGED_ON_STATION_ONLY  | Stecker an der Station eingerastet, nicht im Fahrzeug.  |
| 2  | PLUGGED_ON_STATION_AND_VEHICLE  | Stecker beidseitig gesteckt; bereit zum Verriegeln/Laden.  |
| 3  | ERROR_UNAVAILABLE  | Hardwarefehler oder Steckverbinder nicht verfügbar.  |

### Tabelle E – Lademodus

| Code | Bezeichnung | Bedeutung |
| --- | --- | --- |
| 0  | ECO  | Optimierung auf PV-Überschuss; die Ladestation leitet den Ladestrom dynamisch ab.  |
| 1  | POWER  | Laden mit maximal möglicher Leistung.  |
| 2  | MANUAL  | Fester Strom, gesetzt durch Benutzer/EMS (A).  |

### Tabelle F – Autorisierungstyp

| Code | Bezeichnung | Bedeutung |
| --- | --- | --- |
| 0  | FREE  | Keine Authentifizierung erforderlich.  |
| 1  | RFID  | Lokale/Online-RFID-Autorisierung.  |
| 2  | KEYSWITCH  | Physischer Schlüsselschalter erforderlich.  |
| 3  | OCPP  | Backend-Autorisierung über OCPP.  |

### Tabelle G – Phasenumschaltungsstatus

| Code | Bezeichnung | Bedeutung |
| --- | --- | --- |
| 0  | IDLE  | Keine Umschaltung im Gange. Auch der Wert, der gelesen wird, bevor die Station diesen Block zum ersten Mal gemeldet hat – siehe **Phasenwahl**.  |
| 1  | IN_PROGRESS  | Phasenumschaltung läuft.  |

### Tabelle H – StatusWord-Bitfeld

| Bit | Bezeichnung | Bedeutung |
| --- | --- | --- |
| 0-15  | RESERVED  | Reserviert für künftige Verwendung; derzeit alle `0`.  |

> StatusWord (`30003`) ist noch nicht belegt. Für die Daemon-Gesundheit **DaemonStatus** (Tabelle I) verwenden.

### Tabelle I – DaemonStatus-Bitfeld (IR 30050)

`DaemonStatus` stellt den eigenen Start- und Verbindungszustand des Daemons bereit, getrennt vom elektrischen/Ladezustand der Ladestation. Verwenden Sie ihn, um „die Ladestation ist offline“ von „das Gateway startet noch“ zu unterscheiden.

| Bit | Bezeichnung | Bedeutung (wenn auf 1 gesetzt) |
| --- | --- | --- |
| 0  | units_ready  | Die Startsperre ist aufgehoben; das Gateway ist bereit, Anfragen zu bedienen.  |
| 1  | mqtt_connected  | Die interne Datensitzung zur Ladestation ist aufgebaut.  |
| 2  | api_seed_succeeded  | Seit dem Daemon-Start wurde mindestens ein Konfigurations-Seed fehlerfrei abgeschlossen (das Bit wird durch ein später fehlgeschlagenes Re-Seed nicht gelöscht).  |
| 3  | persistence_degraded  | Eine Failsafe-Einstellung ist live wirksam, aber noch nicht auf dem Datenträger gespeichert (ein Reboot würde sie zurücksetzen).  |
| 4  | degraded_mode  | Das Gateway hat seine Anfragesperre aufgehoben, bevor alle Einheiten den Start abgeschlossen hatten.  |
| 5-15  | RESERVED  | Für künftige Verwendung; immer `0`.  |

---

## Steuerung der Ladestation

Das Laden wird durch genau zwei Register gesteuert: `Set_Charge_Current_Target` (`40202`) und `Start_Stop_Charging` (`40203`). `Set_Charge_Power_Target` (`40201`) wird angenommen, bewirkt aber nichts.

### Eine Sitzung starten

1. Schreiben Sie einen Stromsollwert innerhalb des Stationsfensters (`MinCurrent`-`MaxCurrent`, HR `40104`/`40105`) nach `40202`.
2. Schreiben Sie `1` nach `40203`.

Ein Startbefehl wird **abgelehnt, solange der Stromsollwert** `0` **ist**: `40203 = 1` mit `40202 = 0` liefert Exception `0x03`, und nichts wird übernommen. Beide Register in einem einzigen FC16-Telegramm zu schreiben ist das sichere Muster; diese Kombination wird geprüft, bevor irgendetwas committet wird, sodass das Telegramm als Ganzes abgelehnt wird, statt halb übernommen zu werden.

> Firmware älter als diese Basis meldete diese Ablehnung als `0x04` (Slave Device Failure). Wenn Ihr Client die beiden unterscheidet, behandeln Sie beide als „zuerst einen gültigen Stromsollwert setzen“.

### Die Start/Stopp-Verriegelung des Stromsollwerts

**Solange** `Start_Stop_Charging` auf `0` steht, werden der Ladestation `0 A` angeboten, egal was Sie nach `40202` schreiben. Der Schreibzugriff wird angenommen und das Register liest den gesendeten Wert zurück, aber der Station wird `0` mitgeteilt. Das ist Absicht: Den angebotenen Strom im gestoppten Zustand anzuheben, könnte eine Ladung beginnen, die niemand kommandiert hat.

Die praktische Folge ist, dass ein vor dem Startbefehl geschriebener Stromsollwert nicht von selbst wirksam wird – er wird übernommen, wenn `40203` auf `1` geht. Wenn Sie einen Stromsollwert schreiben und die Ladestation bei `0 A` bleibt, lesen Sie zuerst `40203`.

### Strom während einer Sitzung ändern

Steht `40203` bereits auf `1`, schreiben Sie den neuen Wert nach `40202`; er wird dem Fahrzeug sofort angeboten. Werte außerhalb des Stationsfensters werden mit `0x03` abgelehnt, und das Register behält seinen vorherigen Wert.

### Beenden

Schreiben Sie `0` nach `40203`. Der Ladestation werden `0 A` angeboten, und die Sitzung wird deautorisiert. `EVCS_State` verlässt CHARGING, sobald die Station tatsächlich gestoppt hat, innerhalb eines Telemetriezyklus (**≤ 2 s**) – nicht im Moment der Annahme des Schreibzugriffs.

### Der Lademodus ist entscheidend

Ein EMS-Stromsollwert hält nur, solange die Station im Modus **MANUAL** ist (`ChargeMode = 2`). In den Modi ECO und POWER berechnet die Station den Ladestrom selbst – aus dem PV-Überschuss in ECO oder mit dem Maximum in POWER – und überschreibt einen über Modbus geschriebenen Wert. Bevor Sie sich auf `40202` verlassen, lesen Sie den tatsächlichen Modus der Station unter `ChargeMode_Actual` (`30601`); ist er nicht `2`, schreiben Sie `2` nach `ChargeMode` (`40107`) und bestätigen Sie, dass die Änderung unter `30601` erscheint.

> Ein Wechsel des Lademodus – auch der Wechsel _in_ den manuellen Modus – setzt die Ladebegrenzung der Station zurück. Schreiben Sie Ihren Stromsollwert nach jedem Moduswechsel erneut.

### Phasenwahl

Die Funktion selbst — was eine Umschaltung mit einer laufenden Sitzung macht, ihr Zeitverhalten und wie sich prüfen lässt, ob sie gewirkt hat — ist unter [Phasenumschaltung](/de/features/phase-switching) beschrieben. Dieser Abschnitt behandelt die Modbus-Seite.

`Target_Phase` (`40209`) akzeptiert `1` oder `3`, und nur, wenn die Phasenumschaltung auf der Station aktiviert ist; andernfalls wird der Schreibzugriff mit `0x03` abgelehnt.

**Eine Phasenumschaltung wird nur während einer aktiven Ladesitzung ausgeführt.** Die Station fährt die Relaissequenz, solange der Control Pilot im Zustand C oder D ist – ein Fahrzeug ist angesteckt und zieht Strom. An einer Station im Leerlauf wird die Anforderung intern vermerkt, und nichts bewegt sich: `PhaseSwitchingStatus` (`30302`) bleibt `0` und `ActualPhase` (`30303`) bleibt `0`. Wählen Sie keine Phase vor einer Sitzung vor in der Annahme, die Sitzung starte damit; führen Sie die Umschaltung durch, während die Sitzung läuft.

Zwei weitere Fälle machen einen angenommenen Schreibzugriff wirkungslos, beide ohne Fehler:

* **Die angeforderte Phase entspricht der gespeicherten Auswahl der Station.** Der gespeicherte Wert ist standardmäßig 3-phasig und übersteht Reboots, sodass `40209 = 3` auf einer frischen Station in der Regel gar nichts bewirkt.
* **Eine Umschaltung läuft bereits**, d. h. `30302` ist nicht `0`.

Ein angenommener Schreibzugriff bestätigt, dass der Befehl die Station erreicht hat, nicht, dass er ausgeführt wurde – die obigen Bedingungen werden danach ausgewertet und erzeugen keinen Fehler auf Modbus-Seite.

**Zeitverhalten.** Nach dem Ladestart blockiert die Station die Umschaltung für rund 30 Sekunden und erzwingt danach ein Mindestintervall zwischen aufeinanderfolgenden Umschaltungen. Die Relaissequenz selbst braucht mehrere Sekunden, und die Station wartet bis zu 60 s auf die Bestätigung der Leistungsstufe. `PhaseSwitchDelay` (`30305`) und `PhaseSwitchDuration` (`30306`) melden diese beiden Werte derzeit nicht zuverlässig – der im Web-Oberfläche konfigurierte Wert landet auf `30306`, während `30305` einen festen internen Standardwert meldet. Leiten Sie daraus keine Zeiten ab.

**Überwachung.** Fragen Sie `PhaseSwitchingStatus` (`30302`) und `ActualPhase` (`30303`) ab: `30302` geht auf `1`, solange die Umschaltung läuft, und zurück auf `0`, wenn sie abgeschlossen ist, und `30303` zeigt dann die neue Phasenzahl. `EVCS_State` kann während der Umschaltung `7 = PHASE_SWITCHING` melden, das hängt aber von internen Bedingungen ab, die nicht immer erfüllt sind – verwenden Sie es nicht als Fortschrittsanzeige.

**Die Phase außerhalb einer Sitzung lesen.** Kein Modbus-Register meldet die *gespeicherte* Phasenwahl der Station; `30303` und `30304` sind nur während einer laufenden Sitzung aussagekräftig, und `0` in diesem Block bedeutet sowohl „Leerlauf / keine Phase“ als auch „noch nicht gemeldet“. Lesen Sie die gespeicherte Auswahl stattdessen über REST: `GET /api/?path=secc/port0/salia/phase_switching/actual`.

**`PhaseSwitchingEnabled` (`30301`) ist keine Live-Bestätigung.** Es meldet, was der Modbus-Daemon beim Start aus der Stationskonfiguration gelesen hat. Die Ladefirmware der Station liest dieselbe Einstellung unabhängig davon, ebenfalls bei ihrem eigenen Start. Wird die Phasenumschaltung im Web-Oberfläche aktiviert, ohne die gesamte Station neu zu starten, kann `30301` `1` lesen, während die Ladefirmware weiterhin jede Umschaltanforderung verwirft. Das Erkennungsmerkmal sind `30302`, `30303` und `30304`, die alle auf `0` stehen; ein vollständiger Neustart der Station synchronisiert beide wieder. Liefert `GET /api/?path=secc/port0/salia/phase_switching/status` `"idle"` oder `"progress"`, ist die Seite der Ladefirmware bestätigt aktiv.

---

## Funktionsbeispiele

### Identitätsdaten lesen (in einem Zug)

**Ziel**: `MapVersion`, `Model`, `SerialNumber`, `Manufacturer`, `FirmwareVersionStr`, `FirmwareVersionU32` in einer Anfrage lesen.

**Wo**: HR `40001 ... 40058` – das sind **58 Register** ab PDU-Offset `0`.

**Funktion**: `0x03` (Read Holding Registers).

**Anfrage-PDU** (Start bei 0, Anzahl 58 = `0x003A`):

```
03 00 00 00 3A
```

**Antwort**: Byte-Anzahl + **116 Bytes** (58 Reg. x 2 Bytes). Für Zeichenketten 2 ASCII-Zeichen je Register dekodieren und abschließende `0x00` abschneiden. Die letzten beiden Register sind die `u32`-Firmware-Nummer (Wortreihenfolge HighWord-LowWord, Big-Endian-Bytes innerhalb jedes Registers).

### Zählerwerte lesen (Wirkleistung je Phase)

**Ziel**: Wirkleistung gesamt + L1/L2/L3 lesen (vier `f32`).

**Wo**: IR `31015 / 31017 / 31019 / 31021` -> PDU-Offsets `1014 / 1016 / 1018 / 1020`.

**Funktion**: `0x04` (Read Input Registers).

**Anfrage-PDU** (8 Reg. ab 1014 lesen):

```
04 03 F6 00 08
```

**Antwort**: Byte-Anzahl + **16 Bytes** = 4 x `f32` in der Reihenfolge `Power_Total`, `Power_L1`, `Power_L2`, `Power_L3` (jeder belegt zwei Reg., HighWord an der niedrigeren Adresse).

### Stromsollwert setzen (z. B. 16 A)

**Ziel**: `Set_Charge_Current_Target` (HR `40202`, PDU-Offset `201`) mit **16 A** schreiben.

> Dieses Register ist ein `u16`, kein Float. Gültige Werte sind `0` (Stopp) oder ein beliebiger Strom innerhalb des Stationsfensters (`MinCurrent`-`MaxCurrent`, HR `40104`/`40105`). Schreiben Sie den ganzzahligen Ampere-Wert direkt.

**Funktion**: `0x06` (Write Single Register).

**Anfrage-PDU** (`address = 0x00C9` = 201, `value = 0x0010` = 16):

```
06 00 C9 00 10
```

**Antwort**: Echo von Adresse und Wert (`00 C9 00 10`). Werte außerhalb von `0` oder dem Stationsfenster werden mit Exception `0x03` abgelehnt, und das Register bleibt unverändert. Denken Sie daran, dass der Wert der Ladestation erst angeboten wird, sobald `Start_Stop_Charging` (`40203`) auf `1` steht – siehe **Steuerung der Ladestation**.

### Strom setzen und Ladung atomar starten (FC16)

**Ziel**: den Stromsollwert auf 16 A setzen und das Laden in einem atomaren Telegramm starten, um den Fehler „Start mit Stromsollwert = 0“ zu vermeiden.

**Wo**: HR `40202-40203` -> PDU-Offsets `201-202` (`Set_Charge_Current_Target`, `Start_Stop_Charging`).

**Funktion**: `0x10` (Write Multiple Registers).

**Anfrage-PDU** (`start = 0x00C9` = 201, `quantity = 2`, `byte count = 4`, Werte `16`, `1`):

```
10 00 C9 00 02 04 00 10 00 01
```

**Antwort**: Echo von Start und Anzahl (`00 C9 00 02`).

> Weil FC16 atomar ist, vermeidet dies einen Startbefehl, während der Stromsollwert noch `0` ist (was das Gerät mit Exception `0x03` ablehnt; Firmware älter als diese Basis meldete dafür `0x04`). Es umgeht außerdem die Start/Stopp-Verriegelung: Gemeinsam geschrieben, wird der Stromsollwert angeboten, sobald der Startbefehl committet ist. `Set_Charge_Power_Target` (`40201`) ist nicht implementiert; das Laden wird ausschließlich über `Set_Charge_Current_Target` (`40202`) und `Start_Stop_Charging` (`40203`) gesteuert.

### In den Failsafe eintreten (und ihn verlassen)

**Verhalten**: Bleibt der EMS-Verkehr aus, entscheidet die Ladestation anhand von `Failsafe_Timeout`, wann der Failsafe-Strom angewendet wird.

**Relevante Register**

* `40204` (PDU 203) `Failsafe_Timeout` (s) – RW; `0` deaktiviert; ungleich null muss `10-3600` sein; Standard `20`.
* `40206` (PDU 205) `Failsafe_Current_Target` (A, `u16`) – RW; `0` oder ein Strom innerhalb des Stationsfensters (`MinCurrent`-`MaxCurrent`, HR `40104`/`40105`).
* `30027` (PDU 26) `Failsafe_Active` (`0/1`) – **reines Lese-Input-Register** (per FC04 lesen).
* `40208` (PDU 207) `Heartbeat` – nur schreibbar; periodisch einen beliebigen Wert schreiben.
* `30004` (PDU 3) `ErrorCode`.

**Ablauf**

1. Das EMS konfiguriert `Failsafe_Current_Target` und `Failsafe_Timeout` und schreibt dann periodisch den `Heartbeat` (`40208`) – nur angenommene Schreibzugriffe auf `40202`, `40203`, `40208` oder `40209` setzen den Timer zurück.
2. Trifft innerhalb von `Failsafe_Timeout` Sekunden kein timer-zurücksetzender Schreibzugriff ein, tritt die Ladestation in den Failsafe ein: Sie wendet `Failsafe_Current_Target` an, setzt `Failsafe_Active = 1` (lesbar unter IR `30027`) und meldet `ErrorCode = 7` (Failsafe aktiv). Kann die Ladestation den Failsafe-Strom nicht anwenden, bleibt `Failsafe_Active` auf `0`, und das Gerät versucht es erneut.
3. Nimmt das EMS die Kommunikation wieder auf, verlässt die Ladestation den Failsafe: Sie stellt zuerst den vom Client beabsichtigten Strom wieder her (basierend auf `Start_Stop_Charging`) und löscht dann `Failsafe_Active = 0`. `ErrorCode` kehrt zu seinem normalen Wert zurück.

**Konfigurationspersistenz (live zuerst)**

* Schreibzugriffe auf `Failsafe_Timeout` (`40204`) und `Failsafe_Current_Target` (`40206`) werden **sofort** wirksam und **nie zurückgerollt**; ein Rücklesewert entspricht immer dem wirksamen Wert.
* Das Speichern des Werts im permanenten Speicher erfolgt nach bestem Bemühen. Wurde er noch nicht gespeichert, ist **DaemonStatus Bit 3** (`persistence_degraded`, IR `30050`) gesetzt, und ein Reboot in diesem Zeitfenster stellt den zuvor gespeicherten Wert wieder her. Muss eine Änderung einen sofortigen Stromzyklus überstehen, prüfen Sie nach dem Schreibzugriff, dass Bit 3 auf `0` steht.

---

## Regeln zur Datencodierung

* **Zeichenketten**: Jedes 16-Bit-Register trägt zwei ASCII-Zeichen (MSB = erstes). Zeichenketten sind nicht nullterminiert; unbenutzte Bytes sind `0`. Abschließende Nullen abschneiden. Beispiel: Die Register `0x6350 0x4832` dekodieren zu `cPH2`.
* **float32**: IEEE-754-32-Bit-Floats werden Big-Endian mit dem **höherwertigen Wort an der niedrigeren Adresse** übertragen. Beide Register vor dem Dekodieren zusammensetzen. Beispiel: `16.0` -> `0x41800000` -> höherwertiges Wort `0x4180`, niederwertiges Wort `0x0000`.
* **uint32**: Big-Endian-Byte- und -Wortreihenfolge, höherwertiges Wort an der niedrigeren Adresse. Verwendet für `Uptime` und `Temperature` (ganzzahlige Grad C). Beispiel: `0x0203004B` -> höherwertiges Wort `0x0203`, niederwertiges Wort `0x004B`.
* **uint16 / boolean / enum**: ein einzelnes Big-Endian-Register; Booleans verwenden `0 = false`, `1 = true`; Aufzählungen verwenden die Werte aus den Tabellen oben (unbekannte Codes als reserviert behandeln).

---

## Zeitregeln und Empfehlungen

* **Telemetrietakt**: Die Ladestation aktualisiert Zähler- und Zustandsregister mindestens alle **5 s**. Vermeiden Sie ein Abfragen schneller als die Aktualisierungsrate; cachen Sie Werte, wo möglich.
* **Sollwert-/Heartbeat-Takt**: Frischen Sie den Heartbeat (oder einen anderen timer-zurücksetzenden Schreibzugriff) häufiger auf als das konfigurierte `Failsafe_Timeout`. Eine sichere Regel ist höchstens **Timeout / 2**: Beim Standard-Timeout von 20 s mindestens alle **10 s** schreiben; beim Mindest-Timeout von 10 s mindestens alle **5 s**. Schreibzugriffe auf `Set_Charge_Current_Target`, `Start_Stop_Charging`, `Target_Phase` und das dedizierte `Heartbeat`-Register setzen alle den Failsafe-Timer zurück.
* **Antwortzeit**: 95 % der Modbus-Antworten werden unter normalen Bedingungen innerhalb von **200 ms** zurückgegeben.
* **Kohärente Snapshots**: Mehrregister-Lesezugriffe liefern Daten aus einem konsistenten Snapshot. Vermeiden Sie es, Registerbereiche zu mischen, die zu unterschiedlichen Zeiten aktualisiert werden (z. B. Identität und Leistung in derselben Anfrage lesen).
* **Bereitschaftsprüfung**: Bevor Sie die Automatisierung nach einem Reboot der Ladestation starten, fragen Sie DaemonStatus (`30050`) ab und warten Sie auf Bit 0 (`units_ready`).

---

## Fehlerbehandlung

* Ungültige Funktionscodes, Adressen oder Werte erzeugen Modbus-Exception-Antworten: `0x01` Illegal Function, `0x02` Illegal Data Address, `0x03` Illegal Data Value, `0x04` Slave Device Failure, `0x06` Server Device Busy, `0x0A` Gateway Path Unavailable (nur weitergeleitete Slaves), `0x0B` Gateway Target Device Failed to Respond.
* **Schreibzugriffe** folgen dieser Matrix:

    * Schreibzugriff auf ein reines Leseregister oder ein Wert außerhalb des gültigen Bereichs -> `0x03` (das Register bleibt unverändert; kein Begrenzen).
    * Schreibzugriff auf eine gültige, aber nicht beschreibbare Adresse (z. B. `40108` oder eine Lücke) -> `0x02`.
    * Falsch ausgerichtetes / Mehrregister-Telegramm mit falscher Länge -> `0x03`.
    * Laden starten (`40203 = 1`), während `Set_Charge_Current_Target` auf `0` steht -> `0x03` (zuerst einen gültigen Stromsollwert setzen; ein FC16-Telegramm, das beides kombiniert, ist das sichere Muster). Firmware älter als diese Basis meldete dafür `0x04`.
    * Ein FC16-Telegramm, das `MinCurrent` über `MaxCurrent` hinterlassen würde -> `0x03`, wobei kein Register des Telegramms geändert wird.
    
* Werte außerhalb des Bereichs werden **abgelehnt**, nicht begrenzt: Das Register behält seinen vorherigen Wert, ein erneutes Lesen nach einem abgelehnten Schreibzugriff zeigt also keine Änderung.

### Fehlersuche

| Symptom | Wahrscheinliche Ursache | Was zu prüfen ist |
| --- | --- | --- |
| Gar keine Verbindung möglich (TCP-Reset / abgewiesen, keine Modbus-Antwort)  | Ihre IP steht nicht auf der Allow-List, oder ein Verbindungslimit wurde erreicht  | Bestätigen Sie, dass Ihre Quell-IP auf der Allow-List steht; prüfen Sie, ob Sie innerhalb von 4 Verbindungen/IP und 32 insgesamt liegen  |
| Exception `0x06`  | Ratenbegrenzung, oder der Daemon startet noch  | Warten und erneut versuchen; DaemonStatus (`30050`) Bit 0 abfragen  |
| Exception `0x0B`  | Falsche Unit ID  | Die konfigurierte Unit ID verwenden (Standard `1`)  |
| Schreibzugriff liefert `0x03`  | Wert außerhalb des Bereichs, oder das Ziel ist nur lesbar  | Einen Wert innerhalb der dokumentierten Grenzen senden; keine reinen Leseregister schreiben  |
| Schreibzugriff liefert `0x02`  | Adresse ist nicht beschreibbar  | Nur die beschreibbaren Bereiche schreiben (`40104-40107`, `40201-40225`)  |
| Stromsollwert mit `0x03` abgelehnt, obwohl der Wert innerhalb von `6-32` liegt  | Das Fenster der Station ist enger als der Hardware-Bereich  | `MinCurrent` (`40104`) und `MaxCurrent` (`40105`) lesen – Schreibzugriffe auf `40202`/`40206` werden gegen dieses Fenster validiert, nicht gegen `6-32`  |
| Ladestart liefert `0x03` (`0x04` bei älterer Firmware)  | Stromsollwert ist beim Start `0`  | Zuerst `Set_Charge_Current_Target` innerhalb des Stationsfensters setzen oder ein atomares FC16-Telegramm verwenden  |
| Stromsollwert angenommen, aber die Ladestation bleibt bei `0 A`  | `Start_Stop_Charging` steht auf `0`, daher wird der angebotene Strom auf `0` gezwungen  | `1` nach `40203` schreiben oder beide Register in einem FC16-Telegramm schreiben  |
| Stromsollwert angenommen und Laden läuft, aber der Strom driftet auf einen anderen Wert  | Die Station ist im Modus ECO oder POWER und berechnet den Strom selbst  | `ChargeMode_Actual` (`30601`) lesen; `ChargeMode` (`40107`) auf `2` (MANUAL) setzen und den Sollwert erneut schreiben  |
| Ein Sollwert-Schreibzugriff auf `40106`/`40107` liest korrekt zurück, aber nichts ändert sich  | Diese Register sind EMS-Sollwerte; die Station führt möglicherweise etwas anderes aus  | Mit `EcoPlus_Actual` (`30602`) und `ChargeMode_Actual` (`30601`) vergleichen  |
| Laden startet nicht, alle Sollwerte sehen korrekt aus  | Das Laden ist lokal über das Web-Oberfläche oder die App pausiert  | `PauseCharging_Actual` (`30603`) lesen; eine lokale Pause überstimmt einen EMS-Start  |
| `ErrorCode = 4` löscht sich nicht  | Die Station liegt noch über der Löschschwelle  | Löscht sich von selbst, sobald die Elektronik 5 K unter die Schwelle abgekühlt ist; kein Neustart nötig. `Temperature` (`30025`) beobachten  |
| `EVCS_State = 4` (ERROR), während die Station normal lädt  | Jeder `ErrorCode` ungleich null verdeckt den Ladezustand  | `ErrorCode` (`30004`) lesen; auch ein informativer Code wie `4` zwingt `EVCS_State` auf ERROR  |
| `EVCS_State` zeigt CHARGING für eine Sitzung, die das EMS nicht gestartet hat  | Seit `MapVersion 2.1.0` erwartetes Verhalten  | CHARGING spiegelt den Energiefluss wider, egal wer ihn gestartet hat; `Start_Stop_Charging` (`40203`) für den eigenen Befehlszustand lesen  |
| `ErrorCode = 7` und `Failsafe_Active = 1`  | Die EMS-Kommunikation ist länger als das Timeout ausgeblieben  | Heartbeat wieder aufnehmen; das Gerät stellt den beabsichtigten Strom wieder her und löscht dann das Flag  |
| `ActualPhase` (`30303`) liest `0`  | Keine Sitzung aktiv, daher ist keine Phase auf das Schütz geschaltet  | An einer Station im Leerlauf erwartet. `30303` meldet `1` oder `3` nur, solange eine Sitzung läuft  |
| `Target_Phase` (`40209`) angenommen, aber nichts passiert  | Keine aktive Sitzung, oder die angeforderte Phase entspricht der gespeicherten Auswahl  | Während einer laufenden Sitzung (CP-Zustand C/D) umschalten und die Phase anfordern, auf der die Station *nicht* steht; siehe **Phasenwahl**  |
| `30301` liest `1`, aber `30302`, `30303` und `30304` bleiben alle auf `0`  | Die Ladefirmware hat die Phasenumschaltung noch deaktiviert – sie und der Modbus-Daemon lesen die Konfiguration beim Start getrennt  | Die gesamte Station neu starten, nicht nur den Daemon. `GET /api/?path=secc/port0/salia/phase_switching/status` muss `"idle"` oder `"progress"` liefern  |
| `Target_Phase` (`40209`) liest nach einem Schreibzugriff `0` zurück  | Der Schreibzugriff wurde nie committet – abgelehntes Telegramm oder eine andere Adresse auf dem Bus  | `40209` allein mit FC06 schreiben und auf Exception `0x03` prüfen; bestätigen, dass das Telegramm PDU-Offset `208` trägt. Ein FC16-Telegramm wird als Ganzes abgelehnt, wenn ein Register darin die Validierung nicht besteht  |
| Temperatur liest als riesige/unsinnige Zahl  | Als Float dekodiert  | `30025` als Big-Endian-`u32` dekodieren (ganzzahlige Grad C)  |

---

## Dokumenthistorie

| Version | Datum | Map-Version | Hinweise |
| --- | --- | --- | --- |
| 2.1.1  | 2026-08-26  | 2.1.0  | **Korrigiert**: `ActualPhase` (`30303`) und `TargetPhase` (`30304`) sind `0`, `1` oder `3`, nicht `1` oder `3` – `0` ist der normale Lesewert an einer Station im Leerlauf; `EVCS_State 7` wird nicht mehr als Fortschrittsanzeige einer Phasenumschaltung dargestellt. **Ergänzt**: Der Abschnitt **Phasenwahl** stellt jetzt fest, dass eine Umschaltung nur während einer aktiven Ladesitzung (CP-Zustand C/D) ausgeführt wird, nennt die zwei stillen No-op-Fälle, die Tatsache, dass ein angenommener Schreibzugriff die Zustellung und nicht die Ausführung bestätigt, das tatsächliche Zeitverhalten der Umschaltung, dass `30305`/`30306` es nicht zuverlässig melden, wie die gespeicherte Phasenwahl über REST gelesen wird und warum `30301` keine Live-Bestätigung ist; vier Fehlersuche-Zeilen zur Phasenumschaltung. Kein Register ist umgezogen und kein Verhalten hat sich geändert – nur Dokumentation.  |
| 2.1.0  | 2026-08-20  | 2.1.0  | **Korrigiert**: `MapVersion` ist `2.1.0`; ein Start mit Stromsollwert null liefert `0x03`, nicht `0x04` (an vier Stellen, einschließlich Exception-Tabelle und Fehlersuche-Matrix); die Beschreibung von `0x04` impliziert keinen ungültigen Wert mehr; `Set_Charge_Current_Target` und `Failsafe_Current_Target` sind durch das Stationsfenster `MinCurrent`-`MaxCurrent` begrenzt statt durch ein festes `6-32`. **Ergänzt**: der Block **Tatsächlicher Konfigurationszustand** (IR `30601-30603`); ein Abschnitt **Steuerung der Ladestation** zur Start/Stopp-Verriegelung auf `40202`, zur Anforderung des Modus MANUAL und zur Phasenwahl; ein Abschnitt **Wie die Zustandssignale abgeleitet werden** mit den Bedingungstabellen für `EVCS_State` und `Connector_State`; die Erkennungsbedingungen der Fehlercodes; die FC16-Regel, die `MinCurrent > MaxCurrent` ablehnt; neun Fehlersuche-Zeilen. **Geändert**: `EVCS_State = CHARGING` erfordert nicht mehr den EMS-Startbefehl; Übertemperatur (`ErrorCode 4`) wird aus dem aktuellen Messwert mit 5 K Hysterese bewertet, löscht sich ohne Neustart und verwendet eine je Station aus der Hardware gelesene Schwelle statt eines festen Werts. **Klargestellt**: `MinCurrent`/`MaxCurrent` folgen der Station, `EcoPlus`/`ChargeMode` sind reine EMS-Sollwerte, und `ErrorCode 4` ist informativ, zwingt `EVCS_State` aber dennoch auf ERROR.  |
| 2.0.1  | 2026-07-29  | 2.0.0  | ErrorCode-PDU-Offset im Failsafe-Beispiel korrigiert (`3`, nicht `4`); FirmwareVersionU32-Beispiel auf `0x0203004B` korrigiert; die genaue Menge der timer-zurücksetzenden Failsafe-Schreibzugriffe angegeben (`40202`/`40203`/`40208`/`40209`); die Hinweise zu Plug_Error und Contactor_Error korrigiert (Firmware-Fehlercodes, nicht Tabelle B); DaemonStatus Bit 2 korrigiert (Latch seit dem Start); sechs Blockbereiche auf das letzte belegte Register korrigiert; Persistenz von Failsafe_Power_Target auf `VOL` korrigiert; die Empfehlung zur Auswahl von Leistungs-/Strommodus ersetzt; Lesezugriffe auf Nur-Schreib-Register und die Auflistung reservierter Einträge klargestellt.  |
| 2.0.0  | 2026-06-16  | 2.0.0  | Failsafe_Active auf IR `30027` korrigiert; Konfigurationsblock neu geschrieben (korrekte Adressen, beschreibbare Sollwerte); Temperature auf `u32` korrigiert; Sicherheitsabschnitt, DaemonStatus (`30050`), den vollständigen Exception-Satz (`0x06`/`0x0A`/`0x0B`), Fehlerpriorität, Verfügbarkeit des Netz-Blocks, das FC16-Beispiel und eine Fehlersuche-Matrix ergänzt; Ablehnen-statt-Begrenzen und Skalierung klargestellt.  |
| 1.0.0  | --  | 1.0.0  | Erstveröffentlichung (abgelöst).  |

---

_(c) eCharge Hardy Barth GmbH – Modbus-TCP-Dokumentation_
