-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
smarteq SOC Modul: 2FA, MBAPI #1582
base: master
Are you sure you want to change the base?
Conversation
Wie in bmwbc auf context handler umgestellt. |
Websocket interface hat seit 28.05.2024 nicht mehr funktioniert. |
Konflikt in requirements.txt behoben. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Das Logging wird so definitiv nicht gemergt.
Im Forum klappt es oft schon nicht, dass Log-Dateien im Level Details gepostet werden. Ein normaler Endbenutzer wird nicht die richtige Option auswählen können. Deshalb wird im Loglevel Details alles für die Fehlersuche notwendige geloggt, damit die Kunden lediglich das Log hochladen müssen und Hilfe bekommen und nicht schon vor der Fehlersuche so viel nachgefragt werden muss.
Ich denke, man kann das Logging insgesamt noch etwas entschlacken. Ich habe ein paar Stellen aufgezeigt.
def set_CarState(self, ev: int, soc: int, range: float, ts: int): | ||
try: | ||
msgs = [] | ||
topic = 'openWB/set/vehicle/' + str(ev) + '/get/soc' | ||
# self.pub(topic, str(soc)) | ||
msgs.append({'topic': topic, 'payload': str(soc)}) | ||
topic = 'openWB/set/vehicle/' + str(ev) + '/get/range' | ||
# self.pub(topic, str(range)) | ||
msgs.append({'topic': topic, 'payload': str(range)}) | ||
topic = 'openWB/set/vehicle/' + str(ev) + '/get/soc_timestamp' | ||
_ts = time.time() | ||
# self.pub(topic, str(_ts)) | ||
msgs.append({'topic': topic, 'payload': str(_ts)}) | ||
_infoLog('Q', "set_CarState publish.multiple: msgs=\n" + json.dumps(msgs)) | ||
_infoLog('q', "set_CarState: " + str(soc) + '%/' + str(range) + 'KM@' + str(_ts)) | ||
publish.multiple(msgs, hostname='localhost', port=1883) | ||
except Exception as e: | ||
log.exception("set_CarState error: %s", e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bitte nur den CarState zurückgeben und Publishen, Fehlerbehandlung etc vom Backend erledigen lassen. Wenn jedes Modul seine eigene Implementierung nutzt, wird die Wartung des Codes schnell sehr sehr aufwändig.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Das Return-Interface püass für das im smarteq benutzte Mercedes-API halt nicht.
Das SOC-Modul subscribed die Daten über Websockets.
Die Fahrzeug-Daten kommen asynchron über WebSockets ca. alle 15 Sekunden.
Wenn sich Soc oder range ändern schreibt das Modul die Daten über diese Funktion in den CarState.
Ich habe mittlerweile eine Alternative über den store:
# publish CarState via core store
def set_CarState(self, vehicle: int, soc: int, range: float, ts: int):
try:
st: CarValueStoreBroker = store.get_car_value_store(vehicle)
carState: CarState = CarState(int(soc), float(range), round(time(), 2))
st.set(carState)
st.update()
except Exception as e:
log.exception("set_CarState Error: %s", e)
return
Wäre das ein akzeptabler Weg?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ich habe jetzt die "API" über den store implementiert wie oben.
self.ws_soc = str(-1) | ||
self.ws_range = str(0.0) | ||
self.ws_soc_ts = 'na' | ||
self.write_ws_store(self.vin) | ||
self.wsError = 1 | ||
|
||
def ws_on_close(self, ws, status_code, message): | ||
self._infoLog('w', "ws_on_close, status_code=" + str(status_code) + | ||
", message=" + str(message)) | ||
self.ws_soc = str(-1) | ||
self.ws_range = str(0.0) | ||
self.ws_soc_ts = 'na' | ||
self.write_ws_store(self.vin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wenn die Abfrage fehl schlägt, bitte eine Exception werfen und keine Standardwerte setzen. Wird die Abfrage dreimal mit einer Exception abgebrochen, startet das Backend bei SoC-geführtem Lademodus die Ladung, damit man nicht mit einem leeren Auto da steht, weil der Server nicht erreichbar war.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Das passiert in dem Websocket thread und signalisiert der nächsten regulären Abfrage, dass die WebSocket-Schnittstelle keine Daten liefern konnte...
def read_token_file(self, path: str) -> str: | ||
try: | ||
with open(path, "r") as tf: # try to open Token file | ||
token = tf.read() # read token | ||
except Exception: | ||
token = None # if no old token found set Token_old to dummy value | ||
return token | ||
|
||
def write_token_file(self, path: str, token: str, config={}): | ||
try: | ||
_infoLog('s', "store Token in file " + path) | ||
with open(path, "w") as tf: | ||
tf.write(token) # write Token file | ||
except Exception as e: | ||
log.exception('Token file write exception ' + str(e)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Die tokens werden im Broker gespeichert, warum nochmal in eine Datei?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im broker wird aktuell nur der refresh.token gespeichert.
In der Ramdisk-Datei werden alle vom Server gelieferten Daten gespeichert.
Bei smarteq/mercedes macht das wenig Unterschied, das refresh- und access-token die gleiche Gültigkeit von 2 Stunden haben.
Bei VWId ist der Access-Token auch recht kurz gültig, der refresh-token (JWT) dagegen gilt für ca. 6 Monate, d.h. im broker wird nur sehr selten gespeichert.
self.ws_storeFile = str(RAMDISK_PATH) + '/soc_smarteq_store_ws' | ||
self.messageFile = str(RAMDISK_PATH) + '/soc_smarteq_message_vh_' + str(vehicle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was sind das für Dateien, die hier geschrieben werden? Die Tokens sollten im Broker, der SoC im Rückgabewert und alles andere im Log landen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ws_storeFile ist eine Datei, in der die Daten der websocket-Schnittstelle gespeichert werden Beispiel:
"vin": "WME4530911Y181749",
"soc": "92",
"range": "113",
"ws_soc_ts": "2024-06-19 15:50:22",
"ws_ts": 1718805022,
"ws_connect_time": 0,
"connect_time": "1718803134"
}````
Diese Datei hat die VIN im Namen und wird daher je VIN geschrieben.
Der "normale" SOC-Abruf kann damit ohne REST-Abruf direkt die Daten verwenden.
messageFile ist zum Test/Analyse gedacht.
Die Websocket-Schnittstelle liefert einige Message-Typen.
Die ankommenden Messages werden per typ in die Ramdisk geschrieben.
Damit lässt sich erkennen wenn sich die Daten einmal ändern sollten.
Hi Lena, |
Ja, das Log ist sehr umfangreich. deshalb steht bei jeder Logausgabe von welchem Fahrzeug sie stammt. Aber dadurch ist es einfach im Forum ohne viele Rückfragen an die benötigten Informationen zu kommen. |
Hallo Lutz und Lena, |
Hallo Rainer, |
Adding
PR for UI: SoC smarteq: 2FA, MBAPI added openwb-ui-settings#454