Projektvorstellung: Überschussladen durch Tesla API und "dumme" Wallbox

Guten Morgen Miteinander,

Ich bin seit einer Woche glücklicher Besitzer eines Model Y. Zudem bekam ich von einem Freund eine Wallbox(Webasto Pure 22kw) geschenkt, die Anscheinend vom LKW gefallen ist :smile:
Ich habe schnell herausgefunden, dass die Wallbox wohl nicht sonderlich intelligent ist, wollte aber, dass mein Auto nur lädt, wenn die PV-Anlage genügend Strom liefert. Mein erster Gedanke war ein einfaches Schütz, welches die Wallbox scharf schaltet, sobald genug Strom vorhanden ist. Da ich aber ein unglaublich fauler Mensch bin und überhaupt keine Lust hatte, nochmal ein extra Kabel von meiner SPS(Siemens S7-300) zu legen, suchte ich im Internet nach anderen Lösungen. Gefunden habe ich die unoffizielle Tesla API welche mir ermöglicht den Ladestrom meines Autos Programmiertechnisch zu ändern. Na ja genau gesagt habe ich 2 Seiten gefunden die von sich behaupten, die TESLA API entschlüsselt zu haben. Eine (teslaapi,io (Komma zu Punkt machen. Darf anscheinen nur 2 Links Posten)) war sehr einfach gehalten und versprach durch einfach JSON Pakete, welche ich an den Tesla Server schicke mein Auto steuern zu können. Hab mich natürlich gleich dran gemacht und in Java los programmiert. Ergebnis: Es funktioniert überhaupt nichts. Eine kurze Recherche ergab, dass diese API veraltet ist und Tesla vor einiger Zeit einige Neuerungen hinzugefügt hatte. Die Neuerungen waren wesentlich komplexer und waren auf der 2. Seite (https://tesla-api.timdorr.com/) zu finden. Meine reaktion: Gar kein Bock…

Eigentlich wollte ich alles in Java programmieren, weil ich dort Zuhause bin. Ich fand aber eine Bibliothek in Python die alles sehr einfach macht. (TeslaPy GitHub - tdorssers/TeslaPy: A Python module to use the Tesla Motors Owner API) Leider habe ich noch nie richtig in Python programmiert, wollte aber endlich eine „Quick and Dirty“ Lösung für mein Lade-Problem.

Ich möchte hier mit euch meinen Quellcode teilen, falls jemand etwas Ähnliches vorhat und nach Input sucht. Das Prinzip ist relativ einfach. Meine SPS (Kann auch etwas anderes sein) sendet an das Programm über UDP(Port:2000) einen Integer, welcher die aktuelle Leistung meines Betriebs widerspiegelt. Ist diese Negativ (d.h. Ich speise ein) weis mein Tesla, falls er am Ladekabel hängt, dass er zum Laden anfangen darf. Da ich die Tesla API nicht überrennen will und auch nicht will, dass mein Auto 10x die Sekunde etwas an der Elektrik ändert, habe ich eine Schonzeit von 60 sek zwischen den Befehlen eingebaut. Das Programm ist sicher nicht Perfekt, läuft bei mir aber seit 2 Tagen recht stabil. Ich nehme sehr gerne Kritik an.

Viel Spaß
Gruß
Marini

from http import server
from time import sleep
import teslapy
import socket

tesla = teslapy.Tesla('[email protected]')
#Anmelden bei Tesla API
if not tesla.authorized:
    print('Use browser to login. Page Not Found will be shown at success.')
    print('Open this URL: ' + tesla.authorization_url())
    tesla.fetch_token(authorization_response=input('Enter URL after authentication: '))
vehicles = tesla.vehicle_list()

#Verbindung mit SPS herstellen
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("192.168.0.127",2000))

print('Verbindung mit SPS wird aufgebaut...')
print('Verbindung wurde hergestellt. Warte auf Daten...')
while True:
     sock.settimeout(None)
     data, addr = sock.recvfrom(4) 
     sock.settimeout(0.2)
     #Buffer löschen um immer aktuellste Stromaufnahme zu erhalten
     while 1:
        try:
            data, addr = sock.recvfrom(4) 
            #print('Buffer Cleard: '+str(data))
        except:
            break

     betriebsstrom = int.from_bytes(data,'big',signed=True)
     print("Leistungsaufnahme Betrieb Gesamt: " +str(betriebsstrom)+ ' w')

    #Daten von Tesla empfangen
     try:
        vehicles[0].get_vehicle_data()
     except:
        print('Daten konnten nicht von Tesla empfangen werden')
        continue

     ladezustand=vehicles[0]['charge_state']['charging_state']
     #print('Aktueller ladezustand Tesla: '+ladezustand)
    #Fahrzeug nicht verbunden
     if ladezustand=='Disconnected':
        print("Fahrzeug nicht an Ladestation angschlossen\nAutomatische Laden nicht möglich")
        sleep(60)
        continue
    #Fahrzeug verbunden. Lädt aber nicht
     if ladezustand=='Stopped' or ladezustand=='Connected':
        

        #Genug Strom für start des Ladevorgangs
        if betriebsstrom < -3450: #3450 w entspricht ca 5A Ladestrom für Tesla
            #226V wurden am Ladepunkt gemessen. Wahrscheinlich durch Spannungsfall
            ready_amps = (betriebsstrom/(3*226))*-1
            #Ampere berreich einschränken
            if ready_amps>16:
                ready_amps=16
            if ready_amps<5:
                ready_amps=5
            try:
                vehicles[0].command('START_CHARGE')
                sleep(3)
                vehicles[0].command('CHARGING_AMPS',charging_amps = int(ready_amps)) 
            except:
                print('Commando Fehler: Ladevorgang konnte nicht gestartet werden')
                continue

             
            print('Ladevorgang wurde gestartet! Gesetzte Ampere: '+str(int(ready_amps))+' A')
            sleep(60)
            continue
        print('Tesla bereit zum Laden...')
        sleep(60)
      #Fahrzeug verbunden und lädt  
     if ladezustand=='Charging':
        
        print("Fahrzeug lädt...")
        ladestrom = vehicles[0]['charge_state']['charger_actual_current']
        ladespannung = vehicles[0]['charge_state']['charger_voltage']
        #phasenzahl = vehicles[0]['charge_state']['charger_phases']
        ladeleistung = ladestrom*ladespannung*3
        differenzleistung = betriebsstrom-ladeleistung

        print('Betrieb ohne Tesla: '+ str(differenzleistung)+' w')
        print('Aktuell Ladeleistung '+str(ladeleistung)+ ' w')
        print('Aktueller Ladestrom ' + str(vehicles[0]['charge_state']['charger_actual_current'])+ ' A')
        print('Aktueller Ladespannung ' + str(vehicles[0]['charge_state']['charger_voltage'])+ ' V')
        #Ampere Anpassen
        if differenzleistung < -3000:
            if ladespannung<=0:
                ready_amps = (differenzleistung/(3*230))*-1
            else:
                ready_amps = (differenzleistung/(3*ladespannung))*-1

            #Ampere berreich einschränken
            if ready_amps>16:
                ready_amps=16
            if ready_amps<5:
                ready_amps=5
            try:
                vehicles[0].command('CHARGING_AMPS',charging_amps = int(ready_amps)) 

            except:
                print('Commando Fehler: Ampere konnten nicht angepasst werden')
                continue
            
            print('Stromaufnahme Angepasst! Gesetzte Ampere: '+str(int(ready_amps))+' A')
            sleep(60)
            continue


        #Stoppen bei Netzbezug
        if differenzleistung > -3000:
            print('Zu hohe Stromaufnahme! Ladevorgang wird gestoppt. 5 Min Pause bis nächstmöglicher Start')
            try:
                vehicles[0].command('STOP_CHARGE')
            except:
                print('Commando Fehler: Ladevorgang konnte nicht gestoppt werden')
                continue

            
            sleep(300)
            continue
        
10 „Gefällt mir“