Fehlerspeicher, Amber statt Gruen, Tankbalken rot ab 90 km
- Neue Sensorrolle FEHLERSPEICHER_SENSOR (number_of_diagnostic_trouble_codes vom CAN) und eine fuenfte Zeile auf der Sicherheitsseite: "Keine Fehlermeldungen". Bewusst NICHT im _sicherheitscheck(): "gesichert" rechnet ein UND ueber diese Liste, und ein Eintrag im Fehlerspeicher sagt nichts darueber, ob der Wagen verschlossen dasteht. - "Zuendung an" ist Amber statt Gruen. Gruen las sich als "alles in Ordnung und sicher"; unterwegs ist kein guter Zustand, sondern ein anderer. - Das Modell-Auswahlfeld bekam dm-eingabe statt dm-auswahl - nur letzteres setzt appearance:none, deshalb zeichnete der Browser seinen nativen Pfeil neben den des Design-Systems. Die Breitenregel heisst jetzt dm-feld--fahrzeug und gilt fuer input und select. - "aktuell" erscheint erst nach einer Pruefung, und fuer beide Abschnitte gemeinsam. Der App-Abschnitt zeigte die Marke schon, sobald ein Buendel vorlag - also unmittelbar nach einem Update wieder. - Der Tankbalken wird rot ab 90 km Restreichweite, in Kilometern und nicht in Prozent: die Reichweite ist die Aussage, um die es geht, und das Fahrzeug rechnet die Fahrweise darin bereits ein. Farbe --red (Audi-CI, #F50537), nicht --bad-flaeche - letzteres ist fuer weisse Schrift darauf gewaehlt, und hier steht keine drauf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7770,6 +7770,75 @@ abgleichen, und nur bei bekanntem Wert) live belegt.
|
||||
gespeicherten Zugang; belegt sind sie über `tsc`, die 303 Tests und den
|
||||
Listenvergleich gegen die Panel-Quelle.
|
||||
|
||||
### Nachtrag (2026.9.5.36–.39): Fehlerspeicher, Amber, Reservebalken
|
||||
|
||||
**Der Doppelpfeil am Modellfeld war meiner.** Das neue `<select>` bekam
|
||||
`dm-eingabe` statt `dm-auswahl` — und nur letzteres setzt `appearance: none`.
|
||||
Der Aufklapp-Pfeil kommt als Hintergrundbild aus dem Design-System
|
||||
(`.ads-feld select`), der Browser zeichnete seinen eigenen daneben. Behoben;
|
||||
die Breitenregel heißt jetzt `dm-feld--fahrzeug` und gilt für `input` **und**
|
||||
`select`. **Merkposten:** `.ads-feld select` im Design-System entfernt den
|
||||
nativen Pfeil NICHT selbst, obwohl sein Kommentar das behauptet — die App
|
||||
liefert den Reset über `.dm-auswahl` nach. Jedes neue `<select>` braucht diese
|
||||
Klasse.
|
||||
|
||||
**„Zündung an" ist Amber, nicht Grün.** Ich hatte Grün gesetzt; der Eigentümer:
|
||||
grün läse sich als „alles in Ordnung und sicher". Unterwegs ist kein guter
|
||||
Zustand, sondern ein anderer — Übersicht und Sicherheitsseite tragen jetzt
|
||||
`--warn`.
|
||||
|
||||
**Fehlerspeicher als fünfte Zeile.** Der Dongle liefert
|
||||
`number_of_diagnostic_trouble_codes` direkt vom CAN (gemessen, 0 im Testwagen).
|
||||
Neue Rolle `FEHLERSPEICHER_SENSOR`; die Zeile heißt „Keine Fehlermeldungen",
|
||||
sonst „N Fehlermeldungen", ohne Sensor „Fehlerspeicher unbekannt".
|
||||
|
||||
**Bewusst NICHT im `_sicherheitscheck()`**, sondern als eigenes Feld
|
||||
`fehlerspeicher`: `gesichert` rechnet ein UND über alle Punkte dieser Liste,
|
||||
und ein Eintrag im Fehlerspeicher sagt nichts darüber, ob der Wagen
|
||||
verschlossen dasteht. Live belegt: `sicherheitscheck` bleibt bei 13 Punkten,
|
||||
`gesichert` unverändert `true`. WELCHER Fehler vorliegt, meldet das Gerät
|
||||
nicht — ein Reserve- oder Warnsignal existiert ebenfalls nicht (alle 54
|
||||
Entitäten geprüft).
|
||||
|
||||
**„aktuell" erst nach einer Prüfung, für beide Abschnitte.** Der App-Abschnitt
|
||||
zeigte die grüne Marke, sobald ein Bündel vorlag — also unmittelbar nach einem
|
||||
Update wieder, ohne dass jemand nachgesehen hätte. Beide Marken hängen jetzt an
|
||||
`geprueft_am`; der eine Knopf prüft beides, also werden beide zusammen grün.
|
||||
|
||||
**Der Tankbalken wird rot ab 90 km Restreichweite.**
|
||||
|
||||
Erst hatte ich das in Prozent umrechnen wollen, mit dem Argument, eine
|
||||
km-Schwelle löse je nach Fahrweise bei unterschiedlichen Füllständen aus. Der
|
||||
Eigentümer hat das verworfen, und zu Recht: „90km sind absolute 90km", und
|
||||
„falls der verbrauch sich verdoppelt wird der balken einfach früher schon rot"
|
||||
— genau das ist der Zweck. Die Reichweite ist die Aussage, um die es geht, und
|
||||
das Fahrzeug rechnet die Fahrweise darin bereits ein.
|
||||
|
||||
Zur Schwelle selbst, damit sie nicht als Messung gilt: **sie ist eine
|
||||
Festlegung.** Belegt ist nur eine Untergrenze — das Bildschirmfoto der
|
||||
myAudi-App zeigt 70 km rot; ein höherer Wert wurde nie im grauen Zustand
|
||||
festgehalten. Aus unseren Daten ist die Schwelle der myAudi-App nicht
|
||||
ableitbar. Gemessen wurde dabei immerhin die Umrechnung, aus 494 Wertepaaren
|
||||
über 45 Tage: **10,46 km je Liter** (Median, 1,71 bis 12,53) und 0,613 l je
|
||||
Prozentpunkt, also ein rechnerischer Tank von **61,3 l** — das Fahrzeugprofil
|
||||
trägt 58 l.
|
||||
|
||||
Farbe: **`--red` (#F50537, Audi-CI-Rot)**, nicht `--bad-flaeche` (#D70015).
|
||||
Letzteres ist Apples dunkles Rot und so gewählt, dass weiße Schrift darauf
|
||||
lesbar bleibt; auf dem Balken steht keine Schrift, der Grund fällt weg. Vom
|
||||
Eigentümer als „weniger dunkel" gemeldet. Rot als Fläche ist sonst
|
||||
zerstörenden Aktionen vorbehalten — hier eine benannte Ausnahme, weil es kein
|
||||
Bedienelement ist, sondern eine Warnung. Live gemessen: `rgb(245, 5, 55)` auf
|
||||
`rgba(120,120,128,.16)`, 6 px, voll gerundet.
|
||||
|
||||
**Offen:** die Ziffern der Reichweite wirken in der myAudi-App dicker. Unsere
|
||||
`.fig` steht auf Audi Type Wide **300** — und das ist der einzige Wide-Schnitt
|
||||
im Repo (`audi-type-wide-300.woff2`; daneben nur `audi-type-400` und
|
||||
`audi-type-extended-400-italic`). Ein dickerer Wide-Schnitt lässt sich damit
|
||||
nicht setzen, und synthetisches Fetten verschmiert die Striche. Braucht
|
||||
entweder die Schriftdatei vom Eigentümer oder die Entscheidung, für diese eine
|
||||
Zahl auf „Audi Type" 400 zu wechseln.
|
||||
|
||||
## Working conventions (observed — keep them)
|
||||
|
||||
- German is the project language: identifiers, comments, commits, UI texts. Exceptions:
|
||||
|
||||
@@ -127,6 +127,9 @@ export interface Fahrzeugstatus {
|
||||
batteriespannung?: number | null;
|
||||
gesichert?: boolean | null;
|
||||
sicherheitscheck?: SicherheitsPunkt[];
|
||||
/** Diagnosecodes im Fehlerspeicher. Getrennt vom Sicherheitscheck, weil ein
|
||||
Eintrag nichts darueber sagt, ob der Wagen verschlossen dasteht. */
|
||||
fehlerspeicher?: { anzahl: number | null; ok: boolean | null } | null;
|
||||
/** Zustand des Zündungssensors — ausdrücklich nicht „fährt": es gibt keinen
|
||||
Bewegungssensor, und die Zündung meldet an auch bei Zubehörstellung oder
|
||||
im Stand. `null`/fehlend heißt „kein Zündungssensor zugeordnet", also
|
||||
|
||||
@@ -66,6 +66,9 @@ export interface Fahrzeug {
|
||||
batteriespannung: number | null
|
||||
gesichert: boolean | null
|
||||
sicherheitscheck: SicherheitsPunkt[]
|
||||
/** Diagnosecodes im Fehlerspeicher; `null` heisst "kein Sensor zugeordnet
|
||||
oder er meldet nichts" - nie als "keine Fehler" deuten. */
|
||||
fehlerspeicher: { anzahl: number | null; ok: boolean | null } | null
|
||||
/** Zustand des Zündungssensors — nicht „fährt": ohne Bewegungssensor sagt
|
||||
an nur, dass die Zündung an ist. `null` heißt „kein Zündungssensor
|
||||
zugeordnet", also unbekannt — nicht „steht". */
|
||||
@@ -181,6 +184,7 @@ export function profilZuFahrzeug(profil: Profil, status: Fahrzeugstatus): Fahrze
|
||||
batteriespannung: status.batteriespannung ?? null,
|
||||
gesichert: status.gesichert ?? null,
|
||||
sicherheitscheck: status.sicherheitscheck ?? [],
|
||||
fehlerspeicher: status.fehlerspeicher ?? null,
|
||||
zuendung: status.zuendung ?? null,
|
||||
geparktSeit: (status.geparkt_seit as string | null) ?? null,
|
||||
faehrtSeit: (status.faehrt_seit as string | null) ?? null,
|
||||
|
||||
@@ -26,6 +26,7 @@ function fahrzeug(odo: number, modus = "hersteller"): Fahrzeug {
|
||||
batteriespannung: null,
|
||||
gesichert: null,
|
||||
sicherheitscheck: [],
|
||||
fehlerspeicher: null,
|
||||
zuendung: null,
|
||||
geparktSeit: null,
|
||||
faehrtSeit: null,
|
||||
|
||||
@@ -412,8 +412,13 @@ export function Einstellungen({
|
||||
gesucht. Die Liste selbst steht in daten/fahrzeugmodelle.ts und
|
||||
wird von einem Test gegen die Panel-Fassung geprüft. */}
|
||||
<Feld label="Modell">
|
||||
{/* dm-auswahl, NICHT dm-eingabe: nur dort steht `appearance: none`.
|
||||
Der Aufklapp-Pfeil kommt als Hintergrundbild aus dem
|
||||
Design-System (.ads-feld select); ohne den Reset zeichnet der
|
||||
Browser seinen eigenen daneben — vom Eigentümer am 05.09.2026
|
||||
als „Doppelpfeil" gemeldet. */}
|
||||
<select
|
||||
className="dm-eingabe dm-eingabe--fahrzeug"
|
||||
className="dm-auswahl dm-feld--fahrzeug"
|
||||
value={werte.fahrzeugtitel}
|
||||
onChange={(e) => {
|
||||
aendern({ fahrzeugtitel: e.target.value })
|
||||
@@ -429,7 +434,7 @@ export function Einstellungen({
|
||||
</Feld>
|
||||
<Feld label="Kennzeichen">
|
||||
<input
|
||||
className="dm-eingabe dm-eingabe--fahrzeug"
|
||||
className="dm-eingabe dm-feld--fahrzeug"
|
||||
value={werte.kennzeichen}
|
||||
onChange={(e) => aendern({ kennzeichen: e.target.value })}
|
||||
onBlur={() => sichern()}
|
||||
@@ -437,7 +442,7 @@ export function Einstellungen({
|
||||
</Feld>
|
||||
<Feld label="Erstzulassung">
|
||||
<input
|
||||
className="dm-eingabe dm-eingabe--fahrzeug"
|
||||
className="dm-eingabe dm-feld--fahrzeug"
|
||||
placeholder="TT.MM.JJJJ"
|
||||
value={erstzulassungWert}
|
||||
onChange={(e) => setzeErstzulassung(e.target.value)}
|
||||
@@ -446,7 +451,7 @@ export function Einstellungen({
|
||||
</Feld>
|
||||
<Feld label="Ausführung" last>
|
||||
<input
|
||||
className="dm-eingabe dm-eingabe--fahrzeug"
|
||||
className="dm-eingabe dm-feld--fahrzeug"
|
||||
value={werte.ausfuehrung}
|
||||
onChange={(e) => aendern({ ausfuehrung: e.target.value })}
|
||||
onBlur={() => sichern()}
|
||||
@@ -844,7 +849,13 @@ export function Einstellungen({
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{integrationUpdate && <span className="dm-standmarke">aktuell</span>}
|
||||
{/* Nur nach einer Prüfung. „aktuell" ohne Prüfung wäre eine
|
||||
Behauptung ohne Grundlage — dieselbe Bedingung trägt der
|
||||
App-Abschnitt darunter, damit beide gemeinsam grün werden
|
||||
(Vorgabe des Eigentümers, 05.09.2026). */}
|
||||
{integrationUpdate?.geprueft_am && (
|
||||
<span className="dm-standmarke">aktuell</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{updateAktionFehler && <p className="dm-fehler">{updateAktionFehler}</p>}
|
||||
@@ -890,11 +901,16 @@ export function Einstellungen({
|
||||
nach dem Neustart etwas. */
|
||||
<p className="dm-erklaerung">Update {otaBuendel.version} vorhanden</p>
|
||||
) : otaBuendel ? (
|
||||
/* Dieselbe grüne Marke wie bei der Integration, statt eines
|
||||
Satzes - Vorgabe des Eigentümers, 05.09.2026. Ohne Zeitpunkt:
|
||||
anders als bei der Integration wird hier nicht auf Knopfdruck
|
||||
geprüft, das Bündel meldet der Server beim Laden mit. */
|
||||
<span className="dm-standmarke">aktuell</span>
|
||||
/* Dieselbe grüne Marke wie bei der Integration - und an
|
||||
dieselbe Bedingung geknüpft: erst nach einer Prüfung. Das
|
||||
Bündel meldet der Server zwar bei jedem Laden mit, aber
|
||||
„aktuell" stand damit schon unmittelbar nach einem Update
|
||||
wieder da, ohne dass jemand nachgesehen hätte (vom Eigentümer
|
||||
am 05.09.2026 bemerkt). Der eine Knopf unten prüft beides,
|
||||
also werden auch beide zusammen grün. */
|
||||
integrationUpdate?.geprueft_am ? (
|
||||
<span className="dm-standmarke">aktuell</span>
|
||||
) : null
|
||||
) : (
|
||||
<p className="dm-erklaerung">
|
||||
Der Server hat gerade kein Update-Bündel hinterlegt.
|
||||
|
||||
@@ -44,6 +44,17 @@ export function Fahrzeugstatus({ geheZu }: { geheZu: (name: SeitenName) => void
|
||||
Schlosssensoren melden — nur die Überschrift darf nicht „abgestellt"
|
||||
behaupten, während die Zündung an ist. */
|
||||
const faehrt = standortZustand(fahrzeug).faehrt
|
||||
const fehlerAnzahl =
|
||||
typeof fahrzeug.fehlerspeicher?.anzahl === "number" ? fahrzeug.fehlerspeicher.anzahl : null
|
||||
const fehlerOk = fehlerAnzahl === null ? null : fehlerAnzahl === 0
|
||||
const fehlerText =
|
||||
fehlerAnzahl === null
|
||||
? "Fehlerspeicher unbekannt"
|
||||
: fehlerAnzahl === 0
|
||||
? "Keine Fehlermeldungen"
|
||||
: fehlerAnzahl === 1
|
||||
? "1 Fehlermeldung"
|
||||
: `${fehlerAnzahl} Fehlermeldungen`
|
||||
const sammelText = faehrt
|
||||
? "Zündung an - Fahrzeug in Betrieb"
|
||||
: gesichert === null
|
||||
@@ -68,7 +79,7 @@ export function Fahrzeugstatus({ geheZu }: { geheZu: (name: SeitenName) => void
|
||||
{/* Während der Fahrt weder Haken noch Kreuz noch Fragezeichen, sondern
|
||||
derselbe Punkt wie im Standortmenü — der Zustand ist dann nicht
|
||||
„geprüft", sondern schlicht ein anderer. */}
|
||||
{faehrt ? <span className="ads-dot" /> : <StatusKreis ok={gesichert} />}
|
||||
{faehrt ? <span className="ads-dot ads-dot--warn" /> : <StatusKreis ok={gesichert} />}
|
||||
<span>{sammelText}</span>
|
||||
</Tile>
|
||||
|
||||
@@ -105,6 +116,15 @@ export function Fahrzeugstatus({ geheZu }: { geheZu: (name: SeitenName) => void
|
||||
{licht === null ? "Licht unbekannt" : licht ? "Licht ausgeschaltet" : "Licht eingeschaltet"}
|
||||
</span>
|
||||
</div>
|
||||
{/* Der Fehlerspeicher des Fahrzeugs. Steht bewusst NICHT im
|
||||
Sicherheitscheck und geht damit auch nicht in „sicher
|
||||
abgestellt" ein — ein Eintrag sagt nichts darüber, ob der Wagen
|
||||
verschlossen dasteht (siehe _fehlerspeicher() im Backend).
|
||||
WELCHER Fehler vorliegt, meldet das Gerät nicht. */}
|
||||
<div className="dm-sicherheitszeile">
|
||||
<StatusKreis ok={fehlerOk} />
|
||||
<span className="dm-sicherheitszeile__text">{fehlerText}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Tile>
|
||||
</>
|
||||
|
||||
@@ -29,6 +29,8 @@ import { Typenschild, schildErkennen } from "./Typenschild"
|
||||
// links der Kennzahl - deckungsgleich mit ART_ICON im Panel (vHome()). Die
|
||||
// Hauptuntersuchung hat kein Restkilometer-Ziel und zeigt stattdessen den
|
||||
// Art-Namen selbst unter dem (gleich großen) Datum.
|
||||
const RESERVE_KM = 90
|
||||
|
||||
const SERVICE_SYMBOL: Partial<Record<string, typeof SymbolOelwechsel>> = {
|
||||
"Ölwechsel": SymbolOelwechsel,
|
||||
"Inspektion": SymbolInspektion,
|
||||
@@ -102,9 +104,30 @@ export function Uebersicht({ geheZu }: { geheZu: (name: SeitenName, id?: string)
|
||||
Wortlaut wie im Standortmenü: „Zündung an", nicht „fährt" — einen
|
||||
Bewegungssensor gibt es nicht, die Zündung steht auch im Stand mit
|
||||
laufendem Motor auf an. Deckungsgleich mit vHome() im Panel. */
|
||||
/* Ab wann der Tankbalken rot wird - in KILOMETERN Restreichweite, nicht in
|
||||
Prozent. Die Reichweite ist die Aussage, um die es geht ("wie weit komme ich
|
||||
noch"), und das Fahrzeug rechnet die Fahrweise darin bereits ein; eine
|
||||
Prozentschwelle haette bei 1,71 bis 12,53 km je Liter (in 45 Tagen gemessen)
|
||||
bei ganz unterschiedlichen Restreichweiten ausgeloest.
|
||||
|
||||
90 km ist die Zahl des Eigentuemers, an der myAudi-App beobachtet. Belegt ist
|
||||
daraus nur eine Untergrenze: sein Bildschirmfoto zeigt 70 km rot, ein Wert
|
||||
darueber wurde nie im grauen Zustand festgehalten. Der Dongle liefert kein
|
||||
Reserve- oder Warnsignal (alle 54 Entitaeten geprueft), die Schwelle der
|
||||
myAudi-App steht also in keinen Daten, die wir haben - dies ist eine
|
||||
Festlegung, keine Messung.
|
||||
|
||||
Ohne bekannte Reichweite bleibt der Balken neutral: eine Warnung aus
|
||||
fehlenden Daten waere geraten. */
|
||||
const tankReserve =
|
||||
typeof fahrzeug.reichweite === "number" && fahrzeug.reichweite <= RESERVE_KM
|
||||
|
||||
const faehrt = standortZustand(fahrzeug).faehrt
|
||||
/* Amber, nicht grün: „Zündung an" ist kein guter Zustand, sondern ein
|
||||
anderer — grün läse sich als „alles in Ordnung und sicher" (Vorgabe des
|
||||
Eigentümers, 05.09.2026). */
|
||||
const sicherheitsstatus = faehrt
|
||||
? "ok"
|
||||
? "warn"
|
||||
: fahrzeug.gesichert === true
|
||||
? "ok"
|
||||
: fahrzeug.gesichert === false
|
||||
@@ -190,7 +213,10 @@ export function Uebersicht({ geheZu }: { geheZu: (name: SeitenName, id?: string)
|
||||
{fahrzeug.tankBekannt ? `${de(fahrzeug.tankPct)} %` : "–"}
|
||||
</span>
|
||||
</div>
|
||||
<ProgressBar percent={Math.max(0, Math.min(100, fahrzeug.tankPct))} />
|
||||
<ProgressBar
|
||||
percent={Math.max(0, Math.min(100, fahrzeug.tankPct))}
|
||||
className={tankReserve ? "dm-balken--reserve" : ""}
|
||||
/>
|
||||
<span className="ads-eyebrow" style={{ marginTop: "var(--sp-3)" }}>
|
||||
Reichweite
|
||||
</span>
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
Oberflächen: das längste Label ("Erstzulassung") lässt in der App nur
|
||||
183px fürs Feld, im Panel 196px. 180 passt in beiden mit etwas Luft und
|
||||
hält sie zugleich untereinander gleich. */
|
||||
.ads-feld input.dm-eingabe--fahrzeug {
|
||||
.ads-feld input.dm-feld--fahrzeug,
|
||||
.ads-feld select.dm-feld--fahrzeug {
|
||||
width: 180px;
|
||||
flex: 0 0 auto;
|
||||
max-width: none;
|
||||
@@ -2383,3 +2384,17 @@ input[type="range"] {
|
||||
/* Spinner UND Beschriftung in EINEM Knopf: seit dem 05.09.2026 trägt der
|
||||
Knopf der Update-Kachel den laufenden Vorgang selbst, statt dass daneben
|
||||
eine eigene Ladezeile steht (Vorgabe des Eigentümers: „warum nicht den
|
||||
update suchen button dafür verwenden"). */
|
||||
.dm-knopflader {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Tankbalken in der Reserve: das Audi-CI-Rot (--red, #F50537), nicht
|
||||
--bad-flaeche (#D70015). Letzteres ist Apples dunkles Rot und ist so
|
||||
gewaehlt, dass WEISSE SCHRIFT darauf lesbar bleibt - hier steht keine
|
||||
Schrift auf der Flaeche, der Grund faellt also weg. Der Balken bildet die
|
||||
myAudi-App nach, und deren Rot ist das der Marke (vom Eigentuemer am
|
||||
05.09.2026 als "weniger dunkel" gemeldet).
|
||||
|
||||
|
||||
@@ -163,6 +163,12 @@ class Sensorzuordnung:
|
||||
# veroeffentlichung.py.
|
||||
DACH_SENSOR: str = ""
|
||||
LICHT_SENSOR: str = ""
|
||||
# Anzahl der im Fehlerspeicher stehenden Diagnosecodes (OBD/CAN). 0 heisst
|
||||
# "keine Fehlermeldungen"; jeder Wert darueber ist einer. Der Sensor sagt
|
||||
# NICHT, welcher Fehler vorliegt - das steht nicht im Datensatz des
|
||||
# Geraets. Zaehlt bewusst nicht in "sicher abgestellt" hinein: ein Auto
|
||||
# mit einem Eintrag im Fehlerspeicher steht trotzdem verschlossen da.
|
||||
FEHLERSPEICHER_SENSOR: str = ""
|
||||
|
||||
# Vom Fahrzeug selbst gemeldete Service-Fälligkeit (ergänzt die
|
||||
# App-eigene, aus dem Servicebuch berechnete Prognose).
|
||||
@@ -322,6 +328,11 @@ FELDER: list[dict] = [
|
||||
"domains": ["binary_sensor"], "device_classes": ["light"], "units": [], "liste": False, "pflicht": False,
|
||||
"beispiel": "parking_lights",
|
||||
"stichworte": ["licht", "standlicht", "light", "parking lights"]},
|
||||
{"key": "FEHLERSPEICHER_SENSOR", "label": "Fehlerspeicher", "gruppe": "sicherheit",
|
||||
"hinweis": "Anzahl der Diagnosecodes (DTC). 0 = keine Fehlermeldungen.",
|
||||
"domains": ["sensor"], "device_classes": [], "units": [], "liste": False, "pflicht": False,
|
||||
"beispiel": "number_of_diagnostic_trouble_codes",
|
||||
"stichworte": ["dtc", "fehler", "diagnostic", "trouble", "codes", "fault"]},
|
||||
{"key": "NAECHSTER_OELWECHSEL_SENSOR", "label": "Nächster Ölwechsel", "gruppe": "uebersicht",
|
||||
"hinweis": "Vom Fahrzeug selbst gemeldete Fälligkeit, ergänzt die App-eigene Servicebuch-Prognose.",
|
||||
"domains": ["sensor"], "device_classes": ["date", "timestamp"], "units": [], "liste": False, "pflicht": False,
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":"2026.9.5.35","sha256":"8873fddf9a976ff3317fb16cf4ed708ac19ef76dbf8faf4ff29189e2a5f83a75","bytes":324134,"gebaut":"2026-09-05T15:01:50Z"}
|
||||
{"version":"2026.9.5.39","sha256":"1a78c65f9a96298f7ed97a8595e6505cf91f00a71620b068b4afcfdd14020483","bytes":324341,"gebaut":"2026-09-05T15:29:32Z"}
|
||||
Binary file not shown.
@@ -232,6 +232,8 @@ function profilZuCar(p, status) {
|
||||
reichweite: status.reichweite_km,
|
||||
batteriespannung: status.batteriespannung,
|
||||
gesichert: status.gesichert,
|
||||
// Getrennt vom Sicherheitscheck, siehe _fehlerspeicher() im Backend.
|
||||
fehlerspeicher: status.fehlerspeicher ?? null,
|
||||
sicherheitscheck: status.sicherheitscheck || [],
|
||||
zuendung: status.zuendung ?? null,
|
||||
geparktSeit: status.geparkt_seit ?? null,
|
||||
@@ -2298,6 +2300,25 @@ function standAlterTicken() {
|
||||
const sy = $("#sync span"); if (sy) sy.textContent = standAlterText();
|
||||
}
|
||||
|
||||
/* Ab wann der Tankbalken rot wird - in KILOMETERN Restreichweite, nicht in
|
||||
Prozent. Die Reichweite ist die Aussage, um die es geht ("wie weit komme ich
|
||||
noch"), und das Fahrzeug rechnet die Fahrweise darin bereits ein; eine
|
||||
Prozentschwelle haette bei 1,71 bis 12,53 km je Liter (in 45 Tagen gemessen)
|
||||
bei ganz unterschiedlichen Restreichweiten ausgeloest.
|
||||
|
||||
90 km ist die Zahl des Eigentuemers, an der myAudi-App beobachtet. Belegt ist
|
||||
daraus nur eine Untergrenze: sein Bildschirmfoto zeigt 70 km rot, ein Wert
|
||||
darueber wurde nie im grauen Zustand festgehalten. Der Dongle liefert kein
|
||||
Reserve- oder Warnsignal (alle 54 Entitaeten geprueft), die Schwelle der
|
||||
myAudi-App steht also in keinen Daten, die wir haben - dies ist eine
|
||||
Festlegung, keine Messung.
|
||||
|
||||
Ohne bekannte Reichweite bleibt der Balken neutral: eine Warnung aus
|
||||
fehlenden Daten waere geraten. */
|
||||
const RESERVE_KM = 90;
|
||||
function tankReserve() {
|
||||
return typeof CAR.reichweite === "number" && CAR.reichweite <= RESERVE_KM;
|
||||
}
|
||||
function vHome() {
|
||||
const g = CAR.gesichert;
|
||||
/* Faehrt der Wagen, kann er nicht gleichzeitig "sicher abgestellt" sein -
|
||||
@@ -2319,7 +2340,10 @@ function vHome() {
|
||||
const statusText = faehrt
|
||||
? "Zündung an"
|
||||
: g === null ? "Status unbekannt" : g ? "Sicher abgestellt" : "Nicht sicher abgestellt";
|
||||
const statusDot = faehrt ? "" : g === null ? "warn" : g ? "" : "bad";
|
||||
/* Amber, nicht gruen: "Zuendung an" ist kein guter Zustand, sondern ein
|
||||
anderer - gruen laese sich als "alles in Ordnung und sicher" (Vorgabe des
|
||||
Eigentuemers, 05.09.2026). */
|
||||
const statusDot = faehrt ? "warn" : g === null ? "warn" : g ? "" : "bad";
|
||||
const pct = CAR.tankPct;
|
||||
const t = naechsterTermin();
|
||||
/* C2/C5/D1: Reihenfolge der myAudi-App - randloses Fahrzeugbild, Name und
|
||||
@@ -2345,7 +2369,7 @@ function vHome() {
|
||||
<div class="fig" style="font-size:60px">${CAR.reichweite != null ? de(CAR.reichweite) : "–"}<span class="unit">km</span></div>
|
||||
<span class="pct">${CAR.tankBekannt ? pct + " %" : "–"}</span>
|
||||
</div>
|
||||
<div class="balken"><i style="width:${pct}%;background:var(--fg)"></i></div>
|
||||
<div class="balken"><i style="width:${pct}%;background:var(${tankReserve() ? "--red" : "--fg"})"></i></div>
|
||||
<span class="label" style="margin-top:12px">Reichweite</span>
|
||||
</div>
|
||||
${(() => {
|
||||
@@ -2436,6 +2460,30 @@ function sicherheitsGruppe(gruppe) {
|
||||
return { eintraege, ok };
|
||||
}
|
||||
|
||||
/* Der Fehlerspeicher des Fahrzeugs, als eigene Zeile unter den vier
|
||||
Sammelzeilen. Er steht bewusst NICHT im Sicherheitscheck und geht damit
|
||||
auch nicht in "sicher abgestellt" ein: ein Eintrag im Fehlerspeicher sagt
|
||||
nichts darueber, ob der Wagen verschlossen dasteht (siehe
|
||||
_fehlerspeicher() im Backend).
|
||||
|
||||
Die Anzahl wird genannt, sobald sie groesser als null ist - "es liegt etwas
|
||||
vor" ohne Zahl waere weniger, als der Sensor hergibt. WELCHER Fehler es
|
||||
ist, steht nicht im Datensatz des Geraets und kann hier deshalb auch nicht
|
||||
stehen. */
|
||||
function fehlerzeile() {
|
||||
const f = CAR.fehlerspeicher || {};
|
||||
const anzahl = typeof f.anzahl === "number" ? f.anzahl : null;
|
||||
const ok = anzahl === null ? null : anzahl === 0;
|
||||
const text = anzahl === null
|
||||
? "Fehlerspeicher unbekannt"
|
||||
: anzahl === 0
|
||||
? "Keine Fehlermeldungen"
|
||||
: anzahl === 1
|
||||
? "1 Fehlermeldung"
|
||||
: `${anzahl} Fehlermeldungen`;
|
||||
return `<div class="row sicherheitszeile">${statusKreis(ok)}
|
||||
<span class="sicherheitszeile-text">${esc(text)}</span></div>`;
|
||||
}
|
||||
function vSicherheit() {
|
||||
const g = CAR.gesichert;
|
||||
const verriegelt = sicherheitsGruppe("verriegelt");
|
||||
@@ -2464,7 +2512,7 @@ function vSicherheit() {
|
||||
return `
|
||||
<div class="szene bleed schmal"><div class="carbox">${bildMitPlatzhalter(bildAdresse("draufsicht.webp"), "draufsicht.webp", "Draufsicht", "carfix klein")}</div></div>
|
||||
<div class="tile" style="display:flex;align-items:center;gap:12px;padding:16px 20px">
|
||||
${faehrt ? '<span class="dot"></span>' : statusKreis(g)}
|
||||
${faehrt ? '<span class="dot warn"></span>' : statusKreis(g)}
|
||||
<span style="font-size:15px;color:var(--fg)">${esc(sammelText)}</span>
|
||||
</div>
|
||||
<div class="tile sicherheitsliste">
|
||||
@@ -2472,6 +2520,7 @@ function vSicherheit() {
|
||||
${zeile("Türen und Klappen geschlossen", tuerenKlappen.ok, "Türen oder Klappen offen", "Türen/Klappen unbekannt", "tuerenklappen")}
|
||||
${zeile("Fenster und Dach geschlossen", fensterDach.ok, "Fenster oder Dach offen", "Fenster/Dach unbekannt")}
|
||||
${zeile("Licht ausgeschaltet", licht.ok, "Licht eingeschaltet", "Licht unbekannt")}
|
||||
${fehlerzeile()}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -3833,7 +3882,9 @@ function vEinst() {
|
||||
<dd>${esc(u.version)}${u.geprueft_am ? `<small>geprüft ${dezeitpunkt(new Date(u.geprueft_am))}</small>` : ""}</dd></div></dl>
|
||||
`;
|
||||
}
|
||||
return u ? `<span class="standmarke">aktuell</span>` : "";
|
||||
// Nur nach einer Pruefung - "aktuell" ohne Pruefung waere eine
|
||||
// Behauptung ohne Grundlage. Wortgleich mit der App.
|
||||
return u && u.geprueft_am ? `<span class="standmarke">aktuell</span>` : "";
|
||||
})()}
|
||||
${INTEGRATION_UPDATE && INTEGRATION_UPDATE.fehler && !INTEGRATION_UPDATE_LAEUFT
|
||||
? `<span class="label" style="margin-top:10px;color:var(--red)">${esc(INTEGRATION_UPDATE.fehler)}</span>`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "audi_dashboard",
|
||||
"name": "Audi Dashboard",
|
||||
"version": "2026.9.5.35",
|
||||
"version": "2026.9.5.39",
|
||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||
"codeowners": [
|
||||
|
||||
@@ -190,6 +190,26 @@ def _sicherheitscheck(hass: HomeAssistant, werte: Sensorzuordnung) -> list[dict]
|
||||
return eintraege
|
||||
|
||||
|
||||
def _fehlerspeicher(hass: HomeAssistant, werte: Sensorzuordnung) -> dict:
|
||||
"""Wie viele Diagnosecodes im Fehlerspeicher stehen.
|
||||
|
||||
BEWUSST NICHT Teil von _sicherheitscheck(): dort steht ausschliesslich,
|
||||
was zu oder verriegelt ist, und daraus rechnet "gesichert" ein UND ueber
|
||||
alle Punkte. Ein Fehlerspeichereintrag sagt nichts darueber, ob der Wagen
|
||||
sicher abgestellt ist - er wuerde die Aussage still verfaelschen.
|
||||
|
||||
"anzahl" ist None, solange kein Sensor zugeordnet ist oder er nichts
|
||||
meldet; die Oberflaechen zeigen das als "unbekannt" und raten nicht auf
|
||||
"keine Fehler".
|
||||
"""
|
||||
roh = zustand_oder_none(hass, werte.FEHLERSPEICHER_SENSOR)
|
||||
anzahl = _zu_zahl(roh)
|
||||
if anzahl is None:
|
||||
return {"anzahl": None, "ok": None}
|
||||
ganz = int(anzahl)
|
||||
return {"anzahl": ganz, "ok": ganz == 0}
|
||||
|
||||
|
||||
def fahrzeugstatus(
|
||||
hass: HomeAssistant,
|
||||
werte: Sensorzuordnung,
|
||||
@@ -238,6 +258,8 @@ def fahrzeugstatus(
|
||||
"batteriespannung": spannung,
|
||||
"gesichert": gesichert,
|
||||
"sicherheitscheck": sicherheitscheck,
|
||||
# Getrennt vom Sicherheitscheck, siehe _fehlerspeicher().
|
||||
"fehlerspeicher": _fehlerspeicher(hass, werte),
|
||||
# Fährt das Fahrzeug gerade? Kommt aus derselben Zündungs-Entität, die
|
||||
# auch die Fahrterkennung als maßgebliches Signal für Fahrtbeginn und
|
||||
# -ende nimmt - damit sagen Anzeige und Erfassung zwangsläufig
|
||||
|
||||
Reference in New Issue
Block a user