Anbindung von Kia UVO an fhem

Begonnen von Eckat, 15 Februar 2021, 08:53:19

Vorheriges Thema - Nächstes Thema

Eckat

Moin moin  :)

Entweder ist das hier eine Frage weil ich zu dusselig zum Suchen bin oder es gibt tatsächlich noch nichts.

In ein paar Tagen kommt mein Kia e-Niro, also ein rein elektrisches Auto.
Dieses hat die Kia UVO Connect Funktionalität, mit der man über eine Smartphone App den Zustand des Auto überwachen und einige Dinge fernsteuern kann.
Aktuell wäre mir das Auslesen des Ladezustands des Akkus (SoC) am wichtigsten.

Gibt es dazu schon ein Modul für fhem, dass die Anbindung realisiert?

Kurz noch zum Hintergrund.

Ich habe eine PV-Anlage mit SMA Wechselrichter und einer Tesla Powerwall 2. Dazu zwei go-eCharger als Wallboxen.
Alles ist erfolgreich an fhem angebunden und funktioniert.
Nun war mein Plan, da ich mehr oder weniger täglich wechselnd Home-Office und Präsenzarbeit mache, das Laden so zu automatisieren, dass folgende Punkte berücksichtigt werden:

  • Je Wochentag möchte ich den mindest Akku-Ladestand hinterlegen
  • Das Auto soll über den PV-Überschuss immer geladen werden, damit der Strom im Auto-Akku und nicht im Netz landet
  • Wenn nach Sonnenuntergang der Akku-Ladestand nicht den erforderlichen Wert für den nächsten Morgen erreicht hat, wird über Netzbezug der Rest nachgeladen

Das ist auch alles soweit kein Problem.
Nur kann ich nicht, wie ich das (ohne Recherche) erwartet hatte, den Akku-Ladestand über den go-eCharger abfragen.  ???
Dazu bräuchte ich die Anbindung an das Kia UVO Connect.

Hinweis:
Grundsätzlich scheint das möglich zu sein: https://github.com/wcomartin/kiauvo
Ja, ich weiß das fhem nicht in Python geschrieben ist  ;)

Wenn es nichts gibt, werde ich mich mal daran setzen.
Jedoch sind meine perl-Kenntnisse ... *räusper* ... überschaubar.  :D

Vielen Dank und viele Grüße
Carsten

Det20

#1
https://github.com/wcomartin/kiauvo/blob/master/KiaUvo/__init__.py


base_url = 'https://www.myuvo.ca/tods/api/'
url = self.base_url + 'vhcllst'

req = requests.post(url, headers=headers, data=json.dumps({}))
return [self.get_vehicle_status_by_id(x['vehicleId']) for x in req.json()['result']['vehicles']]


So wie es aussieht, haben die ne API. Aufruf via HTTPS/XHR, Ergebnis ist JSON.
Werde mir das mal anschauen, wenn mein Sorento da ist. Könntest du aber, wenn das so funktioniert, auch schmerzfrei in PHP o.ä. nachbauen.

gadget

Ich häng mich hier mal an. e-soul soll demnächst ausgeliefert werden.

gadget

#3
Mein kia e-soul steht jetzt in der Garage.

Mit https://github.com/Hacksore/bluelinky habe ich es schon mal hinbekommen, mit dem debug-Skript Daten auszulesen (SOC, Voraussichtliche Reichweite usw.)
Ich bekomme sogar den Kilometerstand, den zeigt mir nicht mal die UVO App. Bezüglich nodejs bin ich aber völlig ohne Plan wie ich da jetzt zumindest mal ein CLI-Tool o.ä. draus ableite, das mir die interessanten Daten nach fhem bringt.

Irgendwer hat scheinbar auch mal angefangen, die Daten aus UVO nach MQTT zu übersetzten ( das wäre eigentlich recht elegant und universell), aber da gab es seit 6 Monaten keinen Update. https://github.com/fredrikedling/bluelink_mqtt

Update: Habs inzwischen hingefrickelt bekommen. Die Daten aus UVO, die mich interessieren (km-Stand, SOC, SOC der 12V Hilfsbatterie, Reichweite) landen jetzt per MQTT sowohl in fhem als auch in Home Assistant. Die Aktualisierungsfrequenz mache ich abhängig davon ob der Stromer an der Wallbox hängt oder nicht.

Eckat

Zitat von: gadget am 03 April 2021, 16:43:34Update: Habs inzwischen hingefrickelt bekommen. Die Daten aus UVO, die mich interessieren (km-Stand, SOC, SOC der 12V Hilfsbatterie, Reichweite) landen jetzt per MQTT sowohl in fhem als auch in Home Assistant. Die Aktualisierungsfrequenz mache ich abhängig davon ob der Stromer an der Wallbox hängt oder nicht.

Na toll ... das ist mein "eigener" Thread, aber aus irgendwelchen Gründen waren die Benachrichtigungen nicht aktiv  :o

Könntest du das mit der MQTT Anbindung für UVO näher erläutern?

gadget

#5
Zitat von: Eckat am 27 April 2021, 14:45:43
Könntest du das mit der MQTT Anbindung für UVO näher erläutern?

Ich habe auf dem Raspi (Raspian Stretch 9.13) , auf dem auch fhem läuft, unter dem User pi  bluelinky https://github.com/Hacksore/bluelinky installiert.
npm und nodejs hatte ich eh schon drauf.


Falls noch nicht vorhanden:



sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nodejs npm
sudo npm cache clean -f
sudo npm update npm -g
sudo npm install -g n
sudo n stable

sudo shutdown -r now

npm --version
6.14.12
node --version
v10.24.1



Bluelinky dann installiert (als User pi) mit



mkdir /home/pi/bluelinky
cd /home/pi/bluelinky
npm install bluelinky
npm install async-mqtt




Weiterhin habe ich sowieso einen eingenständigen MQTT Server laufen (Mosquitto), aber hierfür würde der fhem-eigene MQTT2_SERVER auch locker ausreichen.

Benötigt werden:

Ip-Adresse des MQTT-Servers  MQTTIP
Port des MQTT-Server MQTTPORT  (üblicherweise 1883)
Username MQTT-Server:  MQTTUSER
zugehöriges Passwort: MQTTPW

Von UVO braucht man

UVO-Username:  UVOUSER
UVO-Passwort: UVOPW
UVO-Pin:  UVOPIN
Die VIN des Autos: UVOVIN



Als MQTT-Topic verwende  ich BluelinkCarStatus/VIN

Als Vorlage für mein Skript habe ich bluelinky-mqtt-ha verwendet.

Die ganzen Zugangsdaten habe ich direkt in mein Skript (kia.js) geschrieben (  !! ich habe von Javascript so gut wie keinen blassen Schimmer !!).  Das ist von der Sicherheit her eher unschön. Man kann mit den Daten ja z.B. das Auto entriegeln und den Standort abfragen ....

Die kia.js  schaut dann so aus und liegt in /home/pi/bluelinky


const BlueLinky = require('bluelinky');
const MQTT = require("async-mqtt");

const client = new BlueLinky({
  username: 'UVOUSER',
  password: 'UVOPW',
  brand: 'kia',
  region: 'EU',
  pin: 'UVOPIN'
});

client.on('ready', async () => {
  const vehicle = client.getVehicle('UVOVIN');
  try {
    const odo = await vehicle.odometer();
    console.log(odo); 
    const status = await vehicle.status({ parsed: false, refresh: true });
    console.log(status);
    const location = await vehicle.location();
    console.log(location);

    const mqttClient = await MQTT.connectAsync("mqtt://MQTTIP:MQTTPORT", { username:"MQTTUSER", password:"MQTTPW" })
    console.log("Sending to MQTT server");
    if ((status.evStatus.batteryStatus > 0) && (odo.value > 0)) {  // wird gelegentlich falsch mit 0 ausgelesen, dann nicht senden
        try {
                var options={
                retain:true,
                qos:1};
                await mqttClient.publish(
                   "BluelinkCarStatus/UVOVIN",
                   JSON.stringify({
                     odo: odo.value,
                     soc: status.evStatus.batteryStatus,
                     range: status.evStatus.drvDistance[0].rangeByFuel.evModeRange.value,
                     locked: status.doorLock,
                     battery12V: status.battery.batSoc,
                     longitude: location.longitude,
                     latitude: location.latitude,
                   }),options
                );

                // This line doesn't run until the server responds to the publish
                await mqttClient.end();
                // This line doesn't run until the client has disconnected without error
                console.log("mqtt call Done");
        } catch (e){
                // Do something about it!
                console.log(e.stack);
                process.exit();
        }
    } // if
  } catch (err) {
    // log the error from the command invocation
  }
});

client.on('error', async (err) => {
  // something went wrong with login
});


Auf Kommandozeile kann man dann als user pi ausführen mit


cd /home/pi/bluelinky
node kia.js


Auf fhem Seite nimmt dieses MQTT-Device die Daten dann entgegen:
UVOVIN natürlich wieder mit der eigenen VIN ersetzten, IODev auf das passende MQTT2_SERVER Device verweisen, wenn man den fhem-eigenen MQTT-Server verwendet ist das i.d.R. m2s.


defmod kia MQTT_DEVICE
attr kia DbLogInclude .*
attr kia IODev mein_MQTT_Server
attr kia autoSubscribeReadings BluelinkCarStatus/+
attr kia group Auto
attr kia icon car
attr kia stateFormat SOC: UVOVIN_soc % Reichweite: UVOVIN_range km km-Stand: UVOVIN_odo km
attr kia subscribeReading_UVOVIN BluelinkCarStatus/UVOVIN
attr kia userReadings battery {ReadingsNum($name,"UVOVIN_battery12V","") > 30 ? "ok" : "low"},\




Und mit diesem Helper werden aus den JSON-Strings Readings:


defmod ej_kia expandJSON kia:.*
attr ej_kia addReadingsPrefix 1
attr ej_kia addStateEvent 1
attr ej_kia room hidden


und mit diesem Mechanismus starte ich das Skript regelmäßig (sollte man nicht allzu oft machen weil der UVO-Account dann irgendwann geblockt wird)


defmod getuvo dummy
attr getuvo event-on-change-reading state
attr getuvo icon car
attr getuvo room Zeitsteuerung
attr getuvo webCmd on:off

defmod di_uvoUpdate DOIF ## Alle 40 min wenn kein Ladevorgang\
( ([+:40]) and ([?goeCharger1:state] ne "charging") and ([?goeCharger2:state] ne "charging"))\
   (set getuvo on) \
   (set getuvo off) \
DOELSEIF\
## Alle 20 Minuten bei Ladevorgang\
( ([+:20]) and (([?goeCharger1:state] eq "charging") or ([?goeCharger2:state] eq "charging")))\
   (set getuvo on)\
   (set getuvo off)\

attr di_uvoUpdate do always
attr di_uvoUpdate room Zeitsteuerung
attr di_uvoUpdate wait 0,30:0,30

defmod getuvoOn notify getuvo:on {system ("cd /home/pi/bluelinky && node kia.js &")}
attr getuvoOn room Zeitsteuerung



Grüße, gadget

Eckat

Vielen, vielen Dank  :)

Da habe ich ja am Wochenende was zu tun  ;D

Det20

#7
Hallo,

inzwischen ist mein Sorento da und natürlich möchte ich auslesen/steuern, was geht.
Das Script habe ich soweit angepasst, allerdings passiert ... nix.

Mit dem MQTT habe ich noch nie etwas gemacht, hoffe, alles so eingestellt zu haben, wie es sein muss (allowed-Device fehlt hier).

Ein Device wird nicht automatisch angelegt und "nrclients" bleibt auch bei 0, Reading wird auch nicht auf aktuelle Uhrzeit aktualisiert, da kommt also nix an. Wenn ich mich per Telnet verbinde, wird zumindest die Uhrzeit vom Reading aktualisiert.


Internals:
   Clients    :MQTT2_DEVICE:MQTT_GENERIC_BRIDGE:
   ClientsKeepOrder 1
   DEF        1883 global
   FD         22
   FUUID      60d308de-f33f-4070-f6f3-39c86e9a91108539
   NAME       MQTT2_FHEM_Server
   NR         1282
   PORT       1883
   STATE      Initialized
   TYPE       MQTT2_SERVER
   .attraggr:
   .attrminint:
   MatchList:
     1:MQTT2_DEVICE ^.
     2:MQTT_GENERIC_BRIDGE ^.
   READINGS:
     2021-06-23 12:22:27   lastPublish     BluelinkCarStatus/xxxxxxxxxxxxxxxx:
     2021-06-23 12:29:36   nrclients       0
     2021-06-23 12:29:36   state           Initialized
   clients:
   retain:
Attributes:
   autocreate simple


Habe im Script (kia.js) gesehen, dass dort MQTT verwendet wird, nicht MQTT2. Macht das einen Unterschied?

Oder gibt es einen anderen Weg als das NODE Teil?

VG

gadget

Funktioniert denn die Abfrage der Daten bei UVO prinzipiell wenn du node kia.js auf der Kommandozeile ausführst ?
Ob überhaupt was an den MQTT Server gesendet wird kannst Du z.B. mit dem https://mqtt-explorer.com/ überprüfen.
Wofür hast Du eine MQTT_GENERIC_BRIDGE angelegt ?

Det20

Zitat von: gadget am 23 Juni 2021, 14:15:25
Funktioniert denn die Abfrage der Daten bei UVO prinzipiell wenn du node kia.js auf der Kommandozeile ausführst ?

Da kommt nix. Kein Output, kein Fehler, einfach 5 sekunden lang Pause und dann direkt wieder Prompt. Ohne irgendwelchen output.

Zitat von: gadget am 23 Juni 2021, 14:15:25
Wofür hast Du eine MQTT_GENERIC_BRIDGE angelegt ?

Habe ich nicht oder nicht mit Absicht. Erstellt wird er mit


defmod MQTT2_FHEM_Server MQTT2_SERVER 1883 global
attr MQTT2_FHEM_Server autocreate simple
attr MQTT2_FHEM_Server room AAA
attr MQTT2_FHEM_Server verbose 5

xerion

Zitat von: Det20 am 23 Juni 2021, 14:21:58
Da kommt nix. Kein Output, kein Fehler, einfach 5 sekunden lang Pause und dann direkt wieder Prompt. Ohne irgendwelchen output.

Habe ich nicht oder nicht mit Absicht. Erstellt wird er mit


defmod MQTT2_FHEM_Server MQTT2_SERVER 1883 global
attr MQTT2_FHEM_Server autocreate simple
attr MQTT2_FHEM_Server room AAA
attr MQTT2_FHEM_Server verbose 5


Dann hast du ein grundsätzliches Problem was nichts mit FHEM zu tun hat, die Frage wäre eher bei Bluelinky aufgehoben. Ich vermute aber es liegt daran, das dein Token nicht passt. Arbeite dich hier mal durch, dann bekommst du auch Logausgaben was das Problem ist:

https://github.com/Hacksore/bluelinky#debug-locally
Ich würde mich  freuen, wenn du meinen Einladungscode für Tibber, der Stromanbieter, der dir hilft, deinen Stromverbrauch zu verstehen und zu reduzieren, nutzt: https://invite.tibber.com/5fc08jbs. So bekommen wir beide 50 Euro und 100 % Ökostrom / https://geld-fuer-eauto.de/ref/334561880

Det20

Kenne mich in Node so überhaupt mal garnicht aus, ist (ich oute mich) hauptsächlich Copy-and-Paste.
Eben zumindest mal einen Output bekommen:


Register request has failed with Error=PHONE_REGISTRATION_ERROR


gadget

Schau noch mal genau, ob Du alles richtig im Skript eingetragen hast im kia.js
Mich wundert es etwas, dass Du noch nicht einmal einen Login Error o.ä. bekommst.
Skript auch unter Linux mit vi oder nano erzeugt und nicht unter Windows ( -> CRLF Zeilenenden etc ....) ?

gadget

Zitat von: Det20 am 23 Juni 2021, 14:31:43

Eben zumindest mal einen Output bekommen:


Register request has failed with Error=PHONE_REGISTRATION_ERROR


Das hatte ich auch öfters. Mach nochmal ein


npm install bluelinky
npm update

Det20

Mit Nano. Also unter "client" sind meine Login-Daten angegeben, die ich auch in der "UVO 2021" App verwende. Brand ist "kia", "region" ist "EU". Pin ist der, den ich auch zur Steuerung in der App eingeben muss. Unter "vehicle = client.getVehicle" ist die Fahrzeugnummer hinterlegt. Bleibt nur nut "mqttClient = await MQTT.connceptAsync", dort ist die IP vom FHEM bzw Raspberry sowie Benutzername/Kennwort vom Allowed-Device hinterlegt. Mehr kann ich dort ja eigentlich nicht machen.