# Benutzerdefinierte Geräte

> Zeigt, wie du Wallbox, Zähler, Fahrzeug oder Heizung ohne fertige Vorlage einbindest, indem du Messwerte und Steuerung selbst per HTTP, MQTT oder Modbus definierst.

Beim Anlegen einer Wallbox, eines Heizgeräts, eines Netzzählers, einer Batterie, einer PV-Anlage, eines weiteren Verbrauchers, eines Fahrzeugs, eines Tarifs, eines Einspeisebegrenzers oder eines Benachrichtigungsdienstes lässt sich in der Geräteliste der Eintrag **Benutzerdefiniertes Gerät** wählen und eine eigene Logik auf Basis des [Plugin-Systems](/de/reference/plugins) beschreiben.

So lassen sich auch Geräte einbinden, die nicht von einem eingebauten Template abgedeckt sind, z. B. die aktuelle Leistung über einen HTTP-Endpunkt lesen oder einen Zielstrom per Modbus schreiben.

## Ein Gerät definieren

In der Benutzeroberfläche steht bei jedem Gerätetyp der Eintrag **Benutzerdefiniertes Gerät** in der Template-Auswahl bereit. Damit öffnet sich der Editor für die eigene Konfiguration. Standardmäßig wird ein Gerät mit `type: custom` angelegt. Der Typ lässt sich bei Bedarf mit einem anderen Wert überschreiben (z. B. `type: heatpump`).

```yaml
power:
  source: mqtt
  topic: home/current/imsys/chn2/raw
```

Alternativ lässt sich die vollständige Konfiguration direkt in die `evcc.yaml` schreiben, mit `name`, `type: custom` und den Attributen darunter:

```yaml
meters:
  - name: imsys
    type: custom
    power:
      source: mqtt
      topic: home/current/imsys/chn2/raw
```

Alle weiteren Beispiele auf dieser Seite verwenden die flache Attribut-Block-Form, wie sie in der UI eingegeben wird.

Die Liste der verfügbaren Plugin-Quellen (`http`, `mqtt`, `modbus`, …) und Helper (`calc`, `map`, `watchdog`, …) steht in der [Plugins-Referenz](/de/reference/plugins).

## Attribute und Features

Jedes benutzerdefinierte Gerät besteht aus drei Arten von Feldern:

* **Lese-Attribute** — Plugins, die evcc regelmäßig abfragt, um einen Wert zu erhalten (z. B. `power`, `soc`, `status`).
* **Schreib-Attribute** — Plugins, die evcc aufruft, um einen Wert zu setzen oder eine Aktion auszulösen (z. B. `enable`, `maxcurrent`, `wakeup`). Der zu schreibende Wert steht im Plugin zur Verfügung.
* **Features** — `features`-Liste, die abweichendes Verhalten freischaltet. Verfügbare Flags hängen vom Gerätetyp ab.

Allgemeine Form:

```yaml
# Lese-Attribute
power:
  source: http
  uri: http://meter.local/power
soc:
  source: mqtt
  topic: battery/soc


# Schreib-Attribute
enable:
  source: http
  uri: "http://charger/relay?turn={{if .enable}}on{{else}}off{{end}}"
maxcurrent:
  source: mqtt
  topic: charger/maxcurrent
  payload: ${maxcurrent:%d}


# Features
features:
  - heating
  - integrateddevice
```

Welche Attribut-Namen und Feature-Flags verfügbar sind, hängt vom Gerätetyp ab und steht in den nachfolgenden Abschnitten.

## Zähler

Stromzähler werden in der Sektion [`meters`](/de/reference/configuration/meters) konfiguriert. Zähler unter `meters:` können an verschiedenen Stellen innerhalb der `site` Konfiguration referenziert werden:

* `grid`: Netzzähler
* `pv`: PV-Zähler
* `battery`: Hausbatteriezähler
* `charge`: Zähler für die Ladeleistung der Wallbox
* `aux`: Verbrauchszähler für intelligente Verbraucher
* `consumer`: Zähler für einen regulären Verbraucher, erfasst für die Verbrauchsstatistik
* `ext`: Weiterer Zähler, der nicht für die Regelung verwendet oder angezeigt wird, nur geloggt und exportiert

`power` ist das einzig erforderliche Attribut. Nicht alle Zählerrollen unterstützen alle Attribute:

* `limitsoc` und `batterymode` werden ausschließlich für Batteriezähler genutzt (referenziert in `site.battery`).
* `curtail` und `curtailed` werden gemeinsam für `pv`-Zähler verwendet, die eine Abregelung der Einspeisung unterstützen (§ 9 EEG).
* `currents`, `voltages` und `powers` sind Phasen-Attribute, die mit genau drei Plugin-Konfigurationen (als YAML-Array) konfiguriert werden müssen und für Netzzähler (`grid`) und Wallboxen (`charge`) verwendet werden können.

Plugins müssen den richtigen Datentyp zurückliefern. Zur Konvertierung dienen die [Lese-Pipelines](/de/reference/plugins#reading).

### Lese-Attribute

| Attribut       | Typ                   | Erfordert | Kontext       | Beschreibung                                                                |
| -------------- | --------------------- | --------- | ------------- | --------------------------------------------------------------------------- |
| `power`        | `float`               | ja        | alle          | Aktuelle Leistung in W                                                      |
| `energy`       | `float`               | nein      | alle          | Zählerstand in kWh                                                          |
| `returnenergy` | `float`               | nein      | alle          | Zählerstand in Gegenrichtung in kWh (siehe unten)                           |
| `maxpower`     | `int`                 | nein      | `pv` (hybrid) | Maximale AC-Leistung in W                                                   |
| `curtailed`    | `int`                 | nein      | `pv`          | Aktuelles Einspeiselimit in % (0 bis 100). Nur zusammen mit `curtail`.      |
| `soc`          | `int`                 | nein      | `battery`     | Ladestand in %                                                              |
| `capacity`     | `float`               | nein      | `battery`     | Kapazität in kWh                                                            |
| `powers`       | `[float,float,float]` | nein      | alle          | Phasenleistungen in W. Zur Vorzeichenerkennung bei vorzeichenlosen Strömen. |
| `currents`     | `[float,float,float]` | nein      | alle          | Phasenströme in A. Zur Erkennung aktiver Phasen.                            |
| `voltages`     | `[float,float,float]` | nein      | alle          | Phasenspannungen in V. Zur Anschlusserkennung (1p/3p).                      |

### Vorzeichen und Richtungen

Was ein positiver `power`-Wert und die beiden Energierichtungen bedeuten, hängt von der Zählerrolle ab:

| Rolle                    | `power` positiv           | `energy`   | `returnenergy`      |
| ------------------------ | ------------------------- | ---------- | ------------------- |
| `grid`                   | Netzbezug                 | Bezogen    | Eingespeist         |
| `pv`                     | Erzeugung                 | Erzeugt    | Verbraucht (selten) |
| `battery`                | Entladen (negativ: Laden) | Entladen   | Geladen             |
| `charge`                 | Laden                     | Geladen    | Entladen (V2X)      |
| `aux`, `ext`, `consumer` | Verbrauch                 | Verbraucht | Erzeugt (selten)    |

`energy` und `returnenergy` sind steigende Zählerstände in kWh, idealerweise Gesamtwerte wie die Bezugs- und Einspeiseregister eines Stromzählers. Die Differenzen zwischen den Zählerständen werden automatisch berechnet. Das Plugin muss deshalb einen Zählerstand liefern und keine Verbrauchswerte pro Intervall. Auch ein Zähler, der sich regelmäßig zurücksetzt (z. B. täglich), funktioniert, da der Rücksprung automatisch erkannt wird. Ein Zählerstand von `0` wird als nicht verfügbar behandelt.

Beide Attribute sind optional. Ohne sie wird die Energiehistorie aus dem zeitlichen Verlauf von `power` abgeleitet. Echte Zählerstände liefern genauere Langzeitstatistiken.

### Schreib-Attribute

| Attribut      | Typ   | Erfordert | Kontext   | Beschreibung                                                                                                                                                    |
| ------------- | ----- | --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limitsoc`    | `int` | nein      | `battery` | Setze Ladeziel für Batterie in %. Das Ladeziel wird aus den konfigurierten `MinSoc`, `MaxSoc` und dem aktuellen Ladestand (Attribut `soc`) berechnet.           |
| `curtail`     | `int` | nein      | `pv`      | Setze Einspeiselimit in % der Nennleistung der Erzeugung (0 bis 100, `100` = kein Limit). Nur zusammen mit `curtailed`. Siehe [Einspeisebegrenzer](#curtailer). |
| `batterymode` | `int` | nein      | `battery` | Setze den Steuerungsmodus der Batterie direkt. Die Modi sind unten aufgeführt.                                                                                  |

#### Batteriemodi

| Wert | Modus        | Verhalten                                                          |
| ---- | ------------ | ------------------------------------------------------------------ |
| `1`  | `normal`     | Normaler Betrieb: Laden aus Überschuss, Entladen für den Verbrauch |
| `2`  | `hold`       | Entladen verhindern, Laden aus Überschuss bleibt erlaubt           |
| `3`  | `charge`     | Aus dem Netz laden, kein Entladen                                  |
| `4`  | `holdcharge` | Laden verhindern, Entladen für den Verbrauch bleibt erlaubt        |
| `5`  | `discharge`  | Einspeisung ins Netz                                               |

Es werden nur die Batteriemodi genutzt, die das Gerät unterstützt. Ist `batterymode` ein [`switch`](/de/reference/plugins#switch), werden die unterstützten Modi aus dessen `case`-Werten übernommen. Das funktioniert auch, wenn der Switch in einem [`watchdog`](/de/reference/plugins#watchdog) steckt. Für alle anderen Plugins müssen die unterstützten Modi in `batterymodes` angegeben werden, z. B. `batterymodes: ["normal", "hold", "charge"]`.

### Beispiele

Lese die aktuelle Netzleistung über einen HTTP-Endpunkt.

```yaml
meters:
  - name: grid
    type: custom
    power:
      source: http
      uri: http://zaehler.network.local:8080/api/data.json?from=now
      jq: .data.tuples[0][1]
```

Lese Leistung und Ladestand einer Hausbatterie und setze ihren Modus über HTTP. Der `switch` deckt die Modi normal, hold und charge ab, evcc bietet also genau diese drei an.

```yaml
meters:
  - name: battery
    type: custom
    capacity: 10 # kWh
    power:
      source: http
      uri: http://battery.local/api/power
    soc:
      source: http
      uri: http://battery.local/api/soc
    batterymode:
      source: switch
      switch:
        - case: 1 # normal
          set:
            source: http
            uri: http://battery.local/api/mode
            method: POST
            body: '{"mode": "auto"}'
        - case: 2 # hold
          set:
            source: http
            uri: http://battery.local/api/mode
            method: POST
            body: '{"mode": "hold"}'
        - case: 3 # charge
          set:
            source: http
            uri: http://battery.local/api/mode
            method: POST
            body: '{"mode": "charge"}'
```

## Wallbox

Der Standardtyp `type: custom` deckt Wallboxen mit stufenloser Stromregelung ab. Für andere Geräte stehen spezialisierte Charger-Typen unter [Switchsocket](#charger-switchsocket) und [Wärmepumpen](#charger-heating) bereit.

### Lese-Attribute

| Attribut       | Typ                   | Erfordert | Beschreibung                                                                             |
| -------------- | --------------------- | --------- | ---------------------------------------------------------------------------------------- |
| `status`       | `string`              | ja        | Status (A..F)                                                                            |
| `enabled`      | `bool`                | ja        | Ist Ladung freigegeben?                                                                  |
| `power`        | `float`               | nein      | Ladeleistung in W                                                                        |
| `energy`       | `float`               | nein      | Zählerstand in kWh                                                                       |
| `returnenergy` | `float`               | nein      | Zählerstand in Gegenrichtung in kWh (Entladeenergie, V2X)                                |
| `identify`     | `string`              | nein      | Aktuelle RFID-Kennung                                                                    |
| `soc`          | `int`                 | nein      | Ladestand in %                                                                           |
| `limitsoc`     | `int`                 | nein      | Ladelimit in %                                                                           |
| `temp`         | `float`               | nein      | Aktuelle Temperatur in °C (Heizung, Alias für `soc`)                                     |
| `limittemp`    | `int`                 | nein      | Temperaturlimit in °C (Heizung, Alias für `limitsoc`)                                    |
| `finishtime`   | `string`              | nein      | Geschätztes Ladeende (RFC3339, Go-Duration, Unix-Zeitstempel oder verbleibende Sekunden) |
| `phases`       | `int`                 | nein      | Anzahl der physischen Phasen (1..3)                                                      |
| `powers`       | `[float,float,float]` | nein      | Phasenleistungen in W. Zur Vorzeichenerkennung bei vorzeichenlosen Strömen.              |
| `currents`     | `[float,float,float]` | nein      | Phasenströme in A. Zur Erkennung aktiver Phasen.                                         |
| `voltages`     | `[float,float,float]` | nein      | Phasenspannungen in V. Zur Anschlusserkennung (1p/3p).                                   |

### Schreib-Attribute

| Attribut           | Typ     | Erfordert | Beschreibung                                          |
| ------------------ | ------- | --------- | ----------------------------------------------------- |
| `enable`           | `bool`  | ja        | Ladung freigeben / sperren                            |
| `maxcurrent`       | `int`   | ja        | Setze maximalen Ladestrom in A                        |
| `maxcurrentmillis` | `float` | nein      | Setze maximalen Ladestrom in A (mit Nachkommastellen) |
| `phases1p3p`       | `int`   | nein      | Phasenumschaltung durchführen (erfordert `tos: true`) |
| `wakeup`           | `bool`  | nein      | Wecke Fahrzeug auf                                    |

### Features

| Feature            | Beschreibung                                                                                                                                                                                                                                                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `integrateddevice` | Gerät ohne angeschlossenes Fahrzeug und ohne Ladesitzungen (z. B. Wärmepumpe, Heizstab, fest installierter Verbraucher). Keine Fahrzeugauswahl.                                                                                                                                                                                                         |
| `heating`          | Behandelt das Gerät als Heizung: SOC und Limits werden in °C statt in % dargestellt.                                                                                                                                                                                                                                                                    |
| `continuous`       | Gerät läuft im “deaktivierten” Zustand eigenständig in seinem Normalbetrieb weiter. Statt “Standby” wird “Normalbetrieb” angezeigt. Eine Empfehlung zur Leistungserhöhung (z. B. bei PV-Überschuss oder günstigem Strom) wird als “Boost” gekennzeichnet. Die Modi heißen **Normal**, **Smart** und **Boost** statt **Aus**, **Smart** und **Schnell**. |
| `switchdevice`     | Gerät kann nur ein- und ausgeschaltet werden (keine stufenlose Stromregelung). Max-Strom und die Option **Dauerhaft laden** werden nicht angezeigt. Min-Strom und Phasen legen die PV-Einschaltleistung fest. Ohne `continuous` heißen die Modi **Aus**, **Smart** und **Ein**.                                                                         |

Häufige Feature-Kombinationen aus den vorkonfigurierten Templates:

**Heizstab**:

```yaml
features:
  - integrateddevice
  - heating
```

**Steckdose**:

```yaml
features:
  - switchdevice
  - integrateddevice # optional, wenn die Steckdose einen festen Verbraucher schaltet
  - heating # optional, wenn ein Heizgerät geschaltet wird
```

**Wärmepumpe**:

```yaml
features:
  - integrateddevice
  - heating
  - continuous
  - switchdevice # optional, wenn keine Stromregelung vorhanden (SG Ready)
```

### Beispiele

Frage den Ladestatus einer Wallbox per Modbus ab.

```yaml
features:
  - integrateddevice
enabled:
  source: modbus
  id: 4711
  uri: modbus.local:502
  rtu: false
  register:
    address: 100
    type: holding
    decode: uint16
```

Schalte eine Tasmota-Steckdose per MQTT-Nachricht.

```yaml
enable:
  source: mqtt
  broker: mosquitto.local:883
  topic: cmd/unu-switch/Power
  payload: ON
```

### Switchsocket

**`type: switchsocket`**

Für schaltbare Steckdosen und vergleichbare Relais-Geräte, die nur ein-/ausgeschaltet werden können, ohne stufenlose Stromregelung. Der Ladestatus wird aus der aktuellen Leistung abgeleitet (oberhalb `standbypower` gilt als Laden). Vollständige Einrichtung unter [Schaltbare Steckdosen](/de/smartswitches).

| Attribut       | Typ     | Erfordert | Beschreibung                                                                                            |
| -------------- | ------- | --------- | ------------------------------------------------------------------------------------------------------- |
| `enabled`      | `bool`  | ja        | Status der Steckdose (an/aus)                                                                           |
| `power`        | `float` | ja        | Aktuelle Leistung in W                                                                                  |
| `energy`       | `float` | nein      | Zählerstand in kWh                                                                                      |
| `soc`          | `float` | nein      | Ladestand in %                                                                                          |
| `enable`       | `bool`  | ja        | Steckdose ein-/ausschalten                                                                              |
| `standbypower` | `float` | nein      | Schwellwert in W. Darüber: Laden, darunter: Standby. Negativ: statisch (keine Leistungsmessung möglich) |

### Wärmepumpen

Für Wärmepumpen und vergleichbare Heizgeräte gibt es eigene Charger-Typen mit jeweils eigenen Attributen. Die vollständige Einrichtung ist unter [Wärmepumpen, Heizstäbe](/de/heating) beschrieben.

* Wärmepumpe

  **`type: heatpump`**

  Für wechselrichtergesteuerte Wärmepumpen, die einen kontinuierlichen Leistungs-Sollwert per Modbus, HTTP o. Ä. annehmen. Die Ziel-Heizleistung wird direkt über `setmaxpower` geschrieben.

  | Attribut      | Typ     | Erfordert | Beschreibung                          |
  | ------------- | ------- | --------- | ------------------------------------- |
  | `power`       | `float` | nein      | Aktuelle Leistung in W                |
  | `energy`      | `float` | nein      | Zählerstand in kWh                    |
  | `temp`        | `float` | nein      | Aktuelle Temperatur in °C             |
  | `limittemp`   | `int`   | nein      | Geräte-internes Temperaturlimit in °C |
  | `setmaxpower` | `int`   | ja        | Setze maximale Heizleistung in W      |
  | `getmaxpower` | `float` | nein      | Aktuelle maximale Heizleistung in W   |

* SG-Ready

  **`type: sgready`**

  Für Wärmepumpen mit klassischer SG-Ready-Schnittstelle, gesteuert über einen einzelnen Modus-Wert. Drei Modi werden unterstützt: `1` reduziert, `2` normal, `3` boost.

  | Attribut      | Typ     | Erfordert | Beschreibung                                            |
  | ------------- | ------- | --------- | ------------------------------------------------------- |
  | `power`       | `float` | nein      | Aktuelle Leistung in W                                  |
  | `energy`      | `float` | nein      | Zählerstand in kWh                                      |
  | `temp`        | `float` | nein      | Aktuelle Temperatur in °C                               |
  | `limittemp`   | `int`   | nein      | Geräte-internes Temperaturlimit in °C                   |
  | `setmode`     | `int`   | ja        | Ändere SG-Ready-Modus (1: reduced, 2: normal, 3: boost) |
  | `getmode`     | `int`   | nein      | Aktueller SG-Ready-Modus (1, 2, 3)                      |
  | `setmaxpower` | `int`   | nein      | Setze maximale Heizleistung in W                        |

* SG-Ready über Relais

  **`type: sgready-relay`**

  Für Wärmepumpen, deren SG-Ready-Eingang als zwei potentialfreie Relais-Kontakte (boost + dim) ausgeführt ist. Jeder Kontakt wird über einen eigenen Sub-Charger geschaltet, referenziert per Typ statt per Plugin.

  | Attribut    | Typ             | Erfordert | Beschreibung                          |
  | ----------- | --------------- | --------- | ------------------------------------- |
  | `power`     | `float`         | nein      | Aktuelle Leistung in W                |
  | `energy`    | `float`         | nein      | Zählerstand in kWh                    |
  | `temp`      | `float`         | nein      | Aktuelle Temperatur in °C             |
  | `limittemp` | `int`           | nein      | Geräte-internes Temperaturlimit in °C |
  | `boost`     | `charger-typed` | ja        | Relais für den SG-Ready Boost-Kontakt |
  | `dim`       | `charger-typed` | nein      | Relais für den SG-Ready Dim-Kontakt   |

## Fahrzeug

Fahrzeugparameter können ebenfalls über Plugins ausgelesen werden.

### Lese-Attribute

| Attribut        | Typ      | Erfordert | Beschreibung                                                                             |
| --------------- | -------- | --------- | ---------------------------------------------------------------------------------------- |
| `soc`           | `int`    | ja        | Ladestand in %                                                                           |
| `limitsoc`      | `int`    | nein      | Ladelimit in %                                                                           |
| `status`        | `string` | nein      | Status (A..F)                                                                            |
| `range`         | `int`    | nein      | Reichweite in km                                                                         |
| `odometer`      | `int`    | nein      | Kilometerstand in km                                                                     |
| `climater`      | `bool`   | nein      | Klimatisierung aktiv?                                                                    |
| `getmaxcurrent` | `float`  | nein      | Maximaler Ladestrom in A                                                                 |
| `finishtime`    | `string` | nein      | Geschätztes Ladeende (RFC3339, Go-Duration, Unix-Zeitstempel oder verbleibende Sekunden) |

### Schreib-Attribute

| Attribut       | Typ    | Erfordert | Beschreibung                   |
| -------------- | ------ | --------- | ------------------------------ |
| `wakeup`       | `bool` | nein      | Fahrzeug aufwecken             |
| `chargeenable` | `bool` | nein      | Starte/stoppe den Ladevorgang  |
| `maxcurrent`   | `int`  | nein      | Setze maximalen Ladestrom in A |

### Konfiguration

| Attribut   | Typ      | Erfordert | Beschreibung                   |
| ---------- | -------- | --------- | ------------------------------ |
| `title`    | `string` | nein      | Anzeigename des Fahrzeugs      |
| `capacity` | `float`  | nein      | Batteriekapazität in kWh       |
| `icon`     | `string` | nein      | Icon in der Benutzeroberfläche |

### Features

| Feature         | Beschreibung                                                                                                                                                  |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `coarsecurrent` | Fahrzeug akzeptiert den Ladestrom nur in ganzen 1 A Schritten. Die Regelung wird auf grobe 1 A-Stufen beschränkt, auch wenn die Wallbox feiner regeln könnte. |
| `streaming`     | Fahrzeug liefert Daten per Push statt per Polling (z. B. BMW Cardata). SOC-Updates außerhalb aktiver Ladevorgänge werden als zuverlässig behandelt.           |
| `welcomecharge` | Fahrzeug erwartet beim Anschließen eine aktive Wallbox, um die Verbindung als funktionierend zu erkennen. Andernfalls meldet das Fahrzeug einen Fehler.       |

### Beispiele

Lese die aktuelle Reichweite aus MQTT-Nachrichten.

```yaml
title: Grüner Mazda # Anzeigename (optional)
capacity: 50 # Batteriekapazität in kWh (optional)
features:
  - coarsecurrent
range:
  source: mqtt
  topic: mazda2mqtt/c53/chargeInfo/drivingRangeKm
```

Ein Auto per HTTP-Ping aufwecken, bevor weitere Abfragen folgen.

```yaml
wakeup:
  source: http
  uri: http://teslalogger.local:5000/command/08154711/wake_up
```

[]()

`onIdentify` setzt den Lademodus automatisch, sobald das Fahrzeug erkannt wird.

```yaml
soc:
  source: mqtt
  topic: car/soc
onIdentify:
  mode: smart
```

Verfügbare Modi sind: `off`, `smart`, `now`. Die veralteten Werte `pv` und `minpv` werden weiterhin akzeptiert und aktivieren `smart` mit [Dauerhaft laden](/de/features/modes#always-charge) aus bzw. an.

## Tarif und Vorhersage

Ein benutzerdefinierter Tarif bindet eine eigene Wertquelle über den Plugin-Mechanismus an. Das Attribut `tariff` legt fest, was die Quelle liefert und in welcher Einheit.

### Lese-Attribute

Die Attribute `price` und `forecast` schließen sich gegenseitig aus. Genau eines der beiden ist erforderlich.

| Attribut   | Typ      | Beschreibung                                                                                                 |
| ---------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| `price`    | `float`  | Aktueller Wert. Float-Wert des Plugins.                                                                      |
| `forecast` | `string` | Vorhersage als JSON-String mit einer Liste von Zeiträumen und Werten (siehe Schema unten). Stündlich geholt. |

### Konfiguration

| Attribut       | Typ        | Erfordert | Beschreibung                                                                                                                                                                                                      |
| -------------- | ---------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tariff`       | `string`   | nein      | `price` (Standard), `co2`, `solar` oder `temperature`. Bestimmt die Einheit der zurückgegebenen Werte: Preis in konfigurierter Währung pro kWh, CO₂-Intensität in g/kWh, Solar-Vorhersage in W, Temperatur in °C. |
| `charges`      | `float`    | nein      | Fester Aufschlag pro kWh, der zu jedem Wert addiert wird. Standard `0`.                                                                                                                                           |
| `chargesZones` | `list`     | nein      | Zeitabhängige Aufschläge (z. B. Netzentgelte), die `charges` für bestimmte Zeiträume überschreiben. Siehe [zeitabhängige Netzentgelte](/de/reference/configuration/tariffs#charges-zones).                        |
| `tax`          | `float`    | nein      | Prozentualer Steuersatz auf das Ergebnis, z. B. `0.2` für 20%. Standard `0`.                                                                                                                                      |
| `formula`      | `string`   | nein      | Go-Ausdruck für eine eigene Berechnung, mit `price`, `charges` und `tax` im Scope. Siehe [Beispiele](#formula-examples).                                                                                          |
| `interval`     | `duration` | nein      | Abfrageintervall für `forecast`. Standard `1h`.                                                                                                                                                                   |
| `cache`        | `duration` | nein      | Cache-Dauer für `price`. Standard `15m`.                                                                                                                                                                          |

### Features

| Feature     | Beschreibung                                                                                                                |
| ----------- | --------------------------------------------------------------------------------------------------------------------------- |
| `average`   | Glättet feingranulare Preisstufen (z. B. 15-Minuten-Werte) zu Stundenmittelwerten.                                          |
| `cacheable` | Speichert abgerufene Werte persistent. Bei Neustart oder Ausfall des Anbieters dienen sie als Fallback (bis zu 24 Stunden). |

### Beispiele

**Aktueller Preis via HTTP**:

```yaml
price:
  source: http
  uri: https://example.com/api/price
```

**Vorhersage via HTTP**:

```yaml
forecast:
  source: http
  uri: https://api.allinpower.nl/troodon/api/p/spot_market/prices/?product_type=ELK
  jq: '[.timestamps, .prices] | transpose | map({ "start": (.[0] | strptime("%Y-%m-%dT%H:%M:%S.%f%z") | strftime("%Y-%m-%dT%H:%M:%SZ")), "end": (.[0] | strptime("%Y-%m-%dT%H:%M:%S.%f%z") | mktime + 3600 | strftime("%Y-%m-%dT%H:%M:%SZ")), "value": .[1] }) | tostring'
```

Das Plugin muss eine JSON-Struktur mit einer Liste von Zeiträumen und Preisen zurückgeben. Die Datumsfelder müssen in der Form `YYYY-MM-DDTHH:MM:SSZ` vorliegen, der Preis in der korrekten Währungseinheit (z. B. EUR). evcc arbeitet intern mit 15-Minuten-Intervallen; Plugins können auch stündliche Daten liefern, die automatisch in 15-Minuten-Intervalle umgerechnet werden.

```json
[
  {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-01T00:15:00Z",
    "value": 25.0
  },
  {
    "start": "2025-01-01T00:15:00Z",
    "end": "2025-01-01T00:30:00Z",
    "value": 26.5
  },
  {
    "start": "2025-01-01T00:30:00Z",
    "end": "2025-01-01T00:45:00Z",
    "value": 24.8
  },
  {
    "start": "2025-01-01T00:45:00Z",
    "end": "2025-01-01T01:00:00Z",
    "value": 27.2
  }
]
```

[]()

Das `formula`-Feld akzeptiert einen Go-Ausdruck mit `price`, `charges`, `tax` und dem Slot-Zeitstempel `ts` im Scope. Die [`math`-Bibliothek](https://pkg.go.dev/math) und [`time.Time`](https://pkg.go.dev/time#Time)-Methoden auf `ts` stehen zur Verfügung. Die Formel wird für den aktuellen Preis und jeden Forecast-Slot ausgeführt.

**Preisobergrenze**:

```yaml
charges: 0.22
tax: 0.19
formula: math.Min(0.5, (price + charges) * (1 + tax))
```

Deckelt das Ergebnis bei 50 ct/kWh.

**Keine Einspeisevergütung bei negativen Börsenpreisen** (deutsche PV-Anlagen, Inbetriebnahme ab 25. Februar 2025):

```yaml
formula: factor := 1.0; if price < 0 { factor = 0.0 }; factor * 0.07
```

Zahlt eine feste Einspeisevergütung von 7 ct/kWh, außer wenn der Börsenstrompreis negativ ist.

## Externe Begrenzung

Eine benutzerdefinierte Integration für die [Externe Begrenzung](/de/external-limit) bindet eine Steuerbox oder ein Energiemanagementsystem an, das nicht durch eine integrierte Integration abgedeckt ist. Wähle dazu in der Oberfläche unter **Konfiguration → Externe Begrenzung** die Option **Benutzerdefinierte Integration**.

Einer von vier Typen beschreibt, wie das Begrenzungssignal empfangen wird: `relay` (einzelner Schaltkontakt), `fnn` (FNN-Steuerbox mit mehreren Schaltkontakten), `eebus` (EEBus-Protokoll) oder `custom` (dynamische Limitwerte über Plugins). Jedes Signal wird über eine [Plugin](/de/reference/plugins)-Konfiguration ausgelesen (GPIO, MQTT, HTTP, Modbus). Siehe auch die [`hems`-Konfigurationsreferenz](/de/reference/configuration/hems).

### Relais

Die Anbindung über einen einzelnen Schaltkontakt ist die einfachste Lösung. Die Steuerbox aktiviert einen Kontakt, der von deiner evcc-Instanz ausgewertet wird.

| Attribut      | Typ        | Erforderlich | Beschreibung                                                                                       |
| ------------- | ---------- | ------------ | -------------------------------------------------------------------------------------------------- |
| `maxPower`    | `int` (W)  | ja           | Gesamtleistungslimit, das bei aktivem Signal angewendet wird.                                      |
| `limit`       | Plugin     | ja           | Plugin-Konfiguration zum Auslesen des Schaltkontakts. `true`/`1` = begrenzt, `false`/`0` = normal. |
| `passthrough` | Plugin     | nein         | Leitet das Begrenzungssignal an ein externes System weiter.                                        |
| `interval`    | `duration` | nein         | Abfrageintervall für den Schaltkontakt. Standard `10s`.                                            |

Das Leistungslimit wird dir vom Netzbetreiber mitgeteilt. Bei mehreren steuerbaren Verbrauchseinrichtungen (SteuVE) wird der Gleichzeitigkeitsfaktor berücksichtigt. Du kannst das Limit auch selbst berechnen mit der Formel: **Gesamtlimit = Anzahl SteuVE × 4,2 kW × Gleichzeitigkeitsfaktor**. Details zur Berechnung findest du [hier](https://www.inexogy.com/blog/14a-enwg/).

* Raspberry Pi GPIO

  Bei Verwendung eines Raspberry Pi kann der GPIO-Pin direkt ausgelesen werden:

  ```yaml
  type: relay
  maxPower: 8400 # Beispiel für 2 SteuVE
  limit:
    source: gpio
    function: read
    pin: 17 # GPIO Pin 17 auslesen
    # Rückgabewert: false = nicht begrenzt, true = begrenzt
  ```

  Weitere Details zum GPIO-Plugin findest du in der [Plugin-Dokumentation](/de/reference/plugins#gpio).

* MQTT

  Wenn die Steuerbox oder ein Gateway MQTT-Nachrichten sendet:

  ```yaml
  type: relay
  maxPower: 11340 # Beispiel für 3 SteuVE mit Gleichzeitigkeitsfaktor 0,9
  limit:
    source: mqtt
    topic: hems/limit/status
    # Erwartete Werte: 0/false = normal, 1/true = begrenzt
  ```

* HTTP-API

  Für Steuerboxen mit REST-API:

  ```yaml
  type: relay
  maxPower: 13440 # Beispiel für 4 SteuVE mit Gleichzeitigkeitsfaktor 0,8
  limit:
    source: http
    uri: http://steuerbox.local/api/limit
    jq: .limited # JSON-Pfad zum Boolean-Wert
  ```

* Modbus

  Wenn die Steuerbox oder ein Gateway das Leistungslimit via Modbus bereitstellt:

  ```yaml
  type: relay
  maxPower: 4200 # Beispiel für 1 SteuVE
  limit:
    source: modbus
    uri: 192.168.179.200:4703 # Beispiel: am 2. S0-Zähler einer cFos Power Brain solar Wallbox
    id: 3 # Modbus Slave-ID
    timeout: 5s
    register:
      type: holding
      decode: uint16
      address: 8056
    # Rückgabewert: 0 = nicht begrenzt, 1 = begrenzt
  ```

### FNN-Steuerbox

Steuerboxen nach FNN-Standard signalisieren Dimmung und Abregelung über separate Schaltkontakte. Dimmung des Verbrauchs (W4) und Abregelung der Einspeisung (W3, S2, S1) arbeiten unabhängig voneinander. Mindestens eines der Signale `w4` oder `w3` muss konfiguriert sein.

| Attribut          | Typ        | Erforderlich | Beschreibung                                                                         |
| ----------------- | ---------- | ------------ | ------------------------------------------------------------------------------------ |
| `maxDimPower`     | `int` (W)  | ja¹          | Verbrauchslimit während das Dimmsignal (W4) aktiv ist.                               |
| `maxCurtailPower` | `int` (W)  | ja²          | Installierte PV-Leistung, Basiswert für die Abregelungsstufen.                       |
| `w4`              | Plugin     | nein         | Liest das Dimmsignal. Begrenzt den Verbrauch auf `maxDimPower`.                      |
| `w3`              | Plugin     | nein         | Liest das Abregelungssignal. Begrenzt die Einspeisung auf 0% von `maxCurtailPower`.  |
| `s2`              | Plugin     | nein         | Liest das Abregelungssignal. Begrenzt die Einspeisung auf 30% von `maxCurtailPower`. |
| `s1`              | Plugin     | nein         | Liest das Abregelungssignal. Begrenzt die Einspeisung auf 60% von `maxCurtailPower`. |
| `interval`        | `duration` | nein         | Abfrageintervall für die Schaltkontakte. Standard `10s`.                             |

¹ erforderlich, wenn `w4` konfiguriert ist, ² erforderlich, wenn `w3` konfiguriert ist.

```yaml
type: fnn
maxDimPower: 4200 # Verbrauchslimit während Dimmung (in Watt)
maxCurtailPower: 10000 # Installierte PV-Leistung, Basis für Abregelungsstufen (in Watt)
w4:
  source: gpio
  function: read
  pin: 17 # GPIO-Pin 17 auslesen
  # Rückgabewert: false = normal, true = aktiv
w3:
  source: gpio
  function: read
  pin: 27
s2:
  source: gpio
  function: read
  pin: 22
s1:
  source: gpio
  function: read
  pin: 23
```

### EEBus

Die digitale Anbindung über das EEBus-Protokoll. Die Steuerbox kommuniziert direkt mit deiner evcc-Instanz und übermittelt das Leistungslimit automatisch. Steuerbox und evcc müssen einmalig [gekoppelt](/de/external-limit#eebus-pairing) werden.

| Attribut                              | Typ        | Erforderlich | Beschreibung                                                |
| ------------------------------------- | ---------- | ------------ | ----------------------------------------------------------- |
| `ski`                                 | `string`   | ja           | SKI (Subject Key Identifier) der Steuerbox.                 |
| `contractualConsumptionNominalMax`    | `int` (W)  | nein         | Vertragliche maximale Bezugsleistung.                       |
| `failsafeConsumptionActivePowerLimit` | `int` (W)  | nein         | Failsafe-Limit für die Bezugsleistung.                      |
| `productionNominalMax`                | `int` (W)  | nein         | Installierte Generatorleistung (Wp).                        |
| `failsafeProductionActivePowerLimit`  | `int` (W)  | nein         | Failsafe-Limit für die Einspeiseleistung.                   |
| `failsafeDurationMinimum`             | `duration` | nein         | Failsafe-Mindestdauer, z. B. `2h`.                          |
| `passthrough`                         | Plugin     | nein         | Leitet das Begrenzungssignal an ein externes System weiter. |

```yaml
type: eebus
ski: "1234-5678-90AB-CDEF" # SKI der Steuerbox
```

### Custom

Die generische Integration für Steuerungssysteme, die dynamische Limitwerte statt Schaltkontakten liefern. Verbrauchslimit und Abregelung der Einspeisung werden über Plugins ausgelesen und arbeiten unabhängig voneinander. Mindestens eines der Attribute `maxConsumptionPower` oder `curtailedPercent` muss konfiguriert sein.

| Attribut               | Typ        | Erforderlich | Beschreibung                                                                                                |
| ---------------------- | ---------- | ------------ | ----------------------------------------------------------------------------------------------------------- |
| `maxConsumptionPower`  | Plugin     | nein¹        | Liest das Gesamtleistungslimit in Watt. `0` = kein Limit.                                                   |
| `curtailedPercent`     | Plugin     | nein¹        | Liest die erlaubte Einspeisung in Prozent von `productionNominalMax` (0 bis 100). `100` = keine Abregelung. |
| `productionNominalMax` | `int` (W)  | nein²        | Installierte Generatorleistung (Wp).                                                                        |
| `interval`             | `duration` | nein         | Abfrageintervall für die Plugins. Standard `10s`.                                                           |

¹ mindestens eines von beiden ist erforderlich, ² erforderlich, wenn `curtailedPercent` konfiguriert ist.

```yaml
type: custom
maxConsumptionPower:
  source: http
  uri: http://steuerbox.local/api/limit
  jq: .maxPower # Leistungslimit in Watt, 0 = kein Limit
curtailedPercent:
  source: mqtt
  topic: hems/curtail/percent # Erlaubte Einspeisung in Prozent, 100 = keine Abregelung
productionNominalMax: 10000 # Installierte Generatorleistung (Wp)
```

## Einspeisebegrenzer

Ein benutzerdefinierter Einspeisebegrenzer begrenzt die Einspeisung der PV-Anlage auf Anforderung des Netzbetreibers (§ 9 EEG), wenn der Wechselrichter nicht über seine [Zähler](#meter)-Konfiguration abgeregelt werden kann. Wähle dazu in der Oberfläche unter **Konfiguration → Netzanschluss → Einspeisebegrenzung hinzufügen** die Option **Benutzerdefiniertes Gerät**. Siehe auch die [`curtailers`-Konfigurationsreferenz](/de/reference/configuration/curtailers) und [Externe Begrenzung](/de/external-limit#curtailment-devices).

Das Gerät erhält die erlaubte Einspeisung in Prozent der installierten Generatorleistung und muss sie am Wechselrichter umsetzen. `100` bedeutet kein Limit.

### Attribute

| Attribut    | Typ    | Erforderlich | Beschreibung                                                                                                                                                |
| ----------- | ------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `curtail`   | Plugin | ja           | Setzt das Einspeiselimit in % der Nennleistung der Erzeugung (0 bis 100). Muss Schreibzugriff unterstützen.                                                 |
| `curtailed` | Plugin | ja           | Liest das aktuelle Einspeiselimit in %. Kann das Gerät es nicht liefern, wird das [`error`](/de/reference/plugins#error)-Plugin verwendet (siehe Beispiel). |

### Beispiele

* HTTP

  ```yaml
  curtail:
    source: http
    uri: http://inverter.local/api/limit?percent={{ .curtail }}
    method: POST
  curtailed:
    source: http
    uri: http://inverter.local/api/limit
    jq: .percent
  ```

* Modbus

  Der Wechselrichter kann sein Limit nicht zurückmelden, `curtailed` liefert daher `ErrNotAvailable` und das Limit wird bei jeder Änderung geschrieben.

  ```yaml
  curtail:
    source: modbus
    uri: 192.168.0.10:502
    id: 1
    register:
      type: writesingle
      address: 40016
      encoding: uint16
  curtailed:
    source: error
    error: ErrNotAvailable
  ```

## Benachrichtigungsdienst

Ein benutzerdefinierter Benachrichtigungsdienst verarbeitet [Benachrichtigungen](/de/notifications) über ein beliebiges [Plugin](/de/reference/plugins) mit Schreibzugriff, z. B. ein Shell-Skript, einen HTTP-Aufruf oder eine MQTT-Nachricht. Wähle dazu in der Oberfläche unter **Konfiguration → Benachrichtigungen → Dienste** die Option **Benutzerdefinierter Dienst**.

Die Nachricht wird dem Plugin im Parameter `${send}` (bzw. als Template-Parameter `{{.send}}`) bereitgestellt.

### Konfiguration

| Attribut   | Typ      | Erforderlich | Beschreibung                                                                      |
| ---------- | -------- | ------------ | --------------------------------------------------------------------------------- |
| `send`     | Plugin   | ja           | Plugin, das für jede Nachricht aufgerufen wird. Muss Schreibzugriff unterstützen. |
| `encoding` | `string` | nein         | Format des Werts in `${send}`. Siehe unten.                                       |

Die möglichen Werte für `encoding` sind:

| Encoding | Inhalt von `${send}`                                                                                                         |
| -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `json`   | JSON-Objekt `{ "msg": msg, "title": title }`. Das Feld `title` wird nur hinzugefügt, wenn es für das Ereignis definiert ist. |
| `csv`    | `title` und `msg` als kommaseparierte Liste                                                                                  |
| `tsv`    | Wie `csv`, jedoch mit Tabulator als Trennzeichen                                                                             |
| `title`  | Nur der Titel                                                                                                                |
| (keins)  | Nur die Nachricht (`msg`)                                                                                                    |

### Beispiel

```yaml
messaging:
  events:
    connect:
      title: "${vehicleTitle} verbunden"
      msg: "${vehicleTitle} wurde verbunden (Lademodus: ${mode})."
  services:
    - type: custom
      encoding: json
      send:
        # Plugin-Typ
        source: script
        # Plugin-spezifische Konfiguration;
        # {{.send}} enthält die JSON-Nachricht
        cmd: /usr/local/bin/evcc_message "{{.send}}"
```

In diesem Beispiel wird ein Shell-Skript (`cmd`) mit dem Argument `{"title": "...", "msg": "..."}` aufgerufen.