soc_helper
==========

Ein Programm, um den SOC eines VW e-up!  ohne WeConnect-Dienste in die
OpenWB zu bekommen.  Darüber hinaus besteht die Möglichkeit, den mit 10km
quantisierten Kilometerstand auszuwerten.  Eine automatisierte Übertragung
an Spritmonitor ist möglich.  Vermutlich lassen sich auch andere Fahrzeuge
mit diesem Programm an die OpenWB und spritmonitor anbinden.

Einschränkungen:

Obwohl die OpenWB in Software 2 verschiedene Autos unterscheiden kann, geht
soc_helper davon aus, daß immer dasselbe Auto geladen wird. Wenn das
Fahrzeug mit dem WiCAN in das heimische WLAN einbucht, wird der SOC der
Wallbox mit dem SOC des Fahrzeugs beschrieben, auch, wenn gerade ein anderes
Fahrzeug lädt. Vermutlich ließe sich die Funktionalität schnell auf mehrere
AUtos aufbohren.

Voraussetzungen für die Nutzung:

Hardware:
* Es muß ein Rechner im Hausnetz sein, der dauerhaft läuft.Ein
  Raspberry Pi Zero W unter Raspbian dürfte ausreichend sein.
* ein MeatPI WiCAN (https://www.meatpi.com/products/wican) muß im Fahrzeug
  an der OBD-Buchse gesteckt und konfiguriert sein (siehe weiter unten)
* Es muß eine konfigurierte OpenWB im Hausnetz sein

Software:
Auf dem System, auf dem der soc_helper laufen soll, müssen
* python3 und die python-Pakete
* paho-mqtt
* json
* requests (für die Nutzung von Spritmonitor)
installiert sein. Für die Pakete venv / pip nutzen.
Für die Konfigurationsphase kann das Programm MQTT-Explorer nützlich sein

Spritmonitor:
Für die Nutzung von Spritmonitor ist ein Konto bei Spritmonitor.de nötig; man
benötigt
* ein App-Token (wird für dieses Programm mitgeliefert) und
* ein persönliches Bearer-Token (auf der "Passwort-Vergessen"-Seite anzufordern)
* Es muß ein Fahrzeug angelegt sein, das schon eine Erstbetankung
  eingetragen hat.
* Die Fahrzeug-ID muß in der Konfigurationsdatei eingetragen werden.


Konfiguration

Konfiguration des WiCAN

ACHTUNG: Wenn man sich an den vom WiCAN aufgespannten Access Point
anmeldet, werden alle Einstellungen zurückgesetzt! Daher muß das Mobiltelefon
so konfiguriert werden, daß ein automatisches Einbuchen in diesen AP nicht
erfolgt! Der Zugriff auf den WiCAN darf nach WLAN-Konfiguration ausschließlich
über das Hausnetz erfolgen!
der Adapter muß wie folgt konfiguriert sein:
* Firmware 1.80 oder neuer (unter 1.78 hat der Schlafmodus bei mir nicht
  funktioniert)
* Modus AP+Station, damit er sich im Heimnetz anmeldet
* Die SSID und das Kennwort des Heimnetzes müssen passen
* Sleepmode muss aktiviert sein, damit der WiCAN 3 Minuten nach Rücknahme der
  Fahrbereitschaft in den Stromsparmodus geht
* MQTT muß aktiv sein
* Als MQTT-Broker muß die Adresse der OpenWB eingestellt sein
* Nutzer und Passwort für mqtt scheinen egal zu sein, dürfen aber wohl nicht
  leer bleiben.
* Als CAN-Modushabe ich ELM327 eingestellt - bin nicht sicher, ob das nötig ist.
  Auf jeden Fall kann man so mit der APP Car Scanner aus dem Heimnetzwerk die
  Fehlerspeicher auslesen ;-)
* CAN-Geschwindigkeit auf 500k

Konfiguration der OpenWB

* Die OpenWB muß ladefähig sein.
* Als SOC-Modul für das gewählte Fahrzeug muß Manuell (+Berechnung)
  ausgewählt sein


Nur für Spritmonitor-Nutzung: Konfiguration der Umgebungsvariablen

Das Spritmonitor-Bearer-Token wird aus Sicherheitsgründen nicht in die
Datei configuration.py eingetragen. Dies verhindert eine versehentliche
Weitergabe und damit Zugriff von anderen auf die eigenen Fahrzeuge. Damit
das Bearer-Token trotzdem genutzt werden kann, wird es als Umgebungsvariable
definiert, die das Programm einlesen kann. Hierzu muß in der Datei .profile
im Homeverzeichnis des Benutzers des Programms die Umgebungsvariable
exportiert werden. Die entsprechende Zeile sieht zum Beispiel so aus:
  export SPRITMONITOR_BEARER_TOKEN=<ganzLangesPersoenlichesToken>


Konfiguration von soc_helper in der Datei configuration.py

Hier werden verschiedene Konstanten definiert. Es kann
* Festgelegt werden, ob eine Nutzung von Spritmonitor erfolgen soll
* Die Daten, die für die Spritmonitor-Nutzung erforderlich sind sowie ein
  SOC, dessen Erreichen (+/-2 Prozentpunkte) eine Volladung signalisiert -
  dieser Wert sollte sich mit dem Ziel decken, bei dem die OpenWB das Laden
  beendet.
* die CAN-Botschaften, deren erwarteten Antworten und Geräte-IDs für die
  Anforderung des SOC und Kilometerstand
* Die relevanten Topics der OpenWB. Die in der Software 2 verwendeten IDs
  lassen sich auf der Statusseite der OpenWB einsehen.
* das Topic-Prefix des WiCAN,
* die IP-Adresse und das Zieltopic für den SOC in der OpenWB,
* die Kriterien für eine gültige SOC-Botschaft eingestellt werden.

In der Callback-Funktion cb_rx muß, sofern kein e-up! verwendet wird,
möglicherweise die Berechnung des SOC aus den CAN-Bytes angepaßt werden.


Aufruf:

* Zum Testen aufrufen mit <./soc_helper>. Die Augabe erfolgt dann auf der
  Konsole.
* Für den Dauerbetrieb auf einem Home-Server sollte der Start mit <nohup
  ./soc_helper&> erfolgen, damit das Programm beim Logout nicht beendet
  wird.  Möglicherweise mache ich irgendwann mal einen service daraus, ist
  aber unwahrscheinlich.

Funktionsweise

Wenn das Fahrzeug sich dem Heimnetzwerk nähert und mit dem WLAN verbindet,
sendet es eine MQTT-Message an einen Broker um zu signalisieren, daß es online
ist. Als Broker dient die OpenWB. Der soc_helper hat ein Abo auf diese Nachricht
und reagiert beim Empfang eine MQTT-Nachricht, die den WiCAN dazu veranlaßt, die
CAN-Botschaften mit dem Fahrzeug-SOC und dem Kilometerstand auszulesen.
soc_helper wiederum erkennt die Botschaften, extrahiert den SOC und schickt ihn
per MQTT an die OpenWB, um ihn in der MQTT-Struktur im passenden Fahrzeug zu
hinterlegen.

SOC und Kilometerstand werden nach Wechsel in den Online-Status bei Eintreffen
der entsprechenden Botschaft gespeichert. Der Zählerstand des Ladezählers
wird permanent per MQTT gesendet und dementsprechend quasi kontinuierlich in
der Datenstruktur abgelegt.  Beim Anstecken und beim Abstecken des Ladesteckers
merkt sich soc_helper den Stand des Energiezählers. Somit liegt nach dem
Abstecken die geladene Energiemenge vor und kann mit Hilfe des aktuellen
Kilometerstandes und des letzten gespeicherten Kilometerstandes von Spritmonitor
als "Betankung" ebendort hochgeladen werden.

Detaillierter Ablauf der Funktion

Mit Start von soc_helper abonniert dieser verschiedene Topics des
MQTT-Brokers auf der OpenWB.  Für die SOC- und Kilometerstandsübertragung
sind das
* wican/<ID>/status als Trigger für die SOC- und km-Abfrage des Fahrzeugs
* wican/<ID>/CAN/rx als Empfänger für die Antworten der SOC- und km-Anfragen
Für Daten der OpenWB sind das
* Das Topic, mit dem der SOC gesetzt werden kann
* Der Zustand des Ladesteckers, ob gesteckt oder nicht
* Der in der OpenWB verwendete SOC-Wert zur Bewertung, ob eine Volladung
  vorliegt.
* Der Stand des Ladezählers der OpenWB zur Berechnung der geladenen Energiemenge
Anschließend geht das Programm in eine Endlos-Warteschleife über.

Übertragung aus dem Auto

Wenn eine neue Botschaft unter wican/<ID>/status empfangen wird, wird die
Callback-Funktion cb_status aufgerufen.  Entspricht die empfangene Botschaft
{status:online}, hat sich der WiCAN in das Heimnetz eingebucht. 
Unverzüglich wird die in den Konstanten definierte CAN-Botschaft zum
Auslesen des SOC an die Wallbox geschickt, wo der WiCAN sie empfängt und dem
Fahrzeug zuschickt.  Beim Eintreffen der Antwort wird diese vom WiCAN
wiederum an die Wallbox geschickt, der soc_helper empfängt sie über das
Abonnement und die Funktion cb_rx wird aufgerufen.  Hier wird geprüft, ob es
eine passende Botschaft ist.  Handelt es sich um eine SOC-Botschaft, wird
dem definierten SOC-Topic der OpenWB der extrahierte SOC-Wert geschickt.
Wenn ein Kilometerstand ankommt, wird dieser im Programm gespeichert.

Beim Anstecken und Abstecken (für Spritmonitor-Nutzung)

<Text ist noch ähnlich dem oben, hier mehr in Details gehen>
Für den Ladevorgang entscheidend sind die Übergänge "Stecker wird gesteckt"
und "Stecker wird gezogen". Ein Ladevorgang wird definiert als die
Energiemenge, die zwischen Stecken und Lösen des Steckers von der OpenWB
abgegeben wird.
Wenn der Stecker gelöst wird, wird aus dem Energiezählerstand nach und vor
dem Einstecken die geladene Energiemenge berechnet. Über den letzten bei
Spritmonitor gespeicherten Kilometerstand und dem vor / beim Laden
ausgelesenen und gespeicherten Kilometerstand ergibt sich die
Streckendistanz. Diese Werte zusammen werden genutzt, um einen Eintrag bei
Spritmonitor anzulegen.

Beim e-up ist noch erwähnenswert, daß dieser beim Laden die
Niedervolt-Batterie ebenfalls lädt. Hierdurch wird ein schlafender WiCAN
geweckt, wenn die Ladung nach einiger Zeit startet. Es erfolgt das schon
beschriebene Spiel über Status, Kilometerstand und SOC. Die Werte können
also während der Stecker gesteckt ist, mehrmals ausgelesen und geschrieben
werden, sofern die Ladung z.B. durch mangelnde PV-Leistung unterbrochen wird.


Hilfreiche Links

Dokumentation und Quellcode des WiCAN: https://github.com/meatpiHQ/wican-fw
Bestellung WiCAN: https://eu.mouser.com/c/?m=MeatPi
CAN-Datenbank VW: https://www.goingelectric.de/wiki/Liste-der-OBD2-Codes/


Bekannte Fehler / Erweiterungswünsche:

* Aufbohren auf mehrere Fahrzeuge (und mehrere WiCAN) - das zuletzt aktive
  Fahrzeug kann wohl eher nicht automatisch in der OpenWB ausgewählt werden,
  da ein Fahrzeug gerade laden kann, während ein anderes sich ins WLAN
  einbucht.
* Auslesen des Ziel-SOC aus der OpenWB, um die Entscheidung "Vollgetankt"
  nicht doppelt konfigurieren zu müssen (in configuration.py und dem
  OpenWB-Interface
* Momentan wird von Spritmonitor "tripsum" der Abfrage
  /vehicle/{vehicleId}/tanks.json verwendet, was nicht notwendigerweise
  der Kilometerstand des Fahrzeugs ist. Das muß noch umgestellt werden auf
  "odometer" aus der Abfrage /vehicle/{vehicleId}/tank/{tankId}/fuelings.json
  
