90efcc5b00
Die App blieb nach einem Neustart von Home Assistant auf dem alten Stand stehen, mit einer 502-Fehlerzeile, die erst ein Beenden der App wegbekam. Zwei Ursachen: 502/503/504 galten als harter Ladefehler statt als "Server faehrt gerade hoch", und nach dem Wiederverbinden wurde genau einmal nachgeladen - schlug das fehl, kam nie wieder ein Versuch. Beides behoben, vier Regressionstests dazu. OTA: das Buendel ist von HEAD ueber die Platte bis zu den ausgelieferten Bytes nachweislich deckungsgleich. Die Fassung haengt jetzt trotzdem als ?v= an der Adresse (der statische Pfad kommt ohne Cache-Control, aber mit ETag), und ein Pruefsummenfehler wird erklaert statt durchgereicht. Statistik: der Gesamtwert steht jetzt als grosse Zahl in der Kopfzeile, darunter bleiben vier Spalten - fuenf passen auf dem Telefon nachweislich nicht in eine Zeile. Fahrzeugfoto ohne Beschnitt und ohne Bodenschatten, damit auch ohne den Schalter dafuer. Setup filtert zusaetzlich nach dem Signalnamen aus dem Katalog. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
219 lines
6.6 KiB
TypeScript
219 lines
6.6 KiB
TypeScript
/**
|
|
* Beispieldaten für Rendertests. Aufgebaut wie das, was das Backend
|
|
* tatsächlich liefert (an der laufenden Testinstanz abgelesen), nicht wie es
|
|
* laut Spezifikation aussehen sollte.
|
|
*/
|
|
|
|
import type { DataMetricApi, Fahrt, Fahrzeugstatus, Profil, Tankvorgang } from "../api"
|
|
|
|
export const beispielStatus: Fahrzeugstatus = {
|
|
km: 48250,
|
|
tankprozent: 62,
|
|
reichweite_km: 385,
|
|
batteriespannung: null,
|
|
gesichert: true,
|
|
sicherheitscheck: [
|
|
{ label: "Tür vorne links", ok: true, gruppe: "tueren_klappen" },
|
|
{ label: "Tür vorne rechts", ok: true, gruppe: "tueren_klappen" },
|
|
{ label: "Motorhaube", ok: null, gruppe: "tueren_klappen" },
|
|
{ label: "Fenster vorne links", ok: false, gruppe: "fenster_dach" },
|
|
{ label: "Türschloss vorne links", ok: true, gruppe: "verriegelt" },
|
|
{ label: "Standlicht", ok: true, gruppe: "licht" },
|
|
],
|
|
oelwechsel_faellig_ts: "2027-03-14T00:00:00+00:00",
|
|
oelwechsel_faellig_km: 11750,
|
|
inspektion_faellig_ts: "2027-03-14T00:00:00+00:00",
|
|
inspektion_faellig_km: 11750,
|
|
}
|
|
|
|
export const beispielProfil: Profil = {
|
|
fahrzeug: {
|
|
fin: "WUAZZZF48PA902804",
|
|
titel: "RS 4 Avant",
|
|
zusatz: "competition",
|
|
untertitel: "quattro · 331 kW",
|
|
details: "2.9 TFSI quattro competition",
|
|
kennzeichen: "M AB 1234",
|
|
erstzulassung: "2023-04-01",
|
|
hauptuntersuchung_faellig: "2027-04-01",
|
|
tankvolumen_liter: 58,
|
|
ausfuehrung: "competition",
|
|
},
|
|
einstellungen: {
|
|
nacht_von: "22:00",
|
|
nacht_bis: "06:00",
|
|
uebersichtsbild: "seitenansicht.webp",
|
|
kraftstoffanbieter: "Shell",
|
|
smartdeal: { aktiv: true, laeuft_ab: null },
|
|
oelwechsel_intervall: {
|
|
modus: "hersteller",
|
|
km: 15000,
|
|
monate: 12,
|
|
hersteller_km: 30000,
|
|
hersteller_monate: 24,
|
|
},
|
|
backup_intervall: "taeglich",
|
|
letztes_backup: "2026-08-10T04:00:00",
|
|
},
|
|
versicherung: {
|
|
gesellschaft: "Beispiel Versicherung",
|
|
vertrag: "Vollkasko",
|
|
nummer: "V-123456",
|
|
service: "0800 111111",
|
|
notfall: "0800 222222",
|
|
beitrag: 840,
|
|
zahlweise: "jährlich",
|
|
gueltigAb: "2026-01-01",
|
|
teile: [
|
|
{ bez: "Haftpflicht", betrag: 320 },
|
|
{ bez: "Vollkasko", betrag: 520 },
|
|
],
|
|
selbst: [["Vollkasko", "500 €"]],
|
|
leistungen: [{ bez: "Werkstattbindung", wert: "nein" }],
|
|
schutzbrief: {
|
|
stand: "2026-01",
|
|
gilt: "Europa",
|
|
versichert: "Fahrzeug und Insassen",
|
|
ausloeser: ["Panne", "Unfall"],
|
|
entweder: [],
|
|
gruppen: ["Abschleppen"],
|
|
nicht: [],
|
|
pflichten: ["Unverzüglich melden"],
|
|
},
|
|
},
|
|
steuer: {
|
|
betrag: 320,
|
|
zeitraum: "jährlich",
|
|
faellig: "2027-04-01",
|
|
grundlage: "Hubraum und CO₂-Ausstoß",
|
|
lastschrift: true,
|
|
finanzamt: "München",
|
|
},
|
|
reifen: {
|
|
aktiv: "sommer",
|
|
anzugsmoment_nm: 140,
|
|
wechsel: { datum: "2026-10-15", vereinbart: false },
|
|
referenz_odo_km: 48250,
|
|
saetze: {
|
|
sommer: { km: 12000, mass: "275/30 R20", marke: "Michelin", druck_vorne: "2,5", druck_hinten: "2,4" },
|
|
winter: { km: 8000, mass: "265/35 R19", marke: "Continental", druck_vorne: "2,6", druck_hinten: "2,5" },
|
|
},
|
|
},
|
|
service: {
|
|
vereinbart: {},
|
|
autohaus: { name: "Audi Zentrum", adresse: "Musterweg 1", tel: "089 1234", mail: "a@b.de" },
|
|
buch: [
|
|
{ datum: "2026-02-10", km: 40000, art: "Ölwechsel", werkstatt: "Audi Zentrum" },
|
|
{ datum: "2025-03-05", km: 25000, art: "Inspektion", werkstatt: "Audi Zentrum" },
|
|
],
|
|
},
|
|
technik: [
|
|
{ gruppe: "Motor", posten: [["Bauart", "V6 Biturbo"], ["Leistung", "331 kW"]] },
|
|
],
|
|
ausstattung: [{ gruppe: "RS-Paket", sonder: ["RS competition"], serie: ["Klimaautomatik"] }],
|
|
}
|
|
|
|
export const beispielFahrten: Fahrt[] = [
|
|
{
|
|
trip_id: "t1",
|
|
ts_start: "2026-08-10T08:00:00+02:00",
|
|
ts_end: "2026-08-10T08:45:00+02:00",
|
|
duration_s: 2700,
|
|
distance_km: 42.5,
|
|
km_quelle: "odometer",
|
|
odo_start: 48200,
|
|
odo_end: 48242.5,
|
|
art: "arbeitsweg",
|
|
source: "ha",
|
|
status: "vollständig",
|
|
},
|
|
{
|
|
trip_id: "t2",
|
|
ts_start: "2026-08-09T23:10:00+02:00",
|
|
ts_end: "2026-08-09T23:40:00+02:00",
|
|
duration_s: 1800,
|
|
distance_km: 18.2,
|
|
km_quelle: "odometer",
|
|
odo_start: 48180,
|
|
odo_end: 48198.2,
|
|
art: "privat",
|
|
source: "manual",
|
|
status: "offen",
|
|
},
|
|
]
|
|
|
|
export const beispielTankvorgaenge: Tankvorgang[] = [
|
|
{
|
|
tank_id: "f1",
|
|
ts: "2026-08-08T17:20:00+02:00",
|
|
liters: 48.7,
|
|
fuel_total_eur: 89.12,
|
|
price_per_l: 1.83,
|
|
station_name: "Shell München Ost",
|
|
station_address: "Musterstraße 5",
|
|
product_name: "V-Power",
|
|
odometer_km: 48100,
|
|
distance_km: 520,
|
|
receipt_file: "beleg-2026-08-08.pdf",
|
|
receipt_no: "4711",
|
|
discount: 3.4,
|
|
source: "beleg",
|
|
status: "vollständig",
|
|
},
|
|
]
|
|
|
|
/** Datenschicht-Ersatz für Tests: liefert Beispieldaten, schreibt ins Leere. */
|
|
export function beispielApi(): DataMetricApi {
|
|
const horcher = { verbindung: [] as ((z: string) => void)[] }
|
|
return {
|
|
rest: {
|
|
zustandLesen: async () => ({
|
|
entity_id: "sensor.audi_dashboard_fahrzeugstatus",
|
|
state: "aktuell",
|
|
attributes: { daten: beispielStatus },
|
|
last_changed: "2026-08-11T09:00:00+00:00",
|
|
last_updated: "2026-08-11T09:00:00+00:00",
|
|
}),
|
|
datenLesen: async () => [],
|
|
dienstAufrufen: async () => null,
|
|
verbindungPruefen: async () => ({ message: "API running." }),
|
|
zugangSetzen: () => {},
|
|
},
|
|
live: {
|
|
aufVerbindung: (h: (z: string) => void) => {
|
|
horcher.verbindung.push(h)
|
|
h("verbunden")
|
|
return () => {}
|
|
},
|
|
aufZustand: () => () => {},
|
|
starten: async () => {},
|
|
beenden: () => {},
|
|
},
|
|
warteschlange: {
|
|
laden: async () => {},
|
|
aufAenderung: (h: (a: unknown[]) => void) => {
|
|
h([])
|
|
return () => {}
|
|
},
|
|
anzahl: 0,
|
|
},
|
|
profilLesen: async () => beispielProfil,
|
|
fahrtenLesen: async () => beispielFahrten,
|
|
tankvorgaengeLesen: async () => beispielTankvorgaenge,
|
|
fahrzeugstatusLesen: async () => beispielStatus,
|
|
profilSchreiben: async () => null,
|
|
belegHochladen: async () => null,
|
|
fahrtAnlegen: async () => null,
|
|
fahrtLoeschen: async () => null,
|
|
tankvorgangAnlegen: async () => null,
|
|
tankvorgangAktualisieren: async () => null,
|
|
tankvorgangLoeschen: async () => null,
|
|
jetztAktualisieren: async () => null,
|
|
// Die echte Fassung schluckt ihre Fehler selbst und liefert dann null.
|
|
// Fehlte sie hier ganz, endete jede Ladung im Fangzweig von neuLaden -
|
|
// die Seiten rendern trotzdem, aber ein Test ueber den Ladefehler waere
|
|
// wertlos.
|
|
appVersionAngabeLesen: async () => null,
|
|
} as unknown as DataMetricApi
|
|
}
|