Tesla Wallbox Gen3 Agent

Seit Ende 2021 habe ich eine Tesla Wallbox Gen 3 installiert, die aber keinen Tesla sondern aktuell nur ein PEHV (BMW225xe) lädt. Die Wallbox hat aber eine Rest-API, die, sofern ich das zulassen würde, mit der Tesla-Cloud spricht. Ohne Tesla-Auto steht mir aber keine Verwaltung über die Tesla-App zur Verfügung. Also habe ich mir überlegt, wie ich Änderungen der Wallbox auswerten und z.B. per Telegram API an mein Smartphone senden kann.

PowerShell, MicroPython oder App?

An die Verbindung der Wallbox zur Tesla-Cloud komme ich nicht wirklich ran und muss ich auch nicht, da die Wallbox selbst per REST abgerufen werden kann. Damit gibt es zwei generelle Ansätze:

  • App zur Abfrage
    Ich könnte mir eine App für ein Smartphone zu bauen, welche den aktuellen Status entsprechend schick anzeigt. Dazu muss ich aber im gleichen LAN sein. Eine Veröffentlichung, damit auch unterwegs dies möglich ist, verbietet sich aber ohne weitere Schutzvorkehrungen, denn die Wallbox hat keine Authentifizierung. Da es auch keine bekannte Steuerungsmöglichkeit gibt, ist dieser Ansatz nur bedingt interessant und eher eine kleine Programmierübung für einen angehenden App-Entwickler.
  • Agent/Bot zur Verarbeitung
    Interessanter finde ich einen Prozess, der regelmäßig die Wallbox abfragt und auf Veränderungen reagiert, Daten protokolliert und Meldungen aktiv versendet. Über einen PRTG-Sensor für die Wallbox habe ich ja schon Kennzahlen erfasst.

Natürlich muss die Businesslogik irgendwo ausgeführt werden. Da die Aufgabe eigentlich überschaubar ist, sollte sogar ein ESP8266/ESP32 ausreichen Zudem wäre die Installation sehr einfach, da auch die Wallbox per WLAN kommuniziert. Im Prinzip sieht das Bild wie folgt aus:

Ein Skript im Eigenheim verbindet sich zyklisch mit der Wallbox, um die relevanten Betriebsparameter auszulesen und Änderungen per Telegram API an das Smartphone zu senden.

Funktionsweise

Ich habe mir daher erst einmal die Zustände und deren Veränderungen bei den normalen Events angeschaut. Die relevanten Änderungen habe ich markiert

Event evse_state vehicle_connected Aktion

Fahrzeug wurde verbunden

* -> 4

$false -> $true

Die Tesla-Box hat leider noch keine Zugangskontrolle per RFID und da würde eine Meldung zumindest helfen. Die Meldung kann aber durchaus einige Minuten verzögert werden, denn interessant ist ja erst der "Strombezug". Die Software sollte also hier erst mal nur einen Counter starten und sich den aktuellen kWh-Zähler merken.

Ladevorgang startet/fortgeetzt

*->10/11

$true

Sobald die Ladung startet, ist der Stecker aber verriegelt und es wird Energie bezogen. Wenn ein Fahrzeug angesteckt wird, dann sollte der Ladecounter zurückgesetzt werden und eine Meldung an den Besitzer gehen. Aber natürlich nur, wenn das Auto vorher angesteckt wurde.

Laden unterbrochen/ Laden beendet

* ->8

$true

Es kann durchaus passieren, dass ein Fahrzeug die Ladung unterbricht aber der Stecker nicht abgezogen werden. Das Fahrzeug kann die Ladung auch wieder aufnehmen. Insofern darf der Vorgang der Ladung noch nicht als "Abgeschlossen" gelten. Auf der anderen Seite könnte man natürlich eine Meldung absetzen, damit der Besitzer über eine eventuelles Problem informiert wird. Ein Problem wird es natürlich, zwischen "Laden unterbrochen" und "Ladung abgeschlossen" zu unterscheiden. Die Wallbox kenn nicht den Status des Fahrzeugs.

Fahrzeug wird abgesteckt

*->1

$true -> $false

Die Wallbox kann erkennen, dass der Stecker abgezogen wurde. Das ist definitiv das Ende des Ladevorgangs und sollte zu einer Schlussmeldung samt einer Information über die bezogene Energiemenge und vielleicht weiterer Daten (Dauer, Temperatur etc) führen.

Allerdings kann der Abstand zwischen "Anstecken" und "Laden startet" sehr kurz sein. Es kann also sein, dass ein Statuswechsel unerkannt bleibt. Am einfachsten visualisiert man die Logik in einem "Status-Diagramm samt den Übergängen:

Die Übergänge 5 und 6 passieren eigentlich nicht, denn jeder Wechsel geht immer über den "Fahrzeug verbunden"-Status. Zumindest ist es bei mir so, dass ich das Auto einstecke, dann lädt es nicht sofort, sondern das Fahrzeug "verhandelt" erst einmal und wartet, bis der Stecker verriegelt ist. Den Übergang "5" gibt es so auch nicht, denn erst wenn die Ladung beendet ist, wird der Stecker freigegeben. Auch hier geht die Statusänderung immer über den Status "Fahrzeug verbunden". Allerdings ist der Status dann nicht sehr lange gültig und eine Software, die nur jede Minute nachfragt, könnte diesen Zwischenstatus übersehen. Daher muss ich schon damit umgehen, dass zwei Auslesungen den Weg 5 oder 6 laufen. Gültige Werte von "evse_state" sind:

Status evse_state
Kein Auto angeschlossen

1

Fahrzeug nur verbunden

2,4,8,9

Fahrzeug verbunden und lädt

10,11

Die Zeit zwischen zwei Abfragen muss kurz genug sein, um die gewünschten Änderungen beim Statuswechsel zu erkennen aber übertreiben wollten wir es auch nicht.

POC mit PowerShell

Zuerst wollte ich mal wissen, ob meine Überlegung korrekt ist und auf einem vollwertigen Computer kann ich z.B. mit PowerShell viel schneller so etwas als Prototyp entwickeln und testen. Ich möchte daher wissen wann...

  • ... eine Ladung nach dem Anstecken startet
    Das passiert also immer, wenn sich der Status von einem Wert ungleich 10/11 auf einen Wert 10/11 ändert. Das passt aber noch nicht ganz, um einen Neustart zu erkennen.
  • ... ein Fahrzeug nach der Ladung abgesteckt wird., z.B. mit den bezogenen kWh
    Das sollte durch einen Wechsel auf 1 von einem Status 2,4,8,9,10 oder 11 sein. Ein Wechsel vom Status 0 (Wallbox startet) aber nicht.
  • ... eine Ladung erneut startet. Dann wurde die Ladung ja unterbrochen.
    Dazu müsste ich aber mir merken, ob zwischen der letzten Ladung wirklich einmal der Status 1 erreicht wurde.

Also muss ich per Software regelmäßig den "evse_state" einlesen´, mit dem vorherigen Status vergleichen und entsprechend protokollieren. Das Skript wird natürlich "als Bot" arbeiten. daher musste ich vorab erst einmal

  • Bot in Telegram anlegen und APIKEY übernehmen
    Das habe ich auf Telegram API schon ausführlicher beschrieben, so dass ich hier nur kurz die Konversation mit dem "botfather" als Bild ausgeben und natürlich ist der APIKEY unkenntlich gemacht.

    Diesen Wert übertrage ich in den Parameter "$telegramapikey" des Skripts. An den Standardeinstellungen des Bots (Privacy etc) ändere ich nichts.
  • Telegram -Gruppe anlegen
    Ich könnte nun einen 1:1 Chat mit dem Bot beginnen und die Chat_ID in meinen Bot übernehmen. Da es aber auch zwei oder mehr Nutzer geben kann, bietet sich eine eigene private Telegram-Gruppe an, in die ich den Bot addiere. Nun kann ich als Gruppenadministratoren auch andere Telegrambenutzer dynamisch in die Gruppe hinzufügen oder entfernen ohne am Code etwas zu tun. An den Standardeinstellungen der Gruppe (Privacy) ändere ich nichts. Der Bot kann z.B. so keine Meldungen der Gruppe empfangen, was ich aber auch nicht brauche.
  • GruppenID ermitteln.
    Der Bot muss aber etwas in die Gruppe senden und dazu braucht er eine Chat_ID ich muss in der neu angelegten Gruppe einmal eine Nachricht senden, die der Bot auch sehen kann. Normale Nachrichten sieht der Bot nicht aber Steuerungsnachrichten mit einem "/" als erstes Zeichen werden ihm gemeldet. Also sende ich meine erste Nachricht an die Gruppe:

    Diese Meldung kann ich per PowerShell direkt abrufen und die Chat_ID auslesen um sie ebenfalls in meinen Code zu übernehmen.:
[string]$telegramapikey ="hiermuss:ihr eigener telegram botAPIKey rein" 
(Invoke-Restmethod  -Uri "https://api.telegram.org/bot$($telegramapikey)/GetUpdates").result.message

message_id : 3
from       : @{id=123456789; is_bot=False; first_name=Frank; last_name=Carius; username=msxfaq; language_code=de}
chat       : @{id=-112233445; title=Wallbox2telegram; type=group; all_members_are_administrators=True}
date       : 1639924520
text       : /Start
entities   : {@{offset=0; length=6; type=bot_command}}

Nun habe ich den API-Key und eine Chat_ID um mit dem eigentlichen Programm zu beginnen. Eine erste Version, die einfach nur den Status per "Invoke-RESTMethod" ausgelesen und per Telegram versendet hat, war schnell erstellt. Der Code wurde umfangreicher, als ich die verschiedenen Statusänderungen ermitteln musste und dabei auch die ein oder andere Fehlerausgabe addiert habe. Dabei ist es aber nicht geblieben, denn das Skript sollte ja auch nach einem Neustart wieder aufsetzen, wozu ich den Status in einer Datei zwischenspeichern musste. Speziell bei der PowerShell-Version auf einem Computer habe ich dann noch etwas Code addiert, um die Änderungsvorgänge zusätzlich in eine CSV-Datei zu schreiben.

All diese Meldungen könnte die Wallbox natürlich auch noch an einen MQTT oder HTTP-Server senden. Ein einfacher HTTP-Zugriff auf einen Webserver mit den Daten als Parameter in der URL wird dieser in seinem Webserver-Log protokollieren. Dort können die Daten auch schnell wieder extrahiert werden. Oder man sendet die Daten direkt in eine Influx-DB oder anderes Backend.

Zuletzt habe ich dann doch noch Code addiert, um doch auch Befehle an den Bot für Diagnose-Zwecke zu verarbeiten und eine Hilfe zu liefern.

/Status liefert die JSON-Antwort der Wallbox
/Watt liefert die aktuell geladene Energie
/Ampere liefert den aktuellen Ladestrom

Das Skript werter aber genau genommen nur den ersten Buchstaben aus. Als ich dann gefühlt fertig war, habe ich noch festgestellt, dass der EVSE-Status der Wallbox durchaus unverändert auf 10/11 steht aber sich dennoch der bezogene Strom in Ampere ändert. Also erkenne ich nun auch Änderungen, wenn sich die Stromstärke um mehr als 5 Ampere verändert. Die Stromstärke ist ja durchaus dynamisch, wie die PRTG-Überwachung zeigt.

Gerade zum Ende zu nimmt die Stromstärke dann über 20 Minuten von 15A auf 1A ab. Mit 1A Delta wären dann 15 Meldungen. Der Wert ist über Parameter aber anpassbar. Die Zukunft wird zeigen, welche Anpassungen ich an dem Skript noch machen muss.

Wenn man dann noch mehrere "If/ElseIf/ElseIf/Elseif/Else"-Konstruktionen hat, sollte man aufpassen dass die späteren ElseIf-Bedingungen nicht von vorherigen Bedingungen schon abgefangen werden. So habe ich gemerkt, dass "Disconnect" nie zum Tragen gekommen ist, weil vorher schon die Bedingungen auf "EVSE-State Change" zugeschlagen hat. Zudem macht "Convertfrom-json" aus einem "false"-String im Objekt ein boolean mit "$false". Ein Vergleich der Werte in der Form $false -eq "false" liefert leider kein True. (Siehe auch PS JSON). Aktuell gibt es auch noch eine "Debug"-Ausgabe auf der Konsole für weitere Analysen.

Sie sieht man gut, dass auch beim Start der Ladung eine wenn auch sehr kurze "OnRamp"-Phase steht und gegen Ende das Auto kontinuierlich den Bezug reduziert. Ein Skript könnte anhand der Verlaufskurve zumindest gegen Ende feststellen, ob das Auto auch voll geladen wurde.

So ist das Skript am Ende dann doch deutlich länger geworden, als es am Anfang den Anschein hatte.

Download reiche ich nach, sobald der Code alle Sonderfälle erkannt hat.

Nach dem Download müssen Sie natürlich die richtigen Parameter für ihre Wallbox und den Telegram-APIKEY und die Telegram-CHAT_ID hinterlegen und dann das Skript auf einem Computer mit PowerShell Code und HTTP-Zugriff zur Wallbox und HTTPS zu Telegram starten.

Meldungen

Diese aktuelle Version läuft nun erst einmal einige Tage und Ladevorgänge um zu sehen, ob die Funktion und Parameter so passen. Daher ist auch noch etwas "Debug-Code" aktiv. Hier ein Verlauf

Nachrichtenverlauf Bedeutung

Die Ausgangssituation ist ein voll geladenes Fahrzeug an der Wallbox.

  • 10:29:54 Agent gestartet
    Als Funktionstest und um Neustarts zu erkennen, sende ich einmalig ein Hallo. Hier fehlt mir noch der aktuelle Status.
  • 12:00:47 Auto wird abgesteckt
    Das Auto war schon voll geladen aber mit dem Abstecken endet der Ladevorgang und das Skript kann den Wert aus "session_energy_wh" mit überliefern.
  • 14:09:52 Auto kommt zurück und wird angesteckt
    Am Anfang verhandeln die Geräte aber erst einmal die Fähigkeiten. Daher fließen laut Tesla nur 0,2A und der Wert von "session_energy_wh" wird zurück gesetzt. Intern ist der evse_state= 2 (Angeschlossen, nicht bereit)
  • 14:10:02 Das Auto hat den Status von "nicht bereit" auf "Bereit" geändert (evse_state= 8) aber lädt noch nicht.
  • 14:10:13 Ladung mit 14,1A (bis 11kW) startet
  • 15:17:18 Auto wird aufgeschlossen
    Es unterbricht die Ladung und gibt den Stecker frei
  • 15:17:29 Auto getrennt
    Dieser Ladevorgang hat "nur" 3,6kWh geladen. Die Batterie war nicht voll, da vorher die Reduzierung des Ladestroms nicht gemeldet wurde.

Insofern hilft die Meldung schon einmal, die Aktivitäten an der Wallbox zu erfassen und per Telegram zu melden. Natürlich habe ich im PowerShell-Script auch noch einen Datei-Export eingebaut, der die gleichen Meldungen in eine CSV-Datei schreibt:

"datetime","State","evse_state","vehicle_connected","Message","telegram_updateid","LastWh","LastA"
"2021-12-22 11:00:47Z","Disconnect","1","False","Disconnected:Charging ended. Total Energy (4.0771 kWh)","0","4077,1","0,3"
"2021-12-22 13:09:52Z","Change","2","True","Connected:Not Loading (0.2 Ampere) (0) kWh","0","0","0,2"
"2021-12-22 13:10:02Z","Change","8","True","Connected:Not Loading (0.2 Ampere) (0) kWh","0","0","0,2"
"2021-12-22 13:10:13Z","Change","10","True","Connected:Loading limited with 14.1 Ampere) (0.0018) kWh","0","1,8","14,1"
"2021-12-22 14:17:18Z","Change","8","True","Connected:Not Loading (0.3 Ampere) (3.5969) kWh","0","3596,9","0,3"
"2021-12-22 14:17:28Z","Disconnect","1","False","Disconnected:Charging ended. Total Energy (3.5969 kWh)","0","3596,9","0,3"

Neben den einfachen "Meldungen" stehen hier auch die Rohdaten wie Ampere, kWh, der EVSE-State u.a. für weitere Auswertungen bereit. Irgendwann muss ich dann mal prüfen, welche Messung "genauer" ist.

Energieverbrauch

Ich habe das Skript auf meinen PC laufen lassen und mit "Get-Process" nach ein paar Tagen dann ein paar Tage laufen lassen.

System Messwerte

Windows 10 Desktop

Auf meinem Windows 10 Notebook konnte ich nach ca. 3 Tagen folgenden Mittelwert messen.

PS C:\> ((get-date) - (get-process -id 42456).startt285706,563595

PS C:\> (get-process -id 42456).TotalProcessorTime.totalseconds
222,078125

PS C:\> 222/285706
0,00070777022533653476

Das sind grade mal 0,07% oder 0,7‰ der verfügbaren CPU-Zeit. Dafür sollte man nicht wirklich einen Windows PC "idle" durchlaufen lassen. Denn "tief schlafen" kann er so natürlich dennoch nicht, auch wenn ein gut konfigurierter PC durchaus mit wenigen Watt auskommen kann.

Raspberry

Das Skript nutzt nur PowerShell Core Funktionen und kann daher problemlos auch auf einem Raspberry genutzt werden. Ich habe dazu einen Raspberry 4B mit 4GB Ram genutzt und die PowerShell 7.2.1 installiert. Auch hier kann ich nicht nur das Skript starten sondern mit GetProcess auch die Benutzung auslesen.

Hier komme ich auf ca. 0,1% oder 1‰ CPU-Last, wenn das Skript alle 10 Sekunden die Wallbox abfragt.

Die Gesamt-CPU-Last laut Linux Taskmanager über eine RDP-Verbindung lag bei 1-3%. Auch ein Linux hat ja eine "Grundlast". Allerdings reagiert die PowerShell mit einem "System.OutOfMemoryException", wenn die Wallbox nicht erreichbar ist.

Hier muss ich den Code noch etwas robuster machen oder das Skript immer mal wieder neu starten.

ESP32/8266

Code noch nicht fertig. Noch keine Ergebnisse. Erwarte aber einen viel geringeren Energiebedarf.

ESP-Version

Auf Dauer wollte ich natürlich für diese "einfache Aufgabe" erst einmal keinen PC mit PowerShell laufen lassen. Die regelmäßigen Abfragen, JSON-Auswertungen und den Versand per Telegram kann ja auch ein kleiner Mikroprozessor vom Schlage eines ESP8266 oder ESP32 übernehmen. Das PowerShell-Script könnte man sicher auch direkt auf einem Raspberry laufen lassen, aber dann hat man wieder eine deutlich teurere Lösung mit einem vollwertigen Betriebssystem, welches auch immer mal wieder mit Updates und Fixes versehen werden muss.

Daher finde ich es interessanter, diese klar umrissene Funktion als nativem Code auf einem ESP oder Microbit o.ä. umzusetzen. Das hätte den Vorteil, dass so eine Lösung mit minimalem Stromverbrauch und unschlagbar günstigen Beschaffungskosten sogar als schlüsselfertige Lösung von vielen Besitzern einer Wallbox genutzt werden könnte. Es gibt ja z.B. von M5Stack nette Geräte oder auch die ein oder anderen ESP8266-basierte Consumer-Geräte, die zweckentfremdet werden könnten. Über eine kleine RGB-LED oder sogar eine LCD-Anzeige könnte das Gerät auch die Kennzahlen der Wallbox direkt anzeigen.

Der nächste Schritt ist sicher die Übertragung des Code in C++ oder MicroPython, um einen kleinen Microprozessor damit zu befüllen.
Dazu warte ich aber noch etwas die Erfahrungen aus dem Dauerbetrieb ab.

Weitere Links