Station name as "brand, street, city", grey box on all editable fields
The "grey box around the icons" report turned out not to be a defect: the box on "10.000 km"/"1 Jahr"/"15" is the wanted pattern, and every value the user can change should carry it. All .feld inputs and selects now get the grey iOS fill; inputs with their own visual language (checkbox/radio/range/file) keep the transparent base rule, so the switches are unaffected. Fuel stations are now displayed as "Shell, Pascalstr. 8, Ingolstadt" instead of the bare operator name. New _marke()/_ist_strasse()/_tankstelle() helpers are shared by both parser paths so Shell and non-Shell receipts format the same. The brand is only matched against the receipt header - searching the whole text would let "Total" hit a totals line. Missing parts are dropped instead of leaving empty comma slots, and without a known brand the operator name takes its place. station_address still carries the full street and postcode. test_bekannte_stationen updated to the new format; suite stays green. installationspaket/ is versioned from now on (user request). It contains no real vehicle data - only the example profile with empty FIN/plate placeholders. Keep it in sync whenever pyscript/ or www/ changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""Backup-Funktion für Fahrzeugprofil, Fahrten und Tankvorgänge.
|
||||
|
||||
Manuell über "Backup jetzt erstellen" in den Einstellungen oder automatisch
|
||||
je nach einstellungen.backup_intervall im Fahrzeugprofil (aus/täglich/
|
||||
wöchentlich/monatlich) - immer um 04:00 Uhr, wenn eingestellt. Ein einzelner
|
||||
täglicher Trigger um 04:00 genügt für alle drei Intervalle: wöchentlich läuft
|
||||
nur montags, monatlich nur am Monatsersten, täglich jeden Tag - so reicht eine
|
||||
einzige Trigger-Registrierung statt drei.
|
||||
|
||||
Jedes Backup ist ein eigener Zeitstempel-Unterordner mit Kopien der drei
|
||||
Bestände (siehe profil.py), keine ZIP-Datei - das würde den vorhandenen
|
||||
task.executor(io.open, ...)-Weg (siehe dessen Kopfkommentar in profil.py)
|
||||
unnötig verkomplizieren. shutil.copy() ist wie io.open eine echte externe
|
||||
Funktion und läuft deshalb über denselben task.executor-Weg.
|
||||
|
||||
"Backup exportieren"/"importieren" in der Oberfläche laufen dagegen rein
|
||||
über den Browser (aktuell geladenes Profil + Fahrten + Tankvorgänge als eine
|
||||
JSON-Datei, siehe audi-dashboard-app.js) - audi_dashboard_backup_wiederherstellen()
|
||||
hier ist nur das Gegenstück zum Import, das die drei Bestände wieder
|
||||
komplett überschreibt.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import entitaeten
|
||||
import frontend_veroeffentlichung
|
||||
import profil
|
||||
|
||||
BACKUP_ORDNER = f"{profil.BASIS}/backups"
|
||||
# entitaeten.json gehört dazu: Ohne sie wäre nach einer Wiederherstellung die
|
||||
# komplette Sensor-Zuordnung aus dem Setup-Menü verloren, und weil sie sonst
|
||||
# nirgends abgelegt ist, gäbe es nichts zurückzuholen.
|
||||
_DATEIEN = [
|
||||
"fahrzeugprofil.json",
|
||||
"fahrten.jsonl",
|
||||
"tankvorgaenge.jsonl",
|
||||
"entitaeten.json",
|
||||
]
|
||||
|
||||
|
||||
def _backup_jetzt():
|
||||
ziel = f"{BACKUP_ORDNER}/{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
os.makedirs(ziel, exist_ok=True)
|
||||
for name in _DATEIEN:
|
||||
quelle = f"{profil.BASIS}/{name}"
|
||||
if os.path.exists(quelle):
|
||||
task.executor(shutil.copy, quelle, f"{ziel}/{name}")
|
||||
return ziel
|
||||
|
||||
|
||||
def _letztes_backup_vermerken():
|
||||
p = profil.profil_lesen()
|
||||
if p is None:
|
||||
return
|
||||
p.setdefault("einstellungen", {})["letztes_backup"] = datetime.datetime.now().isoformat()
|
||||
profil.profil_schreiben(p)
|
||||
frontend_veroeffentlichung.profil_veroeffentlichen()
|
||||
|
||||
|
||||
@service
|
||||
def audi_dashboard_backup_jetzt():
|
||||
"""Erstellt sofort ein Backup. Aufruf als pyscript.audi_dashboard_backup_jetzt."""
|
||||
ziel = _backup_jetzt()
|
||||
_letztes_backup_vermerken()
|
||||
log.info(f"audi_dashboard: Backup erstellt unter {ziel}")
|
||||
|
||||
|
||||
@time_trigger("cron(0 4 * * *)")
|
||||
def _automatisches_backup():
|
||||
p = profil.profil_lesen()
|
||||
if p is None:
|
||||
return
|
||||
intervall = p.get("einstellungen", {}).get("backup_intervall", "aus")
|
||||
heute = datetime.date.today()
|
||||
faellig = (
|
||||
intervall == "taeglich"
|
||||
or (intervall == "woechentlich" and heute.weekday() == 0)
|
||||
or (intervall == "monatlich" and heute.day == 1)
|
||||
)
|
||||
if not faellig:
|
||||
return
|
||||
ziel = _backup_jetzt()
|
||||
_letztes_backup_vermerken()
|
||||
log.info(f"audi_dashboard: automatisches Backup ({intervall}) erstellt unter {ziel}")
|
||||
|
||||
|
||||
@service
|
||||
def audi_dashboard_backup_wiederherstellen(profil_json=None, fahrten_json=None, tankvorgaenge_json=None, entitaeten_json=None):
|
||||
"""Stellt ein über "Backup exportieren" heruntergeladenes Backup wieder
|
||||
her - überschreibt Profil, Fahrten, Tankvorgänge und die Sensor-Zuordnung
|
||||
komplett. Aufruf als pyscript.audi_dashboard_backup_wiederherstellen.
|
||||
|
||||
entitaeten_json ist optional: ältere Sicherungen, die vor dem Setup-Menü
|
||||
entstanden sind, enthalten den Abschnitt nicht - dann bleibt die aktuelle
|
||||
Zuordnung unangetastet, statt sie zu leeren."""
|
||||
if profil_json:
|
||||
p = json.loads(profil_json) if isinstance(profil_json, str) else profil_json
|
||||
profil.profil_schreiben(p)
|
||||
if fahrten_json is not None:
|
||||
fahrten = json.loads(fahrten_json) if isinstance(fahrten_json, str) else fahrten_json
|
||||
profil.fahrten_schreiben(fahrten)
|
||||
if tankvorgaenge_json is not None:
|
||||
tankvorgaenge = json.loads(tankvorgaenge_json) if isinstance(tankvorgaenge_json, str) else tankvorgaenge_json
|
||||
profil.tankvorgaenge_schreiben(tankvorgaenge)
|
||||
if entitaeten_json:
|
||||
zuordnung = json.loads(entitaeten_json) if isinstance(entitaeten_json, str) else entitaeten_json
|
||||
entitaeten.overrides_schreiben(zuordnung)
|
||||
entitaeten.overrides_anwenden()
|
||||
frontend_veroeffentlichung.alles_veroeffentlichen()
|
||||
log.info("audi_dashboard: Backup wiederhergestellt")
|
||||
Reference in New Issue
Block a user