diff --git a/AGENTS.md b/AGENTS.md
index d7bb20267..8e93619b6 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -83,6 +83,7 @@ Everything else is hand-written:
- **Always write "evcc" in lowercase** — even at the beginning of sentences
- Never use "EVCC", "Evcc", or other variations
- Prefer "your evcc instance" over a bare "evcc" when referring to a running instance
+- Don't mention "evcc" unless necessary for context — within evcc docs the reader already knows. Drop self-referential fluff like "another strength of evcc", "evcc ships with", "the evcc UI"
### Language & Tone
@@ -201,9 +202,16 @@ Everything else is hand-written:
- Use locale-prefixed absolute paths (`/en/...`, `/de/...`) for clarity
- Keep anchor names (`#section`) consistent between translations
-- **Create explicit anchors** with `{#anchor-name}` on headings instead of relying on auto-generated ones
+- **Create explicit anchors** on headings instead of relying on auto-generated ones
- Auto-generated anchors change with heading text and differ between languages
- - Example: `### Vehicle Detection {#vehicle}` ensures stable, language-independent linking
+ - In `.md` files use the compact form: `### Vehicle Detection {#vehicle}`
+ - In `.mdx` files use a raw HTML anchor element on the line above (MDX parses `{...}` as a JSX expression, so the compact form breaks the build):
+
+ ```mdx
+
+
+ ### Vehicle Detection
+ ```
### Documentation Best Practices
diff --git a/astro.config.mjs b/astro.config.mjs
index 257365508..861c83a6b 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -6,12 +6,16 @@ import starlightBlog from "starlight-blog";
import starlightLlmsTxt from "starlight-llms-txt";
import starlightOpenAPI, { openAPISidebarGroups } from "starlight-openapi";
import mermaid from "astro-mermaid";
+import remarkHeadingId from "remark-heading-id";
export default defineConfig({
site: "https://docs.evcc.io",
trailingSlash: "never",
build: {
format: "directory",
},
+ markdown: {
+ remarkPlugins: [remarkHeadingId],
+ },
redirects: {
"/": "/en",
"/docs": "/de",
@@ -20,8 +24,6 @@ export default defineConfig({
"/en/docs/Home": "/en",
"/docs/reference/api": "/en/integrations/rest-api",
"/en/docs/reference/api": "/en/integrations/rest-api",
- "/de/reference/plugins": "/de/plugins",
- "/en/reference/plugins": "/en/plugins",
},
integrations: [
mermaid({
@@ -137,21 +139,22 @@ export default defineConfig({
link: "/heating",
},
{
- label: "Plugins",
- link: "/plugins",
+ label: "User-defined devices",
+ translations: { de: "Benutzerdefinierte Geräte" },
+ link: "/user-defined-devices",
},
],
},
- {
- label: "Features",
- translations: { de: "Funktionen" },
- items: [{ autogenerate: { directory: "features", collapsed: true } }],
- },
{
label: "Tariffs & forecasts",
translations: { de: "Tarife & Vorhersagen" },
link: "/tariffs",
},
+ {
+ label: "Features",
+ translations: { de: "Funktionen" },
+ items: [{ autogenerate: { directory: "features", collapsed: true } }],
+ },
{
label: "Integrations",
translations: { de: "Integrationen" },
@@ -182,6 +185,7 @@ export default defineConfig({
},
],
},
+ { label: "Plugins", slug: "reference/plugins" },
{ label: "Modbus", slug: "reference/modbus" },
{
label: "CLI",
diff --git a/src/components/UserDefinedHint.astro b/src/components/UserDefinedHint.astro
new file mode 100644
index 000000000..1a6886bbf
--- /dev/null
+++ b/src/components/UserDefinedHint.astro
@@ -0,0 +1,36 @@
+---
+interface Props {
+ lang: "de" | "en";
+ kind?: "device" | "service";
+}
+
+const { lang, kind = "device" } = Astro.props;
+
+const issuesUrl = "https://github.com/evcc-io/evcc/issues/new/choose";
+const userDefinedUrl = `/${lang}/user-defined-devices`;
+
+const t = lang === "de"
+ ? {
+ title: "Dein Gerät nicht dabei?",
+ titleService: "Dein Dienst nicht dabei?",
+ body:
+ kind === "service"
+ ? `Eröffne einen Feature Request auf GitHub oder definiere einen eigenen Dienst über das Plugin-System.`
+ : `Eröffne einen Feature Request auf GitHub oder definiere ein eigenes Gerät über das Plugin-System.`,
+ }
+ : {
+ title: "Device not in the list?",
+ titleService: "Service not in the list?",
+ body:
+ kind === "service"
+ ? `Open a feature request on GitHub or build your own user-defined service via the plugin system.`
+ : `Open a feature request on GitHub or build your own user-defined device via the plugin system.`,
+ };
+
+const title = kind === "service" ? t.titleService : t.title;
+---
+
+
diff --git a/src/content/docs/de/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx b/src/content/docs/de/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
index a5323bb2b..ab8061295 100644
--- a/src/content/docs/de/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
+++ b/src/content/docs/de/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
@@ -107,7 +107,7 @@ Zudem ist das Authentifizierungssystem gesperrt und damit auch alle geschützten
Über die Konfigurationsoberfläche konnten bisher bereits Fahrzeuge, Zähler, PV-, Batteriesysteme, Wallboxen, Tarife, schaltbare Steckdosen und Wärmepumpen angelegt werden.
Basis dafür ist unsere große Bibliothek an Geräte-Templates für inzwischen über 550 Produkte.
-Eine weitere Stärke von evcc ist das [flexible Plugin System](/de/plugins).
+Eine weitere Stärke ist das [flexible Plugin System](/de/reference/plugins).
Damit können auch exotische Geräte und Integrationen mithilfe von HTTP, Modbus, Script, MQTT, ... verbunden werden.
Diese benutzerdefinierten Geräte (`type: custom`) mussten bislang über die `evcc.yaml` konfiguriert werden.
Nun ist dies auch über die UI möglich – komfortabel mit Syntax-Highlighting, Validierung und Prüfen-Funktion.
diff --git a/src/content/docs/de/faq.mdx b/src/content/docs/de/faq.mdx
index e7622fea8..34d89de4d 100644
--- a/src/content/docs/de/faq.mdx
+++ b/src/content/docs/de/faq.mdx
@@ -215,7 +215,7 @@ Wie du das Log aufrufst, findest du in der [Installation](/de/installation) unte
### MQTT plugin gibt `outdated` Warnung
-Bei der Nutzung des [MQTT plugins](devices/plugins#mqtt) kann über den `timeout` parameter gesteuert werden, wie lange ein Wert der per MQTT erhalten wurde, gültig ist.
+Bei der Nutzung des [MQTT plugins](/de/reference/plugins#mqtt) kann über den `timeout` parameter gesteuert werden, wie lange ein Wert der per MQTT erhalten wurde, gültig ist.
Wenn kein neuer Wert innerhalb dieser Zeit kommt, ist der Wert für evcc `outdated`.
Wichtig ist, dass hier eine Einheit mit angegeben werden muss, also z.B. `timeout: 30s`
diff --git a/src/content/docs/de/features/external-control.mdx b/src/content/docs/de/features/external-control.mdx
index 962a95426..25c8dc257 100644
--- a/src/content/docs/de/features/external-control.mdx
+++ b/src/content/docs/de/features/external-control.mdx
@@ -86,7 +86,7 @@ limit:
# Rückgabewert: false = nicht begrenzt, true = begrenzt
```
-Weitere Details zum GPIO-Plugin findest du in der [Plugin-Dokumentation](/de/plugins#gpio).
+Weitere Details zum GPIO-Plugin findest du in der [Plugin-Dokumentation](/de/reference/plugins#gpio).
@@ -249,4 +249,4 @@ Diese Funktion wird weiter ausgebaut und entsprechende Zähler werden in der [Ge
## Weiterführende Informationen
- [Lastmanagement](./loadmanagement) - Grundlagen der Lastverteilung
-- [Plugins](../plugins) - Erweiterte Plugin-Konfigurationen
+- [Plugins](/de/reference/plugins) - Erweiterte Plugin-Konfigurationen
diff --git a/src/content/docs/de/index.mdx b/src/content/docs/de/index.mdx
index 0af097654..782593e74 100644
--- a/src/content/docs/de/index.mdx
+++ b/src/content/docs/de/index.mdx
@@ -25,7 +25,7 @@ evcc läuft lokal auf einem Raspberry Pi oder NAS - keine Cloud erforderlich.
- [Wallboxen und schaltbaren Steckdosen](/de/chargers)
- [Erzeugungsanlagen, Batteriespeichern und Energiemessgeräten (Zähler)](/de/meters)
- [Fahrzeugen](/de/vehicles)
-- [Plugins](/de/plugins) um nahezu beliebige Wallboxen / Zähler / Fahrzeuge hinzuzufügen: Modbus, HTTP, MQTT, Javascript, WebSockets und Shell Skripte
+- [Plugins](/de/reference/plugins) um nahezu beliebige Wallboxen / Zähler / Fahrzeuge hinzuzufügen: Modbus, HTTP, MQTT, Javascript, WebSockets und Shell Skripte
- Status [Benachrichtigungen](/de/reference/configuration/messaging) über [Telegram](https://telegram.org), [PushOver](https://pushover.net) und [viele mehr](https://containrrr.dev/shoutrrr/)
- Datenanalyse mit [InfluxDB](https://www.influxdata.com) und [Grafana](https://grafana.com/grafana/)
- Stufenlose Regelung der Ladeströme mit unterstützten Wallboxen (z. B. bei smartWB als [OLC](https://board.evse-wifi.de/viewtopic.php?f=16&t=187) bezeichnet)
diff --git a/src/content/docs/de/installation/considerations.mdx b/src/content/docs/de/installation/considerations.mdx
index 7eb1919d4..8111dc638 100644
--- a/src/content/docs/de/installation/considerations.mdx
+++ b/src/content/docs/de/installation/considerations.mdx
@@ -30,7 +30,7 @@ Letzteres ist meist dann der Fall, wenn die Solaranlage mit einem Speicher ausge
Der Zähler muss sich elektronisch auslesen lassen.
Schau einfach, mal unter [Geräte > PV, Batterie, Netz, Zähler](/de/meters) nach, ob du deine Geräte findest.
-Wenn nicht, kannst du über [Plugins](/de/plugins) auch selbst eine Integration vornehmen.
+Wenn nicht, kannst du selbst eine Integration als [eigenes Gerät](/de/user-defined-devices) vornehmen.
Eine weitere Voraussetzung für das Automatisieren des Überschussladens ist eine steuerbare Wallbox.
Die unterstützten Geräte sind unter [Geräte > Wallboxen](/de/chargers) gelistet.
diff --git a/src/content/docs/de/reference/configuration/chargers.mdx b/src/content/docs/de/reference/configuration/chargers.mdx
index 51c38476c..d19b4f463 100644
--- a/src/content/docs/de/reference/configuration/chargers.mdx
+++ b/src/content/docs/de/reference/configuration/chargers.mdx
@@ -39,7 +39,7 @@ name: wallbox1
Dies ist der evcc spezifische Wallbox Typ, mit Hilfe dessen mit der Wallbox kommuniziert werden kann. Bekannte Wallboxen könne über den Typ `template` eingebunden werden. Den passenden (Template)Typ findet man unter [Geräte - Wallboxen](/de/chargers).
-Für unbekannte Wallboxen (oder aus anderen individuellen Gründen) kann die Standard Implementierung über [Plugins](/de/plugins) genutzt werden.
+Für unbekannte Wallboxen (oder aus anderen individuellen Gründen) kannst du eine [eigene Wallbox](/de/user-defined-devices#charger) definieren.
**Beispiel**:
diff --git a/src/content/docs/de/reference/configuration/hems.md b/src/content/docs/de/reference/configuration/hems.md
index 2e1377072..f166f0bfb 100644
--- a/src/content/docs/de/reference/configuration/hems.md
+++ b/src/content/docs/de/reference/configuration/hems.md
@@ -56,12 +56,12 @@ Gesamtleistungslimit in Watt, das bei aktivem Signal gesetzt wird.
#### `limit`
-[Plugin](../../plugins)-Konfiguration zum Auslesen des Schaltkontakts.
+[Plugin](/de/reference/plugins)-Konfiguration zum Auslesen des Schaltkontakts.
Erwarteter Rückgabewert: `true`/`1` = begrenzt, `false`/`0` = normal.
#### `passthrough`
-Optionale [Plugin](../../plugins)-Konfiguration zum Durchreichen des Begrenzungssignals an ein externes System.
+Optionale [Plugin](/de/reference/plugins)-Konfiguration zum Durchreichen des Begrenzungssignals an ein externes System.
#### `interval`
@@ -101,7 +101,7 @@ Folgende optionale Parameter können für die EEBus-Kommunikation gesetzt werden
#### `passthrough`
-Optionale [Plugin](../../plugins)-Konfiguration zum Durchreichen des Begrenzungssignals an ein externes System.
+Optionale [Plugin](/de/reference/plugins)-Konfiguration zum Durchreichen des Begrenzungssignals an ein externes System.
#### `interval`
diff --git a/src/content/docs/de/reference/configuration/messaging.md b/src/content/docs/de/reference/configuration/messaging.md
index 4d1c026bc..964512cda 100644
--- a/src/content/docs/de/reference/configuration/messaging.md
+++ b/src/content/docs/de/reference/configuration/messaging.md
@@ -158,7 +158,7 @@ Im folgenden werden nun alle erforderlichen Parameter erklärt.
- `email`: Email. Siehe [`email`](#email) Definition
- `shout`: [shoutrrr](https://containrrr.dev/shoutrrr). Siehe [`shout`](#shout) Definition
- `ntfy`: [ntfy](https://ntfy.sh). Siehe [`ntfy`](#ntfy) Definition
-- `custom`: Ermöglicht die Nutzung von allen [Plugins](/de/plugins), die einen Schreibzugriff erlauben. Siehe [`custom`](#custom) Definition.
+- `custom`: Ermöglicht die Nutzung von allen [Plugins](/de/reference/plugins), die einen Schreibzugriff erlauben. Siehe [`custom`](#custom) Definition.
---
@@ -255,7 +255,7 @@ Weitere Informationen sind in der [ntfy Dokumentation](https://docs.ntfy.sh) zu
### `custom`
-Der Typ `custom` ermöglicht es, beliebige [Plugins](/de/plugins) für die Verarbeitung von Nachrichten zu verwenden. Das Plugin muss den Schreibmodus unterstützen. Die Nachricht selbst wird in der Plugin Konfiguration mit dem Parameter `${send}` (bzw. als Template Parameter `{{.send}}`) bereitgestellt.
+Der Typ `custom` ermöglicht es, beliebige [Plugins](/de/reference/plugins) für die Verarbeitung von Nachrichten zu verwenden. Das Plugin muss den Schreibmodus unterstützen. Die Nachricht selbst wird in der Plugin Konfiguration mit dem Parameter `${send}` (bzw. als Template Parameter `{{.send}}`) bereitgestellt.
**Mögliche Werte**:
diff --git a/src/content/docs/de/reference/configuration/meters.md b/src/content/docs/de/reference/configuration/meters.md
index 6ebfb9bae..693a42697 100644
--- a/src/content/docs/de/reference/configuration/meters.md
+++ b/src/content/docs/de/reference/configuration/meters.md
@@ -14,7 +14,7 @@ evcc verwendet eine einheitliche Vorzeichen-Konvention für Leistungs- und Strom
- **Negativ (-)** für ausgehende Energie: Netzeinspeisung, PV-Wechselrichter Ruhestrombedarf, Hausbatterie-Ladung
- **Verbraucher** (Wallbox, Aux-Zähler) sind immer **positiv (+)**
-Liefert das Gerät die Werte mit umgekehrtem Vorzeichen, kann dies in der [Plugin-Konfiguration](/de/plugins) über `scale: -1` korrigiert werden.
+Liefert das Gerät die Werte mit umgekehrtem Vorzeichen, kann dies in der [Plugin-Konfiguration](/de/reference/plugins) über `scale: -1` korrigiert werden.
Die `meters` Konfiguration ist eine Liste von verschiedenen vorhandenen Geräten.
@@ -365,7 +365,7 @@ password: "DasPasswort"
### `custom`
-Standard Implementierung, bei welchem die einzelnen Werte über [Plugins](/de/plugins) definiert werden.
+Standard Implementierung, bei welchem die einzelnen Werte über [Plugins](/de/user-defined-devices#meter) definiert werden.
**Beispiel**:
diff --git a/src/content/docs/de/plugins.mdx b/src/content/docs/de/reference/plugins.mdx
similarity index 66%
rename from src/content/docs/de/plugins.mdx
rename to src/content/docs/de/reference/plugins.mdx
index 8a26e5ec0..01378b23b 100644
--- a/src/content/docs/de/plugins.mdx
+++ b/src/content/docs/de/reference/plugins.mdx
@@ -6,20 +6,20 @@ tableOfContents:
import { Badge } from "@astrojs/starlight/components";
-Plugins können verwendet werden, um Geräte und externe Datenquellen in evcc zu integrieren, für die es keine direkte Unterstützung gibt.
+Plugins lesen und schreiben einzelne Werte an einem Gerät, z. B. eine Leistungsmessung, einen Zielstrom, einen Enable-Befehl.
+Sie treiben die mitgelieferten Geräte-Templates und werden direkt referenziert, wenn du ein [eigenes Gerät](/de/user-defined-devices) vom Typ `type: custom` aufbaust.
+
Plugins können für folgende Kategorien verwendet werden:
-- `meter`: [PV, Batterie, Netz, Zähler](./meters)
-- `charger`: [Wallboxen](./chargers), [Smarte Schalter](./smartswitches), [Wärmepumpen, Heizstäbe](./heating)
-- `vehicle`: [Fahrzeuge](./vehicles)
-- `tariff`: [Tarife, Vorhersagen](../tariffs)
-- `circuit`: [Lastmanagement](../features/loadmanagement)
+- `meter`: [PV, Batterie, Netz, Zähler](/de/meters)
+- `charger`: [Wallboxen](/de/chargers), [Smarte Schalter](/de/smartswitches), [Wärmepumpen, Heizstäbe](/de/heating)
+- `vehicle`: [Fahrzeuge](/de/vehicles)
+- `tariff`: [Tarife, Vorhersagen](/de/tariffs)
+- `circuit`: [Lastmanagement](/de/features/loadmanagement)
Zusätzlich können Plugins auch für die in [Messaging](/de/reference/configuration/messaging) beschriebenen Endpunkte zum Versenden von Lifecycle-Events genutzt werden.
-## Übersicht
-
-### Plugins
+### Plugin-Liste
- [GPIO Plugin](#gpio) - Plugin zum direkten Zugriff auf GPIO-Pins (nur Linux).
- [Go Plugin](#go) - Plugin, das Werte über ein Go Skript bereitstellt oder entgegennimmt.
@@ -32,7 +32,7 @@ Zusätzlich können Plugins auch für die in [Messaging](/de/reference/configura
- [SMA/Speedwire Plugin](#speedwire) - Plugin speziell für SMA Geräte, die mit dem Speedwire Protokoll kommunizieren können.
- [Websocket Plugin](#websocket) - Plugin zum Empfangen von Gerätedaten über einen eigenen Webserver. Kann nur zum Lesen von Daten genutzt werden.
-### Helpers
+### Helper-Liste
- [Calc Plugin](#calc) - Meta-Plugin um Ausgaben von anderen Plugins arithmetisch zu verknüpfen.
- [Combined Plugin](#combined) - Meta-Plugin speziell für `charger` um die booleschen Status-Werte für den angeschlossenen (_plugged_) und ladenden (_charging_) Zustand zu einem einzigen Ladestatus zu kombinieren.
@@ -50,40 +50,24 @@ Zusätzlich können Plugins auch für die in [Messaging](/de/reference/configura
- [Valid Plugin](#valid) - Meta-Plugin um Plugin-Werte basierend auf einer booleschen Validierung bereitzustellen.
- [Watchdog Plugin](#watchdog) - Meta-Plugin zur automatischen Wiederholung von Schreibvorgängen in regelmäßigen Abständen.
-### Syntax
-
-Jedes Plugin besitzt ein individuelles Konfigurationsschema.
-Dabei ist es wichtig zu wissen, ob das Plugin in einem **lesenden** oder **schreibenden** Kontext verwendet wird.
-Einige Konfigurationsparameter machen nur in einem lesenden Kontext Sinn, andere nur, wenn sie im Schreibmodus genutzt werden.
+## Syntax
-Beispielsweise kann über die folgende Konfiguration ein MQTT Plugin als `meter` eingebunden werden, bei dem der aktuelle Stromverbrauch über das spezifizierte MQTT Topic eingelesen wird:
+Ein Plugin wird an ein Attribut eines Geräts gehängt.
+Der Attributname (z. B. `power`, `enable`, `soc`) bestimmt die Rolle; `source` wählt den Plugin-Typ; weitere Schlüssel sind plugin-spezifische Parameter.
-```yaml title="Beispiel: MQTT Plugin für die Leistungswerte eines Strommessgeräts"
-meters:
- - name: imsys
- type: custom
- power:
- source: mqtt
- topic: "home/current/imsys/chn2/raw"
+```yaml
+:
+ source:
+ : ...
+ : ...
```
-Das Schema der Plugin Konfiguration hat dabei immer folgende Struktur:
-
-```yaml {3,5-6,8}
-- name:
- type: custom
- :
- source:
- : ...
- : ...
- ....
- :
- ....
-```
+Jedes Plugin wird entweder in einem **lesenden** oder einem **schreibenden** Kontext verwendet. Einige Parameter sind nur in einem der beiden Modi sinnvoll.
+Die vollständigen Attribut-Listen für Zähler, Wallboxen, Fahrzeuge und Tarife findest du unter [Eigene Geräte](/de/user-defined-devices).
-Dabei steht `` für den Namen des Geräts, `` und `` für eine der unten beschriebenen Geräte-spezifischen Attribute, `` für den Plugin-Typ und ``, `` für Plugin-spezifische Konfigurationen (z.b. `source`, `topic` für Plugins vom Typ `mqtt`)
+
-#### Lesen
+### Lesen
Beim Lesen von Daten mithilfe eines Plugins können sogenannte _Pipelines_ verwendet werden.
Damit können Daten aus der Ausgabe des Plugins fein granular extrahiert werden.
@@ -97,20 +81,24 @@ Mögliche Parameter für die Datenextraktion sind:
- `unpack`: Konvertiert Werte aus anderen Zahlenrepräsentationen, z. B. `hex`.
- `decode`: Dekodiert Binärformate wie `uint32`, `float32` etc.
-##### Bekannte Fehlerwerte
+
+
+#### Bekannte Fehlerwerte
[HTTP](#http)-, [MQTT](#mqtt)- und [Websocket](#websocket)-Plugins können spezielle Fehlerwerte als String zurückgeben.
evcc erkennt diese und wandelt sie in interne Fehlercodes um, anstatt sie als Daten zu behandeln.
Das ist z. B. nützlich für eigene Fahrzeugintegrationen, bei denen die Datenquelle den Zustand des Fahrzeugs kennt.
-- `ErrAsleep` — Fahrzeug schläft. evcc kann entscheiden, ob das Fahrzeug geweckt werden soll.
-- `ErrMustRetry` — Vorgang soll erneut versucht werden (z. B. bei Rate-Limiting).
-- `ErrNotAvailable` — Wert ist nicht verfügbar. evcc behandelt dies als permanenten Fehler bis zum nächsten Neustart.
+- `ErrAsleep`: Fahrzeug schläft. evcc kann entscheiden, ob das Fahrzeug geweckt werden soll.
+- `ErrMustRetry`: Vorgang soll erneut versucht werden (z. B. bei Rate-Limiting).
+- `ErrNotAvailable`: Wert ist nicht verfügbar. evcc behandelt dies als permanenten Fehler bis zum nächsten Neustart.
Wenn ein Plugin z. B. den String `ErrAsleep` als Antwort liefert, erzeugt evcc intern den entsprechenden Fehler.
Das [Error Plugin](#error) nutzt denselben Mechanismus, um einen festen Fehlerwert als Konstante zurückzugeben.
-#### Schreiben
+
+
+### Schreiben
Beim Schreiben können Parameter in der Konfiguration durch Platzhalter ersetzt werden.
Die Daten werden in Form von `${var[:format]}` zur Verfügung gestellt.
@@ -118,356 +106,8 @@ Wenn Format nicht angegeben wird, werden die Daten im Standard %v Go-Format bere
Die Variablen werden mit dem entsprechenden Wert ersetzt, bevor das Plugin ausgeführt wird.
Zusätzlich können sämtliche Funktionen der Go Template Library verwendet werden, um komplexere Datentransformationen durchzuführen.
-Je nach Gerät ([`meter`](#meter), [`charger`](#charger) oder [`vehicle`](#vehicle)) können andere Attribute mit Plugins gelesen oder gesetzt werden.
-
-### Meter
-
-Stromzähler werden in der Konfigurationssektion [`meters`](/de/reference/configuration/meters) konfiguriert.
-Zähler, die unter `meters:` definiert werden, können an verschiedenen Stellen innerhalb der `site` Konfiguration verwendet 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
-- `ext`: weiterer Zähler, bspw. für Lastmanagement oder Datenerfassung
-
-`power` ist das einzig zwingend erforderliche Attribut das in jeder `meter` Definition vorhanden sein muss, alle weiteren Attribute sind optional.
-
-Jedoch unterstützen nicht alle Metertypen alle Pluginattribute:
-
-- `limitsoc` und `batterymode` werden ausschließlich für Batteriezähler genutzt (d.h. für `meter` die in `site.battery` referenziert werden).
-- `currents`, `voltages` und `powers` sind Phasen Attribute, die mit jeweils genau drei Plugin-Konfigurationen (in einem YAML Array) konfiguriert werden müssen und für Netzzähler (`grid`) und Wallboxen (`charge`) verwendet werden können.
-
-Die folgenden Tabellen enthalten alle Attribute, die von Plugins bereitgestellt werden können, wenn sie für `meter` konfiguriert werden.
-Bei der Verwendung der Plugins ist es auch wichtig, dass diese den richtigen Datentyp zurückliefern.
-Um zu dem verlangten Datentypen zu konvertieren, können die in [Lesen](#lesen) beschriebenen Pipelines genutzt werden.
-
-| Attribut | Typ | Erfordert | Kontext | Beschreibung |
-| -------- | ------------------- | --------- | ------------- | --------------------------------------------------------------------------- |
-| power | float | ja | alle | Aktuelle Leistung in W |
-| energy | float | nein | alle | Zählerstand in kWh |
-| maxpower | int | nein | `pv` (hybrid) | Maximale AC-Leistung in W |
-| 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). |
-
-**Beispiel**
-
-In diesem Beispiel wird die Konfiguration eines Meters um die aktuelle elektrische Gridleistung über einen HTTP-Aufruf abgefragt:
-
-```yaml
-meters:
- - name: volkszaehler
- type: custom
- power:
- source: http
- uri: http://zaehler.network.local:8080/api/data.json?from=now
- jq: .data.tuples[0][1]
-
-site:
- meters:
- grid: volkszaehler
- ...
- ...
-```
-
-Neben den Attributen, die Plugins zur lesenden Auswertung bereitstellen, werden folgende Attribute von evcc genutzt, um Aktionen zu triggern:
-
-| 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. |
-| batterymode | int | nein | `battery` | Setze Lademodus direkt (1: normal, 2: hold, 3: charge) |
-
-### Charger
-
-Wallboxen vom Typ `custom` haben folgende Attribute die ausgelesen werden können:
-
-| 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 |
-| 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). |
-
-Für Wärmepumpen-spezifische Charger-Typen (`heatpump`, `sgready`, `sgready-relay`) gelten andere Plugin-Attribute, siehe [Wärmepumpen](#charger-heating).
-
-#### Allgemeine Konfigurationsoptionen
-
-Zusätzlich zu den Plugin-Attributen können folgende Konfigurationsoptionen direkt am Charger gesetzt werden:
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| ------------ | -------- | --------- | --------------------------------------------------------------- |
-| icon | string | nein | Icon für die Darstellung in der Benutzeroberfläche |
-| features | []string | nein | Feature-Flags für spezielle Charger-Eigenschaften (siehe unten) |
-| standbypower | int | nein | Standby-Leistung in W (für `switchsocket` Typ) |
-
-##### Feature-Flags
-
-Über das `features` Array können spezielle Eigenschaften des Chargers aktiviert werden:
-
-| 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. |
-| switchdevice | Gerät kann nur ein- und ausgeschaltet werden (keine stufenlose Stromregelung). Min/Max-Strom-Einstellungen und der `Min+PV`-Modus werden ausgeblendet. |
-
-##### Häufige Kombinationen
-
-Folgende Kombinationen kannst du als Vorlage für eigene `type: custom` Konfigurationen nutzen.
-Sie entsprechen den vorkonfigurierten Templates in evcc.
-
-**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)
-```
-
-**Beispiel**
-
-Dieses Beispiel zeigt, wie man über das Modbus-Plugin den Ladestatus (ladend/nicht ladend) eines Chargers abfragen kann:
-
-```yaml
-chargers:
- - name: icharge
- type: custom
- features:
- - integrateddevice
- enabled:
- source: modbus
- id: 4711
- uri: modbus.local:502
- rtu: false
- register:
- address: 100
- type: holding
- decode: uint16
-```
-
-Neben den read-only Werten können über Plugins auch Aktionen getriggert oder Konfigurationswerte gesetzt werden:
-
-| 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 |
-
-**Beispiel**
-
-Dieses Beispiel schaltet eine Tasmota-Steckdose über eine MQTT Nachricht gesendet an:
-
-```yaml
-chargers:
- - name: unu-charger
- type: custom
- enable:
- source: mqtt
- broker: mosquitto.local:883
- topic: cmd/unu-switch/Power
- payload: ON
-```
-
-#### Wärmepumpen
-
-Für Wärmepumpen und vergleichbare Heizgeräte gibt es eigene Charger-Typen mit jeweils eigenen Plugin-Attributen.
-Die vollständige Einrichtung ist unter [Wärmepumpen, Heizstäbe](./heating) beschrieben.
-
-Allen drei Typen gemeinsam sind die optionalen Mess-Attribute:
-
-| 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 |
-
-**`type: heatpump`**: Wärmepumpe mit Leistungsvorgabe.
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| ----------- | ----- | --------- | ----------------------------------- |
-| setmaxpower | int | ja | Setze maximale Heizleistung in W |
-| getmaxpower | float | nein | Aktuelle maximale Heizleistung in W |
-
-**`type: sgready`**: Wärmepumpe mit SG-Ready Schnittstelle.
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| ----------- | --- | --------- | ------------------------------------------------------- |
-| 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 |
-
-**`type: sgready-relay`**: Wärmepumpe gesteuert über Relais-Kontakte.
-Die Sub-Charger werden über typisierte Verweise statt Plugins eingebunden.
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| -------- | ------------- | --------- | ------------------------------------- |
-| boost | charger-typed | ja | Relais für den SG-Ready Boost-Kontakt |
-| dim | charger-typed | nein | Relais für den SG-Ready Dim-Kontakt |
-
-### Vehicle
-
-Fahrzeugparameter können ebenfalls über Plugins ausgelesen werden.
-
-| 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) |
-
-#### Allgemeine Konfigurationsoptionen
-
-Folgende Konfigurationsoptionen können direkt am Fahrzeug gesetzt werden:
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| -------- | -------- | --------- | ---------------------------------------------------------------- |
-| title | string | nein | Anzeigename des Fahrzeugs in der Benutzeroberfläche |
-| icon | string | nein | Icon für die Darstellung in der Benutzeroberfläche |
-| capacity | float | nein | Batteriekapazität in kWh |
-| features | []string | nein | Feature-Flags für spezielle Fahrzeug-Eigenschaften (siehe unten) |
-
-##### Feature-Flags
-
-| 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. |
-
-**Beispiel**
-
-Im folgenden Beispiel wird die aktuelle Reichweite des Fahrzeugs aus MQTT Nachrichten gelesen:
-
-```yaml
-vehicles:
- - name: mazda
- type: custom
- title: Grüner Mazda
- capacity: 50
- features:
- - coarsecurrent
- range:
- source: mqtt
- topic: mazda2mqtt/c53/chargeInfo/drivingRangeKm
-```
-
-Zusätzlich können spezielle Kommandos über Plugins an das Fahrzeug geschickt werden:
-
-| Attribut | Typ | Erfordert | Beschreibung |
-| ------------ | ---- | --------- | ------------------------------ |
-| wakeup | bool | nein | Fahrzeug aufwecken |
-| chargeenable | bool | nein | Starte/stoppe den Ladevorgang |
-| maxcurrent | int | nein | Setze maximalen Ladestrom in A |
-
-**Beispiel**
-
-Um ein Auto über einen HTTP Ping aufzuwecken, um weiter Abfragen zu senden, kann wie im folgenden Beispiel das HTTP-Plugin genutzt werden:
-
-```yaml
-vehicles:
- - name: model-y
- type: custom
- wakeup:
- source: http
- uri: http://teslalogger.local:5000/command/08154711/wake_up
-```
-
-#### Lademodus bei Fahrzeugerkennung
-
-Bei benutzerdefinierten Fahrzeugen kann der Lademodus beim Erkennen des Fahrzeugs mit `onIdentify` konfiguriert werden.
-Dies ist nützlich, wenn der gewünschte Lademodus automatisch gesetzt werden soll, sobald das Fahrzeug identifiziert wird.
-
-**Beispiel**:
-
-```yaml
-vehicles:
- - name: my-car
- type: custom
- soc:
- source: mqtt
- topic: car/soc
- onIdentify:
- mode: pv
-```
-
-Verfügbare Modi sind: `off`, `now`, `minpv`, `pv`.
-
-### Tarife & Vorhersagen
-
-Siehe [Tarife & Vorhersagen > Eigenes Plugin](../tariffs#plugin) für die vollständige Konfiguration.
-
-#### Feature-Flags
-
-| 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). |
-
-```yaml
-tariffs:
- grid:
- type: custom
- features:
- - cacheable
- # ... weitere Attribute
-```
-
-### Lastmanagement
-
-:::note[Work in Progress]
-...
-:::
-
-### Messaging
-
-:::note[Work in Progress]
-...
-:::
-
## Plugins
-Folgende Plugins stehen zur Verfügung und können für die oben beschriebenen Attribute konfiguriert werden, um eine flexible Anbindung an die verschiedenen Systeme zu ermöglichen.
-
### GPIO
Das `gpio` Plugin ermöglicht den direkten Zugriff auf GPIO-Pins (General Purpose Input/Output) unter Linux.
@@ -558,15 +198,15 @@ Wenn das `go` Plugin zum Schreiben verwendet wird, wird der zu schreibende Wert
**Beispiel Schreiben**:
```yaml
-charger:
- - type: custom
- maxcurrent:
- source: go
- script: |
- fmt.Printf("Setze Ladestrom: %d A\n", maxcurrent)
- // maxcurrent Variable ist automatisch verfügbar
+maxcurrent:
+ source: go
+ script: |
+ fmt.Printf("Setze Ladestrom: %d A\n", maxcurrent)
+ // maxcurrent Variable ist automatisch verfügbar
```
+
+
#### Input- und Output-Transformationen
Die `go` und `js` Plugins unterstützen `in` und `out` Parameter, um Daten aus anderen Quellen als Variablen im Script zu verwenden bzw. das Ergebnis an andere Plugins weiterzuleiten.
@@ -607,23 +247,20 @@ power:
Mit dem `out` Parameter kann das Ergebnis eines Scripts an andere Plugins weitergeleitet werden.
Dies ist besonders nützlich im Schreibkontext, wenn das Script-Ergebnis z. B. per MQTT oder HTTP weiterverarbeitet werden soll.
-Jeder Eintrag benötigt `name`, `type` und `config` — analog zu `in`.
+Jeder Eintrag benötigt `name`, `type` und `config`, analog zu `in`.
```yaml
-chargers:
- - name: smart-heater
- type: custom
- maxcurrent:
- source: go
- script: |
- watts := maxcurrent * 230
- watts
- out:
- - name: watts
- type: float
- config:
- source: mqtt
- topic: heater/target_power
+maxcurrent:
+ source: go
+ script: |
+ watts := maxcurrent * 230
+ watts
+ out:
+ - name: watts
+ type: float
+ config:
+ source: mqtt
+ topic: heater/target_power
```
### HTTP
@@ -746,12 +383,10 @@ Wenn das `js` Plugin zum Schreiben verwendet wird, wird der zu schreibende Wert
**Beispiel Schreiben**:
```yaml
-charger:
- - type: custom
- maxcurrent:
- source: js
- script: |
- console.log(maxcurrent);
+maxcurrent:
+ source: js
+ script: |
+ console.log(maxcurrent);
```
Das `js` Plugin unterstützt dieselben [Input- und Output-Transformationen](#transformations) (`in`/`out`) wie das `go` Plugin.
@@ -863,6 +498,8 @@ energy:
Die Abfrage muss einen einzelnen numerischen Wert zurückgeben.
Bei Vektor-Ergebnissen muss genau eine Metrik enthalten sein.
+
+
### Shell Script
Das `script` Plugin führt externe Skripte zum Lesen oder Aktualisieren von Daten aus. Das Plugin ist hilfreich um jede Art von externer Funktionalität einzubinden.
@@ -883,6 +520,8 @@ cmd: /home/user/my-script.sh ${enable:%b} # format boolean enable as 0/1
timeout: 5s
```
+
+
### SMA/Speedwire
Das `sma` Plugin bietet eine Schnittstelle zu SMA Geräten, welche das Speedwire Protokoll beherrschen.
@@ -1294,6 +933,8 @@ setmode:
encoding: int16
```
+
+
### Meter
Das `meter` Plugin ermöglicht es, ein anderes Messgerät als Datenquelle zu verwenden.
diff --git a/src/content/docs/de/user-defined-devices.mdx b/src/content/docs/de/user-defined-devices.mdx
new file mode 100644
index 000000000..208bf8f82
--- /dev/null
+++ b/src/content/docs/de/user-defined-devices.mdx
@@ -0,0 +1,502 @@
+---
+title: Benutzerdefinierte Geräte
+tableOfContents:
+ maxHeadingLevel: 4
+---
+
+import { Tabs, TabItem } from "@astrojs/starlight/components";
+
+Beim Anlegen einer Wallbox, eines Heizgeräts, eines Netzzählers, einer Batterie, einer PV-Anlage, eines weiteren Verbrauchers, eines Fahrzeugs, eines Tarifs 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
+- `ext`: Weiterer Zähler, z. B. für Lastmanagement oder Datenerfassung
+
+`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`).
+- `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 |
+| `maxpower` | `int` | nein | `pv` (hybrid) | Maximale AC-Leistung in W |
+| `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). |
+
+### 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. |
+| `batterymode` | `int` | nein | `battery` | Setze Lademodus direkt (1: normal, 2: hold, 3: charge) |
+
+### Beispiel
+
+Lese die aktuelle Netzleistung über einen HTTP-Endpunkt.
+
+```yaml
+power:
+ source: http
+ uri: http://zaehler.network.local:8080/api/data.json?from=now
+ jq: .data.tuples[0][1]
+```
+
+
+
+## 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 |
+| `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. |
+| `switchdevice` | Gerät kann nur ein- und ausgeschaltet werden (keine stufenlose Stromregelung). Min/Max-Strom-Einstellungen und der `Min+PV`-Modus werden ausgeblendet. |
+
+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.
+
+
+
+
+**`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 |
+
+
+
+
+**`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 |
+
+
+
+
+**`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: pv
+```
+
+Verfügbare Modi sind: `off`, `now`, `minpv`, `pv`.
+
+
+
+## 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` oder `solar`. Bestimmt die Einheit der zurückgegebenen Werte: Preis in konfigurierter Währung pro kWh, CO₂-Intensität in g/kWh, Solar-Vorhersage in W. |
+| `charges` | `float` | nein | Fester Aufschlag pro kWh, der zu jedem Wert addiert wird. Standard `0`. |
+| `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.
diff --git a/src/content/docs/en/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx b/src/content/docs/en/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
index 11af4c616..cac28c671 100644
--- a/src/content/docs/en/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
+++ b/src/content/docs/en/blog/2025/07/30/highlights-config-ui-feedin-ai.mdx
@@ -107,7 +107,7 @@ Additionally, the authentication system is disabled, and thus all protected func
Through the configuration interface, vehicles, meters, PV/battery systems, EV chargers, tariffs, smart switches, and heat pumps could already be created.
This is based on our large library of device templates for now over 550 products.
-Another strength of evcc is the [flexible plugin system](/en/plugins).
+Another strength is the [flexible plugin system](/en/reference/plugins).
This allows even exotic devices and integrations to be connected using HTTP, Modbus, Script, MQTT, etc.
These user-defined devices (`type: custom`) previously had to be configured via `evcc.yaml`.
Now this is also possible via the UI – conveniently with syntax highlighting, validation, and test function.
diff --git a/src/content/docs/en/faq.mdx b/src/content/docs/en/faq.mdx
index 583f3629c..1237bbad5 100644
--- a/src/content/docs/en/faq.mdx
+++ b/src/content/docs/en/faq.mdx
@@ -223,7 +223,7 @@ How to access the log is described in [Installation](/en/installation) under you
### MQTT plugin shows `outdated` warning
-When using the [MQTT plugin](devices/plugins#mqtt), you can control how long a value received via MQTT remains valid using the `timeout` parameter.
+When using the [MQTT plugin](/en/reference/plugins#mqtt), you can control how long a value received via MQTT remains valid using the `timeout` parameter.
If no new value arrives within this time, the value is considered `outdated` by evcc.
It is important to specify a unit here, e.g. `timeout: 30s`.
diff --git a/src/content/docs/en/features/external-control.mdx b/src/content/docs/en/features/external-control.mdx
index 21ac3b38f..e450e0b16 100644
--- a/src/content/docs/en/features/external-control.mdx
+++ b/src/content/docs/en/features/external-control.mdx
@@ -86,7 +86,7 @@ limit:
# Return value: false = not limited, true = limited
```
-For more details on the GPIO plugin, see the [plugin documentation](/en/plugins#gpio).
+For more details on the GPIO plugin, see the [plugin documentation](/en/reference/plugins#gpio).
@@ -251,4 +251,4 @@ This feature is being expanded and compatible meters will be marked in the [devi
## Further Information
- [Load Management](./loadmanagement) - Basics of load distribution
-- [Plugins](../plugins) - Advanced plugin configurations
+- [Plugins](/en/reference/plugins) - Advanced plugin configurations
diff --git a/src/content/docs/en/index.mdx b/src/content/docs/en/index.mdx
index a4b78d49b..5e80e15ac 100644
--- a/src/content/docs/en/index.mdx
+++ b/src/content/docs/en/index.mdx
@@ -25,7 +25,7 @@ evcc runs locally on a Raspberry Pi or NAS - no cloud required.
- [Wallboxes & Switchable Sockets](/en/chargers)
- [Inverters, Battery Storage, & Energy Meters](/en/meters)
- [Vehicles](/en/vehicles)
-- [Plugins](/en/plugins) support a wide variety of wallboxes, meters, & vehicles over Modbus, HTTP, MQTT, JavaScript, Websockets, and Shell Scripts
+- [Plugins](/en/reference/plugins) support a wide variety of wallboxes, meters, & vehicles over Modbus, HTTP, MQTT, JavaScript, Websockets, and Shell Scripts
- Status [Notifications](/en/reference/configuration/messaging) via [Telegram](https://telegram.org), [PushOver](https://pushover.net) and [many more](https://containrrr.dev/shoutrrr/)
- Data Export via [InfluxDB](https://www.influxdata.com) and [Grafana](https://grafana.com/grafana/)
- Stepless regulation of charging flows with supported wall boxes (e.g the smartWB's [OLC](https://board.evse-wifi.de/viewtopic.php?f=16&t=187) functionality)
diff --git a/src/content/docs/en/installation/considerations.mdx b/src/content/docs/en/installation/considerations.mdx
index 11e059989..53f8e58b3 100644
--- a/src/content/docs/en/installation/considerations.mdx
+++ b/src/content/docs/en/installation/considerations.mdx
@@ -30,7 +30,7 @@ The latter is usually the case when the solar system is equipped with a storage
The meter must be electronically readable.
Just check under [Devices > PV, Battery, Grid, Meters](/en/meters) to see if you can find your devices.
-If not, you can also integrate them yourself via [Plugins](/en/plugins).
+If not, you can also integrate them yourself as [user-defined devices](/en/user-defined-devices).
Another prerequisite for automating surplus charging is a controllable charger.
The supported devices are listed under [Devices > Chargers](/en/chargers).
diff --git a/src/content/docs/en/reference/configuration/chargers.mdx b/src/content/docs/en/reference/configuration/chargers.mdx
index 57a432b0c..fc0e594d4 100644
--- a/src/content/docs/en/reference/configuration/chargers.mdx
+++ b/src/content/docs/en/reference/configuration/chargers.mdx
@@ -39,7 +39,7 @@ name: charger1
This is the evcc-specific charger type that allows communication with the charger. Known chargers can be integrated using the `template` type. The appropriate (template) type can be found under [devices - chargers](/en/chargers).
-For unknown chargers (or for other individual reasons), the default implementation can be used through [Plugins](/en/plugins).
+For unknown chargers (or for other individual reasons), define a [user-defined charger](/en/user-defined-devices#charger).
**For example**:
diff --git a/src/content/docs/en/reference/configuration/hems.md b/src/content/docs/en/reference/configuration/hems.md
index 191e118ef..e297fc528 100644
--- a/src/content/docs/en/reference/configuration/hems.md
+++ b/src/content/docs/en/reference/configuration/hems.md
@@ -56,12 +56,12 @@ Total power limit in watts that is applied when the signal is active.
#### `limit`
-[Plugin](../../plugins) configuration for reading the switch contact.
+[Plugin](/en/reference/plugins) configuration for reading the switch contact.
Expected return value: `true`/`1` = limited, `false`/`0` = normal.
#### `passthrough`
-Optional [plugin](../../plugins) configuration for passing the limitation signal through to an external system.
+Optional [plugin](/en/reference/plugins) configuration for passing the limitation signal through to an external system.
#### `interval`
@@ -101,7 +101,7 @@ The following optional parameters can be set for EEBus communication:
#### `passthrough`
-Optional [plugin](../../plugins) configuration for passing the limitation signal through to an external system.
+Optional [plugin](/en/reference/plugins) configuration for passing the limitation signal through to an external system.
#### `interval`
diff --git a/src/content/docs/en/reference/configuration/messaging.md b/src/content/docs/en/reference/configuration/messaging.md
index 278f5a9c9..ad0910a0c 100644
--- a/src/content/docs/en/reference/configuration/messaging.md
+++ b/src/content/docs/en/reference/configuration/messaging.md
@@ -158,7 +158,7 @@ The following sections will now explain all the required parameters.
- `email`: Email. See [`email`](#email) definition
- `shout`: [shoutrrr](https://containrrr.dev/shoutrrr/). See [`shout`](#shout) definition
- `ntfy`: [ntfy](https://ntfy.sh). See [`ntfy`](#ntfy) definition
-- `custom`: Allows the usage of any [plugin](/en/plugins) that supports write access. See [`custom`](#custom) definition.
+- `custom`: Allows the usage of any [plugin](/en/reference/plugins) that supports write access. See [`custom`](#custom) definition.
---
@@ -255,7 +255,7 @@ Further information can be found in the [ntfy documentation](https://docs.ntfy.s
### `custom`
-The `custom` type allows the use of any [plugin](/en/plugins) to process messages. The plugin must support write mode. The message itself is provided in the plugin configuration using the parameter `${send}` (or as a template parameter `{{.send}}`).
+The `custom` type allows the use of any [plugin](/en/reference/plugins) to process messages. The plugin must support write mode. The message itself is provided in the plugin configuration using the parameter `${send}` (or as a template parameter `{{.send}}`).
**Possible Values**:
diff --git a/src/content/docs/en/reference/configuration/meters.md b/src/content/docs/en/reference/configuration/meters.md
index 6247012dc..86c325947 100644
--- a/src/content/docs/en/reference/configuration/meters.md
+++ b/src/content/docs/en/reference/configuration/meters.md
@@ -14,7 +14,7 @@ evcc uses a consistent sign convention for power and current values (`power`, `p
- **Negative (-)** for outgoing energy: grid feed-in, PV inverter standby consumption, house battery charging
- **Consumers** (charger, aux meters) are always **positive (+)**
-If the device returns values with the opposite sign, this can be corrected in the [plugin configuration](/en/plugins) using `scale: -1`.
+If the device returns values with the opposite sign, this can be corrected in the [plugin configuration](/en/reference/plugins) using `scale: -1`.
The `meters` configuration is a list of different available devices.
@@ -361,7 +361,7 @@ password: "ThePassword"
### `custom`
-Standard implementation, in which individual values are defined via [plugins](/en/plugins).
+Standard implementation, in which individual values are defined via [plugins](/en/user-defined-devices#meter).
**For example**:
diff --git a/src/content/docs/en/plugins.mdx b/src/content/docs/en/reference/plugins.mdx
similarity index 65%
rename from src/content/docs/en/plugins.mdx
rename to src/content/docs/en/reference/plugins.mdx
index 3d4914056..9bffe68ac 100644
--- a/src/content/docs/en/plugins.mdx
+++ b/src/content/docs/en/reference/plugins.mdx
@@ -6,20 +6,20 @@ tableOfContents:
import { Badge } from "@astrojs/starlight/components";
-Plugins can be used to integrate devices and external data sources into evcc for which there is no direct support.
-Plugins can be used for the following categories:
+Plugins read and write individual values on a device, e.g. a single power reading, a target current, an enable command.
+They power the bundled device templates and are referenced directly when you build a [user-defined device](/en/user-defined-devices) of `type: custom`.
-- `meter`: [PV, battery, grid, meters](./meters)
-- `charger`: [Wallboxes](./chargers), [Smart switches](./smartswitches), [Heat pumps, heating rods](./heating)
-- `vehicle`: [Vehicles](./vehicles)
-- `tariff`: [Tariffs, forecasts](../tariffs)
-- `circuit`: [Load management](../features/loadmanagement)
+Plugins can be used for the following categories:
-Additionally, plugins can also be used for the endpoints described in [Messaging](/en/reference/configuration/messaging) for sending lifecycle events.
+- `meter`: [PV, battery, grid, meters](/en/meters)
+- `charger`: [Wallboxes](/en/chargers), [Smart switches](/en/smartswitches), [Heat pumps, electric heaters](/en/heating)
+- `vehicle`: [Vehicles](/en/vehicles)
+- `tariff`: [Tariffs, forecasts](/en/tariffs)
+- `circuit`: [Load management](/en/features/loadmanagement)
-## Overview
+Plugins are also used by the endpoints described in [Messaging](/en/reference/configuration/messaging) to send lifecycle events.
-### Plugins
+### Plugin list
- [GPIO Plugin](#gpio) - Plugin for direct access to GPIO pins (Linux only).
- [Go Plugin](#go) - Plugin that provides or receives values via a Go script.
@@ -32,7 +32,7 @@ Additionally, plugins can also be used for the endpoints described in [Messaging
- [SMA/Speedwire Plugin](#speedwire) - Plugin specifically for SMA devices that can communicate with the Speedwire protocol.
- [Websocket Plugin](#websocket) - Plugin for receiving device data via its own web server. Can only be used for reading data.
-### Helpers
+### Helper list
- [Calc Plugin](#calc) - Meta-plugin for arithmetically linking outputs from other plugins.
- [Combined Plugin](#combined) - Meta-plugin specifically for `charger` to combine the boolean status values for the connected (_plugged_) and charging (_charging_) state into a single charging status.
@@ -50,40 +50,24 @@ Additionally, plugins can also be used for the endpoints described in [Messaging
- [Valid Plugin](#valid) - Meta-plugin for providing plugin values based on boolean validation.
- [Watchdog Plugin](#watchdog) - Meta-plugin for automatically repeating write operations at regular intervals.
-### Syntax
-
-Each plugin has an individual configuration schema.
-It's important to know whether the plugin is used in a **reading** or **writing** context.
-Some configuration parameters only make sense in a reading context, others only when used in writing mode.
+## Syntax
-For example, the following configuration can be used to integrate an MQTT plugin as a `meter`, where the current power consumption is read via the specified MQTT topic:
+A plugin attaches to an attribute of a device.
+The attribute name (e.g. `power`, `enable`, `soc`) determines the role; the `source` selects the plugin type; the remaining keys are plugin-specific parameters.
-```yaml title="Example: MQTT Plugin for power values of a power meter"
-meters:
- - name: imsys
- type: custom
- power:
- source: mqtt
- topic: "home/current/imsys/chn2/raw"
+```yaml
+:
+ source:
+ : ...
+ : ...
```
-The plugin configuration schema always has the following structure:
-
-```yaml {3,5-6,8}
-- name:
- type: custom
- :
- source:
- : ...
- : ...
- ....
- :
- ....
-```
+Each plugin is used in either a **reading** or a **writing** context. Some parameters only make sense in one of the two.
+For the full attribute lists of meters, chargers, vehicles and tariffs, see [user-defined devices](/en/user-defined-devices).
-Where `` stands for the device name, `` and `` for one of the device-specific attributes described below, `` for the plugin type and ``, `` for plugin-specific configurations (e.g. `source`, `topic` for plugins of type `mqtt`)
+
-#### Reading
+### Reading
When reading data using a plugin, so-called _pipelines_ can be used.
These allow data to be extracted in a fine-grained manner from the plugin's output.
@@ -97,20 +81,24 @@ Possible parameters for data extraction are:
- `unpack`: Converts values from other number representations, e.g. `hex`.
- `decode`: Decodes binary formats like `uint32`, `float32` etc.
-##### Known Error Values
+
+
+#### Known error values
[HTTP](#http), [MQTT](#mqtt), and [Websocket](#websocket) plugins can return special error strings.
evcc recognises these and converts them into internal error codes instead of treating them as data.
This is useful e.g. for custom vehicle integrations where the data source knows the vehicle's state.
-- `ErrAsleep` — Vehicle is asleep. evcc may choose to wake up the vehicle and retry.
-- `ErrMustRetry` — Operation should be retried (e.g. due to rate limiting).
-- `ErrNotAvailable` — Value is not available. evcc treats this as a permanent error until the next restart.
+- `ErrAsleep`: Vehicle is asleep. evcc may choose to wake up the vehicle and retry.
+- `ErrMustRetry`: Operation should be retried (e.g. due to rate limiting).
+- `ErrNotAvailable`: Value is not available. evcc treats this as a permanent error until the next restart.
If a plugin returns the string `ErrAsleep` as its response, evcc generates the corresponding internal error.
The [Error Plugin](#error) uses the same mechanism to return a fixed error value as a constant.
-#### Writing
+
+
+### Writing
When writing, parameters in the configuration can be replaced by placeholders.
The data is provided in the form `${var[:format]}`.
@@ -118,356 +106,8 @@ If format is not specified, the data is provided in the standard %v Go format.
The variables are replaced with the corresponding value before the plugin is executed.
Additionally, all functions of the Go Template Library can be used to perform more complex data transformations.
-Depending on the device ([`meter`](#meter), [`charger`](#charger) or [`vehicle`](#vehicle)), different attributes can be read or set with plugins.
-
-### Meter
-
-Power meters are configured in the configuration section [`meters`](/en/reference/configuration/meters).
-Meters defined under `meters:` can be used at various places within the `site` configuration:
-
-- `grid`: Grid meter
-- `pv`: PV meter
-- `battery`: Home battery meter
-- `charge`: Meter for the charging power of the wallbox
-- `aux`: Consumption meter for intelligent consumers
-- `ext`: Additional meter, e.g. for load management or data collection
-
-`power` is the only mandatory attribute that must be present in every `meter` definition, all other attributes are optional.
-
-However, not all meter types support all plugin attributes:
-
-- `limitsoc` and `batterymode` are used exclusively for battery meters (i.e. for `meter` referenced in `site.battery`).
-- `currents`, `voltages` and `powers` are phase attributes that must be configured with exactly three plugin configurations each (in a YAML array) and can be used for grid meters (`grid`) and wallboxes (`charge`).
-
-The following tables contain all attributes that can be provided by plugins when configured for `meter`.
-When using the plugins, it's also important that they return the correct data type.
-To convert to the required data type, the pipelines described in [Reading](#reading) can be used.
-
-| Attribute | Type | Required | Context | Description |
-| --------- | ------------------- | -------- | ------------- | ----------------------------------------------------------- |
-| power | float | yes | all | Current power in W |
-| energy | float | no | all | Meter reading in kWh |
-| maxpower | int | no | `pv` (hybrid) | Maximum AC power in W |
-| soc | int | no | `battery` | State of charge in % |
-| capacity | float | no | `battery` | Capacity in kWh |
-| powers | [float,float,float] | no | all | Phase powers in W. For sign detection of unsigned currents. |
-| currents | [float,float,float] | no | all | Phase currents in A. For detecting active phases. |
-| voltages | [float,float,float] | no | all | Phase voltages in V. For connection detection (1p/3p). |
-
-**Example**
-
-In this example, the configuration of a meter is queried for the current electrical grid power via an HTTP call:
-
-```yaml
-meters:
- - name: volkszaehler
- type: custom
- power:
- source: http
- uri: http://zaehler.network.local:8080/api/data.json?from=now
- jq: .data.tuples[0][1]
-
-site:
- meters:
- grid: volkszaehler
- ...
- ...
-```
-
-In addition to the attributes that plugins provide for reading evaluation, the following attributes are used by evcc to trigger actions:
-
-| Attribute | Type | Required | Context | Description |
-| ----------- | ---- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| limitsoc | int | no | `battery` | Set charging target for battery in %. The charging target is calculated from the configured `MinSoc`, `MaxSoc` and the current state of charge (attribute `soc`). |
-| batterymode | int | no | `battery` | Set charging mode directly (1: normal, 2: hold, 3: charge) |
-
-### Charger
-
-Chargers of `type: custom` have the following attributes that can be read:
-
-| Attribute | Type | Required | Description |
-| ---------- | ------------------- | -------- | ------------------------------------------------------------------------------------------- |
-| status | string | yes | Status (A..F) |
-| enabled | bool | yes | Is charging enabled? |
-| power | float | no | Charging power in W |
-| energy | float | no | Meter reading in kWh |
-| identify | string | no | Current RFID identifier |
-| soc | int | no | State of charge in % |
-| limitsoc | int | no | Charge limit in % |
-| temp | float | no | Current temperature in °C (heating, alias for `soc`) |
-| limittemp | int | no | Temperature limit in °C (heating, alias for `limitsoc`) |
-| finishtime | string | no | Estimated charging finish time (RFC3339, Go duration, Unix timestamp, or remaining seconds) |
-| phases | int | no | Number of physical phases (1..3) |
-| powers | [float,float,float] | no | Phase powers in W. For sign detection of unsigned currents. |
-| currents | [float,float,float] | no | Phase currents in A. For detecting active phases. |
-| voltages | [float,float,float] | no | Phase voltages in V. For connection detection (1p/3p). |
-
-For heat-pump-specific charger types (`heatpump`, `sgready`, `sgready-relay`), different plugin attributes apply, see [Heat pumps](#charger-heating).
-
-#### General Configuration Options
-
-In addition to plugin attributes, the following configuration options can be set directly on the charger:
-
-| Attribute | Type | Required | Description |
-| ------------ | -------- | -------- | -------------------------------------------------------- |
-| icon | string | no | Icon for display in the user interface |
-| features | []string | no | Feature flags for special charger properties (see below) |
-| standbypower | int | no | Standby power in W (for `switchsocket` type) |
-
-##### Feature Flags
-
-The `features` array can be used to activate special charger properties:
-
-| Feature | Description |
-| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| integrateddevice | No vehicle selection. Device runs without a connected vehicle and without charging sessions (e.g. heat pump, heating rod, permanently installed consumer). |
-| heating | Treat device as heating: SOC and limits are displayed in °C instead of %. |
-| continuous | Device keeps running in its own normal operation when "disabled". The UI shows "Normal operation" instead of "Standby". A request to increase power (e.g. on PV surplus or cheap grid power) is labelled "Boost". |
-| switchdevice | Device can only be switched on/off (no continuous current control). Min/max current settings and the `Min+PV` mode are hidden. |
-
-##### Common Combinations
-
-You can use the following combinations as a starting point for your own `type: custom` configurations.
-They mirror the preconfigured templates in evcc.
-
-**Electric heater**:
-
-```yaml
-features:
- - integrateddevice
- - heating
-```
-
-**Socket**:
-
-```yaml
-features:
- - switchdevice
- - integrateddevice # optional, when the socket drives a fixed load
- - heating # optional, when it controls a heating device
-```
-
-**Heat pump**:
-
-```yaml
-features:
- - integrateddevice
- - heating
- - continuous
- - switchdevice # optional, when no current control is available (SG Ready)
-```
-
-**Example**
-
-This example shows how to query the charging status (charging/not charging) of a charger via the Modbus plugin:
-
-```yaml
-chargers:
- - name: icharge
- type: custom
- features:
- - integrateddevice
- enabled:
- source: modbus
- id: 4711
- uri: modbus.local:502
- rtu: false
- register:
- address: 100
- type: holding
- decode: uint16
-```
-
-In addition to read-only values, actions can also be triggered or configuration values set via plugins:
-
-| Attribute | Type | Required | Description |
-| ---------------- | ----- | -------- | ------------------------------------------------- |
-| enable | bool | yes | Enable / disable charging |
-| maxcurrent | int | yes | Set maximum charging current in A |
-| maxcurrentmillis | float | no | Set maximum charging current in A (with decimals) |
-| phases1p3p | int | no | Perform phase switching (requires `tos: true`) |
-| wakeup | bool | no | Wake up vehicle |
-
-**Example**
-
-This example switches a Tasmota socket via an MQTT message:
-
-```yaml
-chargers:
- - name: unu-charger
- type: custom
- enable:
- source: mqtt
- broker: mosquitto.local:883
- topic: cmd/unu-switch/Power
- payload: ON
-```
-
-#### Heat Pumps
-
-Heat pumps and similar heating devices use dedicated charger types, each with its own plugin attributes.
-The full setup is described under [Heat pumps, heating rods](./heating).
-
-All three types share the following optional measurement attributes:
-
-| Attribute | Type | Required | Description |
-| --------- | ----- | -------- | --------------------------------------- |
-| power | float | no | Current power in W |
-| energy | float | no | Meter reading in kWh |
-| temp | float | no | Current temperature in °C |
-| limittemp | int | no | Device-internal temperature limit in °C |
-
-**`type: heatpump`**: heat pump with power setpoint.
-
-| Attribute | Type | Required | Description |
-| ----------- | ----- | -------- | ---------------------------------- |
-| setmaxpower | int | yes | Set maximum heating power in W |
-| getmaxpower | float | no | Current maximum heating power in W |
-
-**`type: sgready`**: heat pump with SG-Ready interface.
-
-| Attribute | Type | Required | Description |
-| ----------- | ---- | -------- | ------------------------------------------------------ |
-| setmode | int | yes | Change SG-Ready mode (1: reduced, 2: normal, 3: boost) |
-| getmode | int | no | Current SG-Ready mode (1, 2, 3) |
-| setmaxpower | int | no | Set maximum heating power in W |
-
-**`type: sgready-relay`**: heat pump controlled via relay contacts.
-Sub-chargers are referenced by type instead of via plugins.
-
-| Attribute | Type | Required | Description |
-| --------- | ------------- | -------- | ------------------------------------ |
-| boost | charger-typed | yes | Relay for the SG-Ready boost contact |
-| dim | charger-typed | no | Relay for the SG-Ready dim contact |
-
-### Vehicle
-
-Vehicle parameters can also be read via plugins.
-
-| Attribute | Type | Required | Description |
-| ------------- | ------ | -------- | ------------------------------------------------------------------------------------------- |
-| soc | int | yes | State of charge in % |
-| limitsoc | int | no | Charge limit in % |
-| status | string | no | Status (A..F) |
-| range | int | no | Range in km |
-| odometer | int | no | Odometer reading in km |
-| climater | bool | no | Climate control active? |
-| getmaxcurrent | float | no | Maximum charging current in A |
-| finishtime | string | no | Estimated charging finish time (RFC3339, Go duration, Unix timestamp, or remaining seconds) |
-
-#### General Configuration Options
-
-The following configuration options can be set directly on the vehicle:
-
-| Attribute | Type | Required | Description |
-| --------- | -------- | -------- | -------------------------------------------------------- |
-| title | string | no | Display name of the vehicle in the user interface |
-| icon | string | no | Icon for display in the user interface |
-| capacity | float | no | Battery capacity in kWh |
-| features | []string | no | Feature flags for special vehicle properties (see below) |
-
-##### Feature Flags
-
-| Feature | Description |
-| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| coarsecurrent | Vehicle accepts charging current only in whole 1 A steps. The control logic is constrained to coarse 1 A steps even when the charger could regulate more finely. |
-| streaming | Vehicle pushes data instead of being polled (e.g. BMW Cardata). SOC updates outside active charging are treated as reliable. |
-| welcomecharge | Vehicle expects the wallbox to be active on connect to register the link as working. Otherwise it reports an error. |
-
-**Example**
-
-In the following example, the current range of the vehicle is read from MQTT messages:
-
-```yaml
-vehicles:
- - name: mazda
- type: custom
- title: Green Mazda
- capacity: 50
- features:
- - coarsecurrent
- range:
- source: mqtt
- topic: mazda2mqtt/c53/chargeInfo/drivingRangeKm
-```
-
-Additionally, special commands can be sent to the vehicle via plugins:
-
-| Attribute | Type | Required | Description |
-| ------------ | ---- | -------- | --------------------------------- |
-| wakeup | bool | no | Wake up vehicle |
-| chargeenable | bool | no | Start/stop charging process |
-| maxcurrent | int | no | Set maximum charging current in A |
-
-**Example**
-
-To wake up a car via an HTTP ping to send further queries, the HTTP plugin can be used as in the following example:
-
-```yaml
-vehicles:
- - name: model-y
- type: custom
- wakeup:
- source: http
- uri: http://teslalogger.local:5000/command/08154711/wake_up
-```
-
-#### Charge Mode on Vehicle Identification
-
-For user-defined vehicles, the charge mode can be configured with `onIdentify` to be set automatically when the vehicle is identified.
-This is useful when you want the desired charge mode to be set automatically as soon as the vehicle is detected.
-
-**Example**:
-
-```yaml
-vehicles:
- - name: my-car
- type: custom
- soc:
- source: mqtt
- topic: car/soc
- onIdentify:
- mode: pv
-```
-
-Available modes are: `off`, `now`, `minpv`, `pv`.
-
-### Tariffs & Forecasts
-
-See [Tariffs & Forecasts > Custom Plugin](../tariffs#plugin) for the full configuration.
-
-#### Feature Flags
-
-| Feature | Description |
-| --------- | ---------------------------------------------------------------------------------------------- |
-| average | Smooths fine-grained price slots (e.g. 15-minute values) into hourly averages. |
-| cacheable | Persists fetched values. Used as fallback after a restart or provider outage (up to 24 hours). |
-
-```yaml
-tariffs:
- grid:
- type: custom
- features:
- - cacheable
- # ... additional attributes
-```
-
-### Load Management
-
-:::note[Work in Progress]
-...
-:::
-
-### Messaging
-
-:::note[Work in Progress]
-...
-:::
-
## Plugins
-The following plugins are available and can be configured for the above-described attributes to enable flexible integration with various systems.
-
### GPIO
The `gpio` plugin enables direct access to GPIO pins (General Purpose Input/Output) on Linux systems.
@@ -558,15 +198,15 @@ When the `go` plugin is used for writing, the value to be written is passed to t
**Writing Example**:
```yaml
-charger:
- - type: custom
- maxcurrent:
- source: go
- script: |
- fmt.Printf("Setting charge current: %d A\n", maxcurrent)
- // maxcurrent variable is automatically available
+maxcurrent:
+ source: go
+ script: |
+ fmt.Printf("Setting charge current: %d A\n", maxcurrent)
+ // maxcurrent variable is automatically available
```
+
+
#### Input and Output Transformations
The `go` and `js` plugins support `in` and `out` parameters to use values from other sources as variables in the script or to forward the script result to other plugins.
@@ -607,23 +247,20 @@ power:
The `out` parameter forwards the script result to other plugins.
This is particularly useful in a writing context, e.g. when the script result should be further processed via MQTT or HTTP.
-Each entry requires `name`, `type` and `config` — analogous to `in`.
+Each entry requires `name`, `type` and `config`, analogous to `in`.
```yaml
-chargers:
- - name: smart-heater
- type: custom
- maxcurrent:
- source: go
- script: |
- watts := maxcurrent * 230
- watts
- out:
- - name: watts
- type: float
- config:
- source: mqtt
- topic: heater/target_power
+maxcurrent:
+ source: go
+ script: |
+ watts := maxcurrent * 230
+ watts
+ out:
+ - name: watts
+ type: float
+ config:
+ source: mqtt
+ topic: heater/target_power
```
### HTTP
@@ -746,12 +383,10 @@ When the `js` plugin is used for writing, the value to be written is passed to t
**Writing Example**:
```yaml
-charger:
- - type: custom
- maxcurrent:
- source: js
- script: |
- console.log(maxcurrent);
+maxcurrent:
+ source: js
+ script: |
+ console.log(maxcurrent);
```
The `js` plugin supports the same [input and output transformations](#transformations) (`in`/`out`) as the `go` plugin.
@@ -863,6 +498,8 @@ energy:
The query must return a single numerical value.
For vector results, exactly one metric must be included.
+
+
### Shell Script
The `script` plugin executes external scripts to read or update data. The plugin is useful for integrating any kind of external functionality.
@@ -883,6 +520,8 @@ cmd: /home/user/my-script.sh ${enable:%b} # format boolean enable as 0/1
timeout: 5s
```
+
+
### SMA/Speedwire
The `sma` plugin provides an interface to SMA devices that support the Speedwire protocol.
@@ -1294,6 +933,8 @@ setmode:
encoding: int16
```
+
+
### Meter
The `meter` plugin allows using another meter as a data source.
diff --git a/src/content/docs/en/user-defined-devices.mdx b/src/content/docs/en/user-defined-devices.mdx
new file mode 100644
index 000000000..8a083c343
--- /dev/null
+++ b/src/content/docs/en/user-defined-devices.mdx
@@ -0,0 +1,502 @@
+---
+title: User-defined Devices
+tableOfContents:
+ maxHeadingLevel: 4
+---
+
+import { Tabs, TabItem } from "@astrojs/starlight/components";
+
+When creating a charger, heater, grid meter, battery, solar system, other consumer, vehicle, tariff or notification service, you can pick the **User-defined device** option from the device type list and describe your own logic based on the [plugin system](/en/reference/plugins).
+
+That way you can integrate devices that aren't covered by a built-in template, e.g. read the current power from an HTTP endpoint, or write a target current via Modbus.
+
+## How to define a device
+
+In the UI, every device type lists a **User-defined device** entry in the template selector.
+Picking it opens the editor for your own configuration.
+A device with `type: custom` is created by default. The type can be overridden with another value when needed (e.g. `type: heatpump`).
+
+```yaml
+power:
+ source: mqtt
+ topic: home/current/imsys/chn2/raw
+```
+
+Alternatively, write the full configuration directly in `evcc.yaml` with `name`, `type: custom` and the attribute block underneath:
+
+```yaml
+meters:
+ - name: imsys
+ type: custom
+ power:
+ source: mqtt
+ topic: home/current/imsys/chn2/raw
+```
+
+All other examples on this page use the flat attribute-block form you enter in the UI.
+
+For the list of available plugin sources (`http`, `mqtt`, `modbus`, …) and helpers (`calc`, `map`, `watchdog`, …) see the [plugins reference](/en/reference/plugins).
+
+## Attributes and features
+
+Every user-defined device is described by three kinds of fields:
+
+- **Read attributes** — plugins evcc polls to obtain a value (e.g. `power`, `soc`, `status`).
+- **Write attributes** — plugins evcc invokes to set a value or trigger an action (e.g. `enable`, `maxcurrent`, `wakeup`). The value to be written is available in the plugin.
+- **Features** — `features` list toggling non-default behaviour. Available flags depend on the device type.
+
+Generic shape:
+
+```yaml
+# read attributes
+power:
+ source: http
+ uri: http://meter.local/power
+soc:
+ source: mqtt
+ topic: battery/soc
+
+# write attributes
+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
+```
+
+The available attribute names and feature flags differ per device type and are listed in the sections below.
+
+
+
+## Meter
+
+Power meters are configured in the [`meters`](/en/reference/configuration/meters) section.
+Meters defined under `meters:` can be referenced from `site`:
+
+- `grid`: Grid meter
+- `pv`: PV meter
+- `battery`: Home battery meter
+- `charge`: Meter for the charging power of the wallbox
+- `aux`: Consumption meter for intelligent consumers
+- `ext`: Additional meter, e.g. for load management or data collection
+
+`power` is the only required attribute.
+Not all meter roles support all attributes:
+
+- `limitsoc` and `batterymode` are used exclusively for battery meters (referenced from `site.battery`).
+- `currents`, `voltages` and `powers` are phase attributes that must be configured with exactly three plugin entries each (as a YAML array) and apply to grid meters (`grid`) and wallboxes (`charge`).
+
+Return the correct data type from each plugin.
+To convert, use the [reading pipelines](/en/reference/plugins#reading).
+
+### Read attributes
+
+| Attribute | Type | Required | Context | Description |
+| ---------- | --------------------- | -------- | ------------- | ----------------------------------------------------------- |
+| `power` | `float` | yes | all | Current power in W |
+| `energy` | `float` | no | all | Meter reading in kWh |
+| `maxpower` | `int` | no | `pv` (hybrid) | Maximum AC power in W |
+| `soc` | `int` | no | `battery` | State of charge in % |
+| `capacity` | `float` | no | `battery` | Capacity in kWh |
+| `powers` | `[float,float,float]` | no | all | Phase powers in W. For sign detection of unsigned currents. |
+| `currents` | `[float,float,float]` | no | all | Phase currents in A. For detecting active phases. |
+| `voltages` | `[float,float,float]` | no | all | Phase voltages in V. For connection detection (1p/3p). |
+
+### Write attributes
+
+| Attribute | Type | Required | Context | Description |
+| ------------- | ----- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `limitsoc` | `int` | no | `battery` | Set charging target for battery in %. The charging target is calculated from the configured `MinSoc`, `MaxSoc` and the current state of charge (attribute `soc`). |
+| `batterymode` | `int` | no | `battery` | Set charging mode directly (1: normal, 2: hold, 3: charge) |
+
+### Example
+
+Read the current grid power from an HTTP endpoint.
+
+```yaml
+power:
+ source: http
+ uri: http://zaehler.network.local:8080/api/data.json?from=now
+ jq: .data.tuples[0][1]
+```
+
+
+
+## Charger
+
+The default `type: custom` covers wallboxes with continuous current control.
+For other devices, specialised charger types are described under [Switchsocket](#charger-switchsocket) and [Heat pumps](#charger-heating).
+
+### Read attributes
+
+| Attribute | Type | Required | Description |
+| ------------ | --------------------- | -------- | ------------------------------------------------------------------------------------------- |
+| `status` | `string` | yes | Status (A..F) |
+| `enabled` | `bool` | yes | Is charging enabled? |
+| `power` | `float` | no | Charging power in W |
+| `energy` | `float` | no | Meter reading in kWh |
+| `identify` | `string` | no | Current RFID identifier |
+| `soc` | `int` | no | State of charge in % |
+| `limitsoc` | `int` | no | Charge limit in % |
+| `temp` | `float` | no | Current temperature in °C (heating, alias for `soc`) |
+| `limittemp` | `int` | no | Temperature limit in °C (heating, alias for `limitsoc`) |
+| `finishtime` | `string` | no | Estimated charging finish time (RFC3339, Go duration, Unix timestamp, or remaining seconds) |
+| `phases` | `int` | no | Number of physical phases (1..3) |
+| `powers` | `[float,float,float]` | no | Phase powers in W. For sign detection of unsigned currents. |
+| `currents` | `[float,float,float]` | no | Phase currents in A. For detecting active phases. |
+| `voltages` | `[float,float,float]` | no | Phase voltages in V. For connection detection (1p/3p). |
+
+### Write attributes
+
+| Attribute | Type | Required | Description |
+| ------------------ | ------- | -------- | ------------------------------------------------- |
+| `enable` | `bool` | yes | Enable / disable charging |
+| `maxcurrent` | `int` | yes | Set maximum charging current in A |
+| `maxcurrentmillis` | `float` | no | Set maximum charging current in A (with decimals) |
+| `phases1p3p` | `int` | no | Perform phase switching (requires `tos: true`) |
+| `wakeup` | `bool` | no | Wake up vehicle |
+
+
+
+### Features
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `integrateddevice` | No vehicle selection. Device runs without a connected vehicle and without charging sessions (e.g. heat pump, heating rod, permanently installed consumer). |
+| `heating` | Treat device as heating: SOC and limits are displayed in °C instead of %. |
+| `continuous` | Device keeps running in its own normal operation when "disabled". The UI shows "Normal operation" instead of "Standby". A request to increase power (e.g. on PV surplus or cheap grid power) is labelled "Boost". |
+| `switchdevice` | Device can only be switched on/off (no continuous current control). Min/max current settings and the `Min+PV` mode are hidden. |
+
+Common feature combinations seen in built-in templates:
+
+**Electric heater**:
+
+```yaml
+features:
+ - integrateddevice
+ - heating
+```
+
+**Socket**:
+
+```yaml
+features:
+ - switchdevice
+ - integrateddevice # optional, when the socket drives a fixed load
+ - heating # optional, when it controls a heating device
+```
+
+**Heat pump**:
+
+```yaml
+features:
+ - integrateddevice
+ - heating
+ - continuous
+ - switchdevice # optional, when no current control is available (SG Ready)
+```
+
+### Examples
+
+Query the charging status of a charger via Modbus.
+
+```yaml
+features:
+ - integrateddevice
+enabled:
+ source: modbus
+ id: 4711
+ uri: modbus.local:502
+ rtu: false
+ register:
+ address: 100
+ type: holding
+ decode: uint16
+```
+
+Switch a Tasmota socket via an MQTT message.
+
+```yaml
+enable:
+ source: mqtt
+ broker: mosquitto.local:883
+ topic: cmd/unu-switch/Power
+ payload: ON
+```
+
+
+
+### Switchsocket
+
+**`type: switchsocket`**
+
+For smart sockets and similar relay devices that can only be switched on/off without continuous current control.
+The charging status is derived from the current power (above `standbypower` means charging).
+Full setup details are under [Smart switches](/en/smartswitches).
+
+| Attribute | Type | Required | Description |
+| -------------- | ------- | -------- | ---------------------------------------------------------------------------------------- |
+| `enabled` | `bool` | yes | Read socket state (on/off) |
+| `power` | `float` | yes | Current power in W |
+| `energy` | `float` | no | Meter reading in kWh |
+| `soc` | `float` | no | State of charge in % |
+| `enable` | `bool` | yes | Switch socket on/off |
+| `standbypower` | `float` | no | Power threshold in W. Above it: charging; below: standby. Negative: static (no metering) |
+
+
+
+### Heat pumps
+
+Heat pumps and similar heating devices use dedicated charger types, each with its own attributes.
+The full setup is described under [Heat pumps, electric heaters](/en/heating).
+
+
+
+
+**`type: heatpump`**
+
+For inverter-controlled heat pumps that accept a continuous power setpoint over Modbus, HTTP or similar.
+The target heating power is written directly via `setmaxpower`.
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | -------- | --------------------------------------- |
+| `power` | `float` | no | Current power in W |
+| `energy` | `float` | no | Meter reading in kWh |
+| `temp` | `float` | no | Current temperature in °C |
+| `limittemp` | `int` | no | Device-internal temperature limit in °C |
+| `setmaxpower` | `int` | yes | Set maximum heating power in W |
+| `getmaxpower` | `float` | no | Current maximum heating power in W |
+
+
+
+
+**`type: sgready`**
+
+For heat pumps that expose the standard SG-Ready interface as a single mode value.
+Three modes are supported: `1` reduced, `2` normal, `3` boost.
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | -------- | ------------------------------------------------------ |
+| `power` | `float` | no | Current power in W |
+| `energy` | `float` | no | Meter reading in kWh |
+| `temp` | `float` | no | Current temperature in °C |
+| `limittemp` | `int` | no | Device-internal temperature limit in °C |
+| `setmode` | `int` | yes | Change SG-Ready mode (1: reduced, 2: normal, 3: boost) |
+| `getmode` | `int` | no | Current SG-Ready mode (1, 2, 3) |
+| `setmaxpower` | `int` | no | Set maximum heating power in W |
+
+
+
+
+**`type: sgready-relay`**
+
+For heat pumps whose SG-Ready input is wired as two dry relay contacts (boost + dim).
+Each contact is driven by a separate sub-charger referenced by type, not via plugins.
+
+| Attribute | Type | Required | Description |
+| ----------- | --------------- | -------- | --------------------------------------- |
+| `power` | `float` | no | Current power in W |
+| `energy` | `float` | no | Meter reading in kWh |
+| `temp` | `float` | no | Current temperature in °C |
+| `limittemp` | `int` | no | Device-internal temperature limit in °C |
+| `boost` | `charger-typed` | yes | Relay for the SG-Ready boost contact |
+| `dim` | `charger-typed` | no | Relay for the SG-Ready dim contact |
+
+
+
+
+
+
+## Vehicle
+
+Vehicle parameters can also be read via plugins.
+
+### Read attributes
+
+| Attribute | Type | Required | Description |
+| --------------- | -------- | -------- | ------------------------------------------------------------------------------------------- |
+| `soc` | `int` | yes | State of charge in % |
+| `limitsoc` | `int` | no | Charge limit in % |
+| `status` | `string` | no | Status (A..F) |
+| `range` | `int` | no | Range in km |
+| `odometer` | `int` | no | Odometer reading in km |
+| `climater` | `bool` | no | Climate control active? |
+| `getmaxcurrent` | `float` | no | Maximum charging current in A |
+| `finishtime` | `string` | no | Estimated charging finish time (RFC3339, Go duration, Unix timestamp, or remaining seconds) |
+
+### Write attributes
+
+| Attribute | Type | Required | Description |
+| -------------- | ------ | -------- | --------------------------------- |
+| `wakeup` | `bool` | no | Wake up vehicle |
+| `chargeenable` | `bool` | no | Start/stop charging process |
+| `maxcurrent` | `int` | no | Set maximum charging current in A |
+
+### Configuration
+
+| Attribute | Type | Required | Description |
+| ---------- | -------- | -------- | -------------------------------- |
+| `title` | `string` | no | Display name of the vehicle |
+| `capacity` | `float` | no | Battery capacity in kWh |
+| `icon` | `string` | no | Icon shown in the user interface |
+
+
+
+### Features
+
+| Feature | Description |
+| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `coarsecurrent` | Vehicle accepts charging current only in whole 1 A steps. The control logic is constrained to coarse 1 A steps even when the charger could regulate more finely. |
+| `streaming` | Vehicle pushes data instead of being polled (e.g. BMW Cardata). SOC updates outside active charging are treated as reliable. |
+| `welcomecharge` | Vehicle expects the wallbox to be active on connect to register the link as working. Otherwise it reports an error. |
+
+### Examples
+
+Read the current range from MQTT messages.
+
+```yaml
+title: Green Mazda # display name (optional)
+capacity: 50 # battery capacity in kWh (optional)
+features:
+ - coarsecurrent
+range:
+ source: mqtt
+ topic: mazda2mqtt/c53/chargeInfo/drivingRangeKm
+```
+
+Wake a car via an HTTP ping before sending further queries.
+
+```yaml
+wakeup:
+ source: http
+ uri: http://teslalogger.local:5000/command/08154711/wake_up
+```
+
+
+
+`onIdentify` sets the charge mode automatically when the vehicle is detected.
+
+```yaml
+soc:
+ source: mqtt
+ topic: car/soc
+onIdentify:
+ mode: pv
+```
+
+Available modes: `off`, `now`, `minpv`, `pv`.
+
+
+
+## Tariff and forecast
+
+A user-defined tariff connects evcc to a custom value source via the plugin mechanism.
+The `tariff` attribute selects what the source represents and which unit the values use.
+
+### Read attributes
+
+Exactly one of `price` or `forecast` must be configured.
+
+| Attribute | Type | Description |
+| ---------- | -------- | ------------------------------------------------------------------------------------------------- |
+| `price` | `float` | Current value. Float returned by the plugin. |
+| `forecast` | `string` | Forecast as JSON string with a list of time periods and values (see schema below). Polled hourly. |
+
+### Configuration
+
+| Attribute | Type | Required | Description |
+| ---------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `tariff` | `string` | no | `price` (default), `co2` or `solar`. Sets the unit of the returned values: price in configured currency per kWh, CO₂ intensity in g/kWh, solar forecast in W. |
+| `charges` | `float` | no | Fixed additional charge per kWh added to every value. Default `0`. |
+| `tax` | `float` | no | Percentage tax applied to the result, e.g. `0.2` for 20 %. Default `0`. |
+| `formula` | `string` | no | Go expression for a custom calculation, with `price`, `charges` and `tax` in scope. See [examples](#formula-examples). |
+| `interval` | `duration` | no | Polling interval for `forecast`. Default `1h`. |
+| `cache` | `duration` | no | Cache duration for `price`. Default `15m`. |
+
+
+
+### Features
+
+| Feature | Description |
+| ----------- | ---------------------------------------------------------------------------------------------- |
+| `average` | Smooths fine-grained price slots (e.g. 15-minute values) into hourly averages. |
+| `cacheable` | Persists fetched values. Used as fallback after a restart or provider outage (up to 24 hours). |
+
+### Examples
+
+**Current price via HTTP**:
+
+```yaml
+price:
+ source: http
+ uri: https://example.com/api/price
+```
+
+**Forecast 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'
+```
+
+The plugin must return a JSON structure containing a list of time periods and prices.
+Date fields must be in the form `YYYY-MM-DDTHH:MM:SSZ` and the price in the correct currency unit (e.g. EUR).
+evcc works internally with 15-minute intervals; plugins may return hourly data, which is converted automatically.
+
+```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
+ }
+]
+```
+
+
+
+The `formula` field accepts a Go expression with `price`, `charges`, `tax` and the slot timestamp `ts` in scope.
+The [`math` library](https://pkg.go.dev/math) and [`time.Time`](https://pkg.go.dev/time#Time) methods on `ts` are available.
+The formula runs for the current price and each forecast slot.
+
+**Price cap**:
+
+```yaml
+charges: 0.22
+tax: 0.19
+formula: math.Min(0.5, (price + charges) * (1 + tax))
+```
+
+Caps the result at 50 ct/kWh.
+
+**No feed-in tariff on negative day-ahead prices** (German PV systems commissioned after February 25, 2025):
+
+```yaml
+formula: factor := 1.0; if price < 0 { factor = 0.0 }; factor * 0.07
+```
+
+Pays a fixed feed-in tariff of 7 ct/kWh, except when the day-ahead market price is negative.
diff --git a/src/env.d.ts b/src/env.d.ts
index a5ebf13ad..619da460e 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -1,5 +1,7 @@
///
+declare module "remark-heading-id";
+
declare module "virtual:starlight/user-images" {
type ImageMetadata = import("astro").ImageMetadata;
export const logos: {
diff --git a/src/pages/[lang]/chargers/index.astro b/src/pages/[lang]/chargers/index.astro
index 069502123..e94076052 100644
--- a/src/pages/[lang]/chargers/index.astro
+++ b/src/pages/[lang]/chargers/index.astro
@@ -4,6 +4,7 @@ import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
import DeviceCardList from "@components/DeviceCardList.astro";
import DeviceFilter from "@components/DeviceFilter.astro";
import ChargersIntro from "@components/intros/ChargersIntro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, filterByType, availableOverviewFeatures } from "@utils/devices";
export async function getStaticPaths() {
@@ -55,4 +56,5 @@ const headings = lang === "de"
>
)}
+
diff --git a/src/pages/[lang]/heating/index.astro b/src/pages/[lang]/heating/index.astro
index ce01c74ce..b5487fded 100644
--- a/src/pages/[lang]/heating/index.astro
+++ b/src/pages/[lang]/heating/index.astro
@@ -5,6 +5,7 @@ import DeviceCardList from "@components/DeviceCardList.astro";
import DeviceFilter from "@components/DeviceFilter.astro";
import HeatingIntro from "@components/intros/HeatingIntro.astro";
import HeatingOutro from "@components/intros/HeatingOutro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, filterByType, availableOverviewFeatures } from "@utils/devices";
export async function getStaticPaths() {
@@ -48,4 +49,5 @@ const headings = lang === "de"
{supportedTitle}
+
diff --git a/src/pages/[lang]/meters/index.astro b/src/pages/[lang]/meters/index.astro
index 65e087112..fa916da47 100644
--- a/src/pages/[lang]/meters/index.astro
+++ b/src/pages/[lang]/meters/index.astro
@@ -4,6 +4,7 @@ import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
import DeviceCardList from "@components/DeviceCardList.astro";
import DeviceFilter from "@components/DeviceFilter.astro";
import MetersIntro from "@components/intros/MetersIntro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, availableOverviewFeatures, availableUsages } from "@utils/devices";
export async function getStaticPaths() {
@@ -73,4 +74,5 @@ const headings = lang === "de"
/>
>
)}
+
diff --git a/src/pages/[lang]/smartswitches/index.astro b/src/pages/[lang]/smartswitches/index.astro
index aac96992e..a7a217c7e 100644
--- a/src/pages/[lang]/smartswitches/index.astro
+++ b/src/pages/[lang]/smartswitches/index.astro
@@ -4,6 +4,7 @@ import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
import DeviceCardList from "@components/DeviceCardList.astro";
import DeviceFilter from "@components/DeviceFilter.astro";
import SmartswitchesIntro from "@components/intros/SmartswitchesIntro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, filterByType, availableOverviewFeatures } from "@utils/devices";
export async function getStaticPaths() {
@@ -40,4 +41,5 @@ const headings = lang === "de"
{filterFeatures.length > 0 && }
{supportedTitle}
+
diff --git a/src/pages/[lang]/tariffs/index.astro b/src/pages/[lang]/tariffs/index.astro
index 3433c492a..71cfebf92 100644
--- a/src/pages/[lang]/tariffs/index.astro
+++ b/src/pages/[lang]/tariffs/index.astro
@@ -3,6 +3,7 @@ import { getCollection } from "astro:content";
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
import DeviceCardList from "@components/DeviceCardList.astro";
import TariffsIntro from "@components/intros/TariffsIntro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, TARIFF_GROUPS } from "@utils/devices";
export async function getStaticPaths() {
@@ -78,4 +79,5 @@ const headings = [
) : null
)
}
+
diff --git a/src/pages/[lang]/vehicles/index.astro b/src/pages/[lang]/vehicles/index.astro
index 2b2791fa2..c8adac345 100644
--- a/src/pages/[lang]/vehicles/index.astro
+++ b/src/pages/[lang]/vehicles/index.astro
@@ -4,6 +4,7 @@ import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
import DeviceCardList from "@components/DeviceCardList.astro";
import DeviceFilter from "@components/DeviceFilter.astro";
import VehiclesIntro from "@components/intros/VehiclesIntro.astro";
+import UserDefinedHint from "@components/UserDefinedHint.astro";
import { sortDevices, availableOverviewFeatures } from "@utils/devices";
export async function getStaticPaths() {
@@ -53,4 +54,5 @@ const headings = lang === "de"
>
)}
+
diff --git a/src/scripts/generate-legacy-redirects.mjs b/src/scripts/generate-legacy-redirects.mjs
index fdb963e0a..de0f9f919 100644
--- a/src/scripts/generate-legacy-redirects.mjs
+++ b/src/scripts/generate-legacy-redirects.mjs
@@ -85,13 +85,17 @@ const DEVICE_TYPES = [
"vehicles",
"smartswitches",
"heating",
- "plugins",
];
for (const type of DEVICE_TYPES) {
if (writeRedirect(`/docs/devices/${type}`, `/de/${type}`)) count++;
if (writeRedirect(`/en/docs/devices/${type}`, `/en/${type}`)) count++;
}
+// /docs/devices/plugins was the Docusaurus-era plugin reference.
+// Map it to the new reference location.
+if (writeRedirect(`/docs/devices/plugins`, `/de/reference/plugins`)) count++;
+if (writeRedirect(`/en/docs/devices/plugins`, `/en/reference/plugins`)) count++;
+
// One blog post had a period in its old slug that Astro strips.
// /blog/2024/02/01/v0.124-new-tesla-api → //blog/2024/02/01/v0124-new-tesla-api
{