@@ -368,12 +368,12 @@ function markenlogo() {
< span class = "ph" > $ { esc ( label ) } < / s p a n >
< / s p a n > ` ;
}
const OHNE _SZENE = [ "Cockpit" , "Sitze" , "Scheinwerfer" ] ;
function szeneKlasse ( i ) {
if ( ! bodenAn ) return "" ;
if ( OHNE _SZENE . includes ( BILDER [ i ] . name ) ) return "" ;
return CAR . reifen . aktiv === "Winter" ? "winter" : "strasse" ;
}
/ * D e r a n g e d e u t e t e B o d e n u n t e r d e m F a h r z e u g i s t a m 2 0 2 6 - 0 8 - 3 1 e n t f a l l e n -
der Eigentuemer wollte den Schatten weg , und damit hatte auch der
Schalter dafuer nichts mehr zu schalten . Frueher stand hier
szeneKlasse ( ) , das je nach Bild und Reifensatz "strasse" oder "winter"
an . szene haengte ; die zugehoerigen : : after - Regeln sind in
audi - dashboard . css beschrieben . * /
function bildWeiter ( ) {
bild = ( bild + 1 ) % BILDER . length ;
const img = ROOT . getElementById ( "carimg" ) ;
@@ -387,7 +387,7 @@ function bildWeiter() {
box . querySelector ( ".platzhalter-label" ) . textContent = info . label ;
}
const sz = ROOT . getElementById ( "szene" ) ;
if ( sz ) sz . className = "szene " + szeneKlasse ( bild ) ;
if ( sz ) sz . className = "szene" ;
[ ... ROOT . getElementById ( "dots" ) . children ] . forEach ( ( d , i ) => d . classList . toggle ( "on" , i === bild ) ) ;
}
@@ -1654,7 +1654,7 @@ function vHome() {
zwei kurze , haeufig gelesene Textzeilen lagen bisher unter einer 190 px
hohen Karte und damit auf dem Telefon unterhalb des ersten Bildschirms . * /
return `
< div class = "szene bleed ${szeneKlasse(startIndex())} " > < div class = "carbox" > $ { carImg ( "fest" ) } < / d i v > < / d i v >
< div class = "szene bleed" > < div class = "carbox" > $ { carImg ( "fest" ) } < / d i v > < / d i v >
< div class = "tile flat" style = "margin-bottom:20px" >
$ { badge ( ) }
< span class = "label" style = "margin-top:10px" > $ { esc ( CONFIG . kennzeichen ) } < / s p a n >
@@ -1815,7 +1815,7 @@ function vTuerenKlappen() {
function vAudi ( ) {
const r = CAR . reifen , a = r [ r . aktiv . toLowerCase ( ) ] ;
return `
< div class = "szene ${szeneKlasse(bild)} " id = "szene" > < div class = "carbox" > $ { carImg ( "galerie" ) } < / d i v > < / d i v >
< div class = "szene" id = "szene" > < div class = "carbox" > $ { carImg ( "galerie" ) } < / d i v > < / d i v >
< div class = "tile flat" style = "margin:14px 0 16px" >
$ { badge ( ) }
< span class = "label" style = "margin-top:12px" > $ { esc ( CONFIG . kennzeichen ) } < / s p a n >
@@ -2793,7 +2793,6 @@ const SCHRIFT_KEY = "audi-dashboard-tableiste-schrift";
let beschriftung = ( ( ) => {
try { return localStorage . getItem ( SCHRIFT _KEY ) !== "aus" ; } catch ( e ) { return true ; }
} ) ( ) ;
let bodenAn = true ;
function csvDatei ( name , kopf , zeilen ) {
const txt = [ kopf . join ( ";" ) ] . concat ( zeilen . map ( ( r ) => r . join ( ";" ) ) ) . join ( "\r\n" ) ;
const a = document . createElement ( "a" ) ;
@@ -2858,10 +2857,6 @@ function vEinst() {
< label for = "schrift" > Beschriftung in der Menüleiste < / l a b e l >
< label class = "switch" > < input id = "schrift" type = "checkbox" data - schrift $ { beschriftung ? "checked" : "" } > < span class = "track" > < / s p a n > < / l a b e l > < / d i v >
< span class = "label" style = "margin-top:14px" > Aus zeigt nur die Symbole und gibt etwas Höhe frei < / s p a n >
< div class = "feld" style = "margin-top:16px;border-bottom:0" >
< label for = "boden" > Fahrbahn unter dem Fahrzeug < / l a b e l >
< label class = "switch" > < input id = "boden" type = "checkbox" data - boden $ { bodenAn ? "checked" : "" } > < span class = "track" > < / s p a n > < / l a b e l > < / d i v >
< span class = "label" style = "margin-top:14px" > Angedeutete Fahrbahn mit Schatten , nur bei Außenansichten < / s p a n >
< / d i v >
< div class = "tile" > < span class = "label" > Bild der Übersicht < / s p a n >
< div class = "feld" style = "border-bottom:0" > < label for = "startbild" > Ansicht < / l a b e l >
@@ -3040,6 +3035,10 @@ function entitaetScore(feld, e, suchtext) {
if ( feld . domains && feld . domains . includes ( e . domain ) ) score += 3 ;
if ( feld . device _classes && feld . device _classes . length && feld . device _classes . includes ( e . deviceClass ) ) score += 3 ;
if ( feld . units && feld . units . length && feld . units . includes ( e . unit ) ) score += 2 ;
// Der Signalname aus dem Katalog ("z. B. can_fuel_volume") ist der
// treffsicherste Hinweis, den es gibt - deutlich mehr wert als ein
// einzelnes Stichwort.
if ( feld . beispiel && hay . includes ( feld . beispiel . toLowerCase ( ) ) ) score += 8 ;
if ( suchtext && hay . includes ( suchtext . trim ( ) . toLowerCase ( ) ) ) score += 10 ;
return score ;
}
@@ -3048,7 +3047,7 @@ function entitaetKandidaten(feldKey, suchtext, aktuellerWert) {
const feld = setupKatalog ( ) . find ( ( f ) => f . key === feldKey ) ;
if ( ! feld ) return [ ] ;
const text = ( suchtext || "" ) . trim ( ) . toLowerCase ( ) ;
const liste = ALLE _ENTITAETEN . filter ( ( e ) => {
let liste = ALLE _ENTITAETEN . filter ( ( e ) => {
if ( e . id === aktuellerWert ) return true ;
if ( setupNurPassend ) {
if ( feld . domains && feld . domains . length && ! feld . domains . includes ( e . domain ) ) return false ;
@@ -3065,6 +3064,27 @@ function entitaetKandidaten(feldKey, suchtext, aktuellerWert) {
if ( text && ! ( e . id . toLowerCase ( ) . includes ( text ) || e . name . toLowerCase ( ) . includes ( text ) ) ) return false ;
return true ;
} ) ;
/ * " N u r p a s s e n d e S e n s o r e n " s u c h t z u s a e t z l i c h n a c h d e m N a m e n , d e r n e b e n d e r
Ueberschrift als "(z. B. ...)" steht - dem tatsaechlichen Signalnamen der
Integration , nicht einem ausgedachten Beispiel ( siehe FELDER in
einstellungen . py ) . Domain und Einheit allein lassen bei einem Fahrzeug
mit siebzig Sensoren immer noch Dutzende uebrig ; der Signalname trifft
genau einen .
Mit Rueckfall : findet der Name nichts , bleibt die ungefilterte Liste
stehen . Eine leere Auswahl waere schlimmer als eine lange - der Beispiel -
name stammt aus dieser einen Installation , eine andere kann ihre Signale
anders nennen . * /
if ( setupNurPassend && feld . beispiel ) {
const beispiel = feld . beispiel . toLowerCase ( ) ;
const genau = liste . filter (
( e ) =>
e . id === aktuellerWert ||
e . id . toLowerCase ( ) . includes ( beispiel ) ||
e . name . toLowerCase ( ) . includes ( beispiel . replace ( /_/g , " " ) ) ,
) ;
if ( genau . length ) liste = genau ;
}
liste . sort ( ( a , b ) => entitaetScore ( feld , b , suchtext ) - entitaetScore ( feld , a , suchtext ) ) ;
return liste . slice ( 0 , 60 ) ;
}
@@ -3647,6 +3667,13 @@ function vStat() {
const fJahr = fahrtenSeit ( "jahr" ) , fMonat = fahrtenSeit ( "monat" ) , fWoche = fahrtenSeit ( "woche" ) , fTag = fahrtenSeit ( "tag" ) ;
const fAbs = fahrtenSeit ( "absolut" ) , tAbs = tankSeit ( "absolut" ) ;
const kmJahr = sum ( fJahr , ( t ) => t . distance _km ) , hJahr = sum ( fJahr , ( t ) => t . duration _s ) / 3600 ;
// Die grosse Zahl oben in den beiden Kacheln zeigt seit dem 2026-08-31 den
// Gesamtwert, nicht mehr den des laufenden Jahres (Ansage des Eigentuemers).
// Damit steht "Absolut" dort, wo man es zuerst liest, und die Spalten
// darunter bleiben die vier Zeitraeume - fuenf passten auf dem Telefon
// nachweislich nicht in eine Zeile.
const kmAbs = sum ( fAbs , ( t ) => t . distance _km ) , hAbs = sum ( fAbs , ( t ) => t . duration _s ) / 3600 ;
const lAbs = sum ( tAbs , ( f ) => f . liters ) , eAbs = sum ( tAbs , ( f ) => f . fuel _total _eur || 0 ) ;
const tJahr = tankSeit ( "jahr" ) ;
const lJahr = sum ( tJahr , ( f ) => f . liters ) , eJahr = sum ( tJahr , ( f ) => f . fuel _total _eur || 0 ) ;
const tagKm = sum ( fJahr . filter ( ( t ) => ! istNachtZeit ( t . ts _start ) ) , ( t ) => t . distance _km ) ;
@@ -3655,12 +3682,12 @@ function vStat() {
const arbeitKm = sum ( arbeitFahrten , ( t ) => t . distance _km ) , privatKm = kmJahr - arbeitKm ;
const lv = langzeitverbrauch ( ) ;
return `
$ { statTile ( "s1" , ` Distanz und Fahrzeit ${ jahr } ` , de ( kmJahr ) , "km" , de ( hJahr ) + " h" ,
quad ( "Gefahrene Distanz [km]" , [ [ de ( kmJahr ) , "Jahr" ] , [ de ( sum ( fMonat , ( t ) => t . distance _km ) ) , "Monat" ] , [ de ( sum ( fWoche , ( t ) => t . distance _km ) ) , "Woche" ] , [ de ( sum ( fTag , ( t ) => t . distance _km ) ) , "Tag" ] , [ de ( sum ( fAbs , ( t ) => t . distance _km ) ) , "Absolut" ] ] ) +
quad ( "Fahrzeit [h]" , [ [ de ( hJahr ) , "Jahr" ] , [ de ( sum ( fMonat , ( t ) => t . duration _s ) / 3600 ) , "Monat" ] , [ de ( sum ( fWoche , ( t ) => t . duration _s ) / 3600 , 1 ) , "Woche" ] , [ de ( sum ( fTag , ( t ) => t . duration _s ) / 3600 , 1 ) , "Tag" ] , [ de ( sum ( fAbs , ( t ) => t . duration _s ) / 3600 ) , "Absolut" ] ] ) ) }
$ { statTile ( "s2" , ` Getankte Menge und Kosten ${ jahr } ` , de ( lJahr ) , "l" , de ( eJahr ) + " €" ,
quad ( "Getankte Liter [l]" , [ [ de ( lJahr ) , "Jahr" ] , [ de ( sum ( tankSeit ( "monat" ) , ( f ) => f . liters ) ) , "Monat" ] , [ de ( sum ( tankSeit ( "woche" ) , ( f ) => f . liters ) ) , "Woche" ] , [ de ( sum ( tankSeit ( "tag" ) , ( f ) => f . liters ) ) , "Tag" ] , [ de ( sum ( tAbs , ( f ) => f . liters ) ) , "Absolut" ] ] ) +
quad ( "Kraftstoffkosten [€]" , [ [ de ( eJahr ) , "Jahr" ] , [ de ( sum ( tankSeit ( "monat" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Monat" ] , [ de ( sum ( tankSeit ( "woche" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Woche" ] , [ de ( sum ( tankSeit ( "tag" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Tag" ] , [ de ( sum ( tAbs , ( f ) => f . fuel _total _eur || 0 ) ) , "Absolut" ] ] ) ) }
$ { statTile ( "s1" , " Distanz und Fahrzeit" , de ( kmAbs ) , "km" , de ( hAbs ) + " h" ,
quad ( "Gefahrene Distanz [km]" , [ [ de ( kmJahr ) , "Jahr" ] , [ de ( sum ( fMonat , ( t ) => t . distance _km ) ) , "Monat" ] , [ de ( sum ( fWoche , ( t ) => t . distance _km ) ) , "Woche" ] , [ de ( sum ( fTag , ( t ) => t . distance _km ) ) , "Tag" ] ] ) +
quad ( "Fahrzeit [h]" , [ [ de ( hJahr ) , "Jahr" ] , [ de ( sum ( fMonat , ( t ) => t . duration _s ) / 3600 ) , "Monat" ] , [ de ( sum ( fWoche , ( t ) => t . duration _s ) / 3600 , 1 ) , "Woche" ] , [ de ( sum ( fTag , ( t ) => t . duration _s ) / 3600 , 1 ) , "Tag" ] ] ) ) }
$ { statTile ( "s2" , " Getankte Menge und Kosten" , de ( lAbs ) , "l" , de ( eAbs ) + " €" ,
quad ( "Getankte Liter [l]" , [ [ de ( lJahr ) , "Jahr" ] , [ de ( sum ( tankSeit ( "monat" ) , ( f ) => f . liters ) ) , "Monat" ] , [ de ( sum ( tankSeit ( "woche" ) , ( f ) => f . liters ) ) , "Woche" ] , [ de ( sum ( tankSeit ( "tag" ) , ( f ) => f . liters ) ) , "Tag" ] ] ) +
quad ( "Kraftstoffkosten [€]" , [ [ de ( eJahr ) , "Jahr" ] , [ de ( sum ( tankSeit ( "monat" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Monat" ] , [ de ( sum ( tankSeit ( "woche" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Woche" ] , [ de ( sum ( tankSeit ( "tag" ) , ( f ) => f . fuel _total _eur || 0 ) ) , "Tag" ] ] ) ) }
$ { statTile ( "s3" , "Langzeitverbrauch" , lv . wert , "l/100 km" , lv . bis ? "bis " + dedat ( lv . bis ) : "– " ,
` <dl class="rows">
< div class = "row" > < dt > Getankt insgesamt < / d t > < d d > $ { d e ( l v . l i t e r , 1 ) } l < / d d > < / d i v >
@@ -3668,7 +3695,7 @@ function vStat() {
< div class = "row" style = "border-bottom:0" > < dt > Letzter Tankstop < / d t > < d d > $ { l v . b i s ? d e d a t ( l v . b i s ) : " – " } < / d d > < / d i v >
< / d l >
$ { lv . unplausibel ? ` <span class="label" style="margin-top:16px;color:var(--warn)">Aus Litern und Strecke ergibt sich derzeit kein plausibler Wert. Sobald Tankvorgänge und Kilometerstände vollständig vorliegen, erscheint er hier.</span> ` : "" }
$ { quad ( "Näherung je Fahrt, je Zeitraum [l/100 km]" , [ [ schnittFahrtVerbrauch ( fJahr ) , "Jahr" ] , [ schnittFahrtVerbrauch ( fMonat ) , "Monat" ] , [ schnittFahrtVerbrauch ( fWoche ) , "Woche" ] , [ schnittFahrtVerbrauch ( fTag ) , "Tag" ] , [ schnittFahrtVerbrauch ( fAbs ) , "Absolut" ] ] ) }
$ { quad ( "Näherung je Fahrt, je Zeitraum [l/100 km]" , [ [ schnittFahrtVerbrauch ( fJahr ) , "Jahr" ] , [ schnittFahrtVerbrauch ( fMonat ) , "Monat" ] , [ schnittFahrtVerbrauch ( fWoche ) , "Woche" ] , [ schnittFahrtVerbrauch ( fTag ) , "Tag" ] ] ) }
< span class = "label" style = "margin-top:16px" > Der Langzeitwert rechnet alle je getankten Liter gegen die Strecke bis zum letzten Tankstop . Die Werte je Zeitraum sind eine Näherung aus der Tankfüllstand - Differenz der einzelnen Fahrten , keine Meldung des Fahrzeugs . < / s p a n > ` ) }
$ { statTile ( "s4" , "Tag und Nacht" , kmJahr > 0 ? de ( Math . round ( ( tagKm / kmJahr ) * 100 ) ) : "– " , "% bei Tag" , de ( tagKm ) + " km" ,
` <div class="bar"><i style="flex: ${ tagKm } ;background:var(--fg)"></i><i style="flex: ${ nachtKm } ;background:var(--fg3)"></i></div>
@@ -5773,7 +5800,6 @@ function ereignisseVerdrahten() {
}
if ( e . target . dataset . oelkm !== undefined ) { CAR . oel . km = parseInt ( e . target . value , 10 ) ; profilSpeichern ( ) ; return ; }
if ( e . target . dataset . oelm !== undefined ) { CAR . oel . monate = parseInt ( e . target . value , 10 ) ; profilSpeichern ( ) ; return ; }
if ( e . target . dataset . boden !== undefined ) { bodenAn = e . target . checked ; render ( ) ; return ; }
if ( e . target . dataset . setupNurpassend !== undefined ) { setupNurPassend = e . target . checked ; render ( ) ; return ; }
if ( e . target . dataset . startbild !== undefined ) { CONFIG . startbild = e . target . value ; profilSpeichern ( ) ; render ( ) ; return ; }
if ( e . target . dataset . svsel !== undefined ) { svAuswahl = parseInt ( e . target . value , 10 ) ; render ( ) ; return ; }