Tankstelle zweizeilig und antippbar, Belegkarte ohne toten Knopf (2026.9.4.5)
Sieben Meldungen des Eigentuemers, beide Codebasen. Karte im Einzelbeleg: "Position laedt nicht" und "der Button funktioniert nicht" waren dieselbe Stelle - ohne aufloesbaren Ort malte das Panel einen beliebigen Ausschnitt und liess den Zentrieren-Knopf fuer immer disabled. Beide zeigen jetzt die Auskunft statt einer Karte und unterscheiden dabei "steht nicht im Beleg" von "findet niemand". Dazu ein echter Paritaetsmangel: die App schlug nur station_address nach, das Panel faellt seit jeher auf den Namen zurueck - von 16 Testbelegen tragen vier eine Anschrift. Der Suchbegriff darf Name und Anschrift NICHT zusammensetzen: gemessen findet Nominatim "Pascalstr. 8, 85057 Ingolstadt", mit dem Betreibernamen davor nichts. Jetzt zwei Kandidaten nacheinander (Anschrift, dann Name); fuer den Kartendienst dagegen beides zusammen, weil Apple und Google Betriebsnamen kennen. Tankstelle steht ueber die volle Kachelbreite, zweizeilig (Tankstelle und Strasse / Ort) und fuehrt beim Tippen in den Standard-Kartendienst - Apple Karten auf Apple-Geraeten, sonst Google Maps. Dieselbe Wahl jetzt auch fuer Fahrzeugstandort und Autohaus. SmartDeal-Ersparnis brach um, weil die dt-Spalte 150,00px breit war und ihr Inhalt 150,20px - zwei Zehntel Pixel, Zeile dadurch 44,8 statt 26,4px hoch. Der Regler "Fahrt beenden" schreibt nicht mehr beim Loslassen: derselbe Wert stellt den Schlaf-Timeout des Dongles, das soll bewusst ausgeloest werden. Speichern/Verwerfen erscheinen nur bei echter Aenderung. Share-Erweiterung: an der ausgelieferten .ipa gemessen trug sie 1.0, die App 2026.9.3.3 - iOS registriert eine Erweiterung mit abweichender Versionsnummer nicht, sie fehlt dann im Teilen-Blatt. ios-signieren.sh schreibt die Version jetzt in beide Ziele und liest die fertige .ipa gegen. Zwischenablage: dritter Weg ueber UIPasteboard.itemProviders, und ein fehlender nativer Teil wird als solcher gemeldet statt als "Kein Zugriff". Am Geraet gesetzt: 1003 Network Ping Timeout 0 -> 60 s, 1004 ACK Type TCP/IP -> AVL. Beide liegen bei flespi als pending bereit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
# AGENTS.md — Project state, review findings, open items, and working rules
|
||||
|
||||
**Last updated: 2026-09-04** (Geraetezeit statt Ankunftszeit - die Wurzel hinter der 3-km-Fahrt:
|
||||
**Last updated: 2026-09-04** (Tankstelle zweizeilig und antippbar, die Belegkarte sagt bei
|
||||
fehlender Position die Wahrheit statt einen toten Knopf zu zeigen, der Regler bekommt einen
|
||||
Speichern-Knopf, und die Share-Erweiterung trug eine andere Versionsnummer als die App - `2026.9.4.5`,
|
||||
Abschnitt CC. Davor: Geraetezeit statt Ankunftszeit - die Wurzel hinter der 3-km-Fahrt:
|
||||
das Fahrtfenster stand in Geraetezeit, der Verlauf war nach Ankunftszeit sortiert. Dazu die neun
|
||||
Paritaetsbefunde und die verunreinigte Batteriehistorie, `2026.9.4.1`, Abschnitt CB. Davor: Der Regler stellt den Schlaf-Timeout des Dongles, flespi lesend und
|
||||
schreibend, die eigene Warteschlange wieder entfallen, `2026.9.3.10`, Abschnitt BZ. Davor: Zugaenge: die Dienste-Token aus App und Panel bedienbar, der Wert kommt nie
|
||||
@@ -9462,3 +9465,167 @@ resting voltage, the SOC, the SOH trend and the fallback shown in "Mein Audi / Z
|
||||
the same mechanism as `wert_in_naehe()` with its 300 s window for the outside temperature. Without a
|
||||
vehicle, nothing gets recorded. The 13 existing entries are the owner's data; removal is via the
|
||||
swipe gesture in the measurement list.
|
||||
|
||||
## CC. Tankstelle zweizeilig und antippbar, die Belegkarte sagt die Wahrheit, der Regler bekommt einen Knopf (2026.9.4.5)
|
||||
|
||||
Sieben Meldungen des Eigentuemers, dazu die beiden Dongle-Parameter aus dem Vortag.
|
||||
|
||||
### Der Dongle steht jetzt auf 1003 = 60 und 1004 = AVL
|
||||
|
||||
Am Geraet nachgesehen statt angenommen: `network_ping.timeout` stand auf **0** und
|
||||
`ack_type.mode` auf **0 (TCP/IP)** — die Werte, die am 03.09. die tote TCP-Sitzung
|
||||
unbemerkt liessen (Abschnitt CB). Beide ueber `PUT /gw/devices/{id}/settings/{name}`
|
||||
mit `{"properties": …, "address": "connection"}` geschrieben, dieselbe Form wie
|
||||
`schlaf_timeout_schreiben()`. flespi haelt sie als **`pending`** vor und stellt sie
|
||||
zu, sobald sich das Geraet meldet; `current` steht bis dahin unveraendert auf 0/0.
|
||||
`records_params` (1000 = 60 s, 1001 = 30 s, 1002 = Oldest) bleibt wie es war.
|
||||
|
||||
### "Einzelbeleg/Map laedt die Position nicht" und "der Button funktioniert nicht"
|
||||
|
||||
**Dieselbe Stelle, ein Befund.** Reproduziert an einem Beleg ohne aufloesbare
|
||||
Anschrift: das Panel zeichnete dann einen beliebigen Kartenausschnitt und liess den
|
||||
Zentrieren-Knopf fuer immer `disabled`; die App zeigte ihren Leerzustand — und
|
||||
suchte gar nicht erst, weil `TankstellenKarte` ausschliesslich `station_address`
|
||||
nachschlug. Von 16 Tankvorgaengen der Testinstanz tragen **vier** eine Anschrift;
|
||||
das Panel faellt seit jeher auf den Namen zurueck (`f.station_address ||
|
||||
f.station_name`), die App nicht.
|
||||
|
||||
Beide zeigen jetzt bei fehlender Position **keine Karte**, sondern die Auskunft —
|
||||
und unterscheiden dabei "steht nicht im Beleg" von "findet niemand". Im Panel
|
||||
entscheidet das `BELEG_KARTE`, ein Merker, den `initMap()` setzt, wenn der
|
||||
Nachschlag erfolglos zurueckkommt; `go()` und das Speichern eines Tankvorgangs
|
||||
raeumen ihn wieder ab, damit eine korrigierte Anschrift erneut gesucht wird.
|
||||
|
||||
**Der Suchbegriff war der zweite Fallstrick, und er hat mich einmal erwischt.**
|
||||
Die erste Fassung setzte Name UND Anschrift zusammen, mit der Begruendung "eine
|
||||
Hausnummer ohne Betrieb trifft in Gewerbegebieten das Nachbargebaeude". Live
|
||||
gemessen ist das genau falsch herum: `"Pascalstr. 8, 85057 Ingolstadt"` findet
|
||||
Nominatim, `"A. Zrenner GmbH, Pascalstr. 8, 85057 Ingolstadt"` **nicht** — der
|
||||
Betreibername steht in keiner Karte. Sichtbar wurde es sofort als "Keine Position"
|
||||
bei einem Beleg, dessen Anschrift sich vorher aufloesen liess.
|
||||
|
||||
Deshalb jetzt zwei getrennte Begriffe:
|
||||
|
||||
* `tankstelleKandidaten()` — **erst die Anschrift, dann der Name**, nacheinander
|
||||
versucht. Der Name allein ist wertvoll (`"Shell, SÖLDEN"` findet Nominatim), nur
|
||||
eben nicht als Praefix.
|
||||
* `tankstelleZiel()` — Name UND Anschrift, aber nur fuer den Kartendienst: Apple
|
||||
Karten und Google Maps kennen Betriebsnamen und sind darin deutlich besser als
|
||||
Nominatims Freitextsuche.
|
||||
|
||||
### Die Tankstelle steht ueber die volle Breite, in zwei Zeilen, und fuehrt in die Karten
|
||||
|
||||
Vorgabe des Eigentuemers: erste Zeile Tankstelle und Strasse, zweite Zeile der Ort,
|
||||
Tippen oeffnet den Standard-Kartendienst. Vorher eine gewoehnliche Wertzeile mit
|
||||
120px Wertespalte — "Hermann Mogler Mineraloelg. GmbH, Heidenheimerstr.6, 89551
|
||||
Koenigsbronn" stand dort vier- bis fuenfzeilig.
|
||||
|
||||
Geteilt wird am **letzten** Komma (der Belegparser setzt `"<Strasse>, <PLZ Ort>"`
|
||||
zusammen), damit ein Zusatz bei der Strasse bleibt; ohne Komma bleibt alles in der
|
||||
ersten Zeile statt einen Ort zu erfinden. `kartendienstUrl()` waehlt nach Geraet:
|
||||
`maps.apple.com` auf Apple-Geraeten, sonst `google.com/maps/dir`. Dieselbe Wahl
|
||||
gilt jetzt auch fuer den Fahrzeugstandort und das Autohaus — drei Verweise, ein
|
||||
Dienst.
|
||||
|
||||
**Zwei CSS-Fallen dabei, beide erst am laufenden Panel sichtbar:**
|
||||
|
||||
1. `.tankstellenzeile dt` (0,1,1) verliert gegen `.row dt` im **iOS-Overlay**, das
|
||||
spaeter geladen wird — die Schriftgroesse blieb 16px. Die Regeln heissen deshalb
|
||||
`.row.tankstellenzeile …` (0,2,1) und gewinnen unabhaengig von der Reihenfolge.
|
||||
2. `.rows-fest dt { flex: 0 0 150px }` — in einer **Spalte** ist die Flex-Basis die
|
||||
HOEHE. Der Titel "Tankstelle" war damit 150px hoch, die Zeile 214px. `flex: 0 0
|
||||
auto` in derselben Regel hebt es auf. Gemessen 82px danach.
|
||||
|
||||
**Merkposten, zum dritten Mal in dieser Datei:** eine Regel, die im Overlay einen
|
||||
Namensvetter hat, braucht den Wert des Overlays oder hoehere Spezifitaet — und eine
|
||||
Flex-Angabe bedeutet in einer Spalte etwas anderes als in einer Zeile.
|
||||
|
||||
### "Wozu der Zeilenumbruch bei SmartDeal-Ersparnis?"
|
||||
|
||||
Kein Platzmangel, sondern ein Rundungsfehler, am Einzelbeleg bei 375px gemessen:
|
||||
die dt-Spalte war **150,00px** breit, ihr eigener Inhalt **150,20px** — der Text
|
||||
hinter dem Markenlogo rutschte in eine zweite Zeile, die Zeile wurde 44,8px statt
|
||||
26,4px hoch. Zwei Zehntel Pixel. `.marke { white-space: nowrap }` in beiden
|
||||
Codebasen, und die Wertespalte gibt in genau dieser Zeile ihre feste Mindestbreite
|
||||
auf (`.rows-fest .row-marke dd { min-width: 0 }`); ohne das stuende sie um 10px
|
||||
ueber. Live bestaetigt: 26,4px, eine Zeile.
|
||||
|
||||
### Der Regler schreibt nicht mehr beim Loslassen
|
||||
|
||||
Vorgabe des Eigentuemers, und sie ist richtig: derselbe Wert stellt den
|
||||
Schlaf-Timeout des Dongles — eine Aenderung am Fahrzeug ueber zwei Netze, die
|
||||
bewusst ausgeloest werden soll und nicht als Nebenwirkung einer Wischgeste.
|
||||
|
||||
Apples Richtlinien lassen einen Regler sonst sofort wirken; die Ausnahme ist genau
|
||||
dieser Fall, und das Muster dafuer ist der bestaetigende Knopf. Er erscheint **nur**,
|
||||
wenn der Regler wirklich woanders steht (ein dauerhaft sichtbarer, meist
|
||||
wirkungsloser Knopf waere Beiwerk), daneben "Verwerfen" als schlichter Text —
|
||||
dieselbe Anordnung wie in der Speicherleiste der App am Seitenende.
|
||||
|
||||
Panel: `PAUSENZEIT_ENTWURF` neben `CONFIG.pausenzeit`; der `input`-Zweig zieht nur
|
||||
Fuellung und Anzeige nach (ein `render()` mitten in der Geste erzeugt den Regler neu
|
||||
und der Daumen springt aus der Hand), der `change`-Zweig setzt den Entwurf und
|
||||
zeichnet neu, geschrieben wird erst auf Knopfdruck. App: eigener
|
||||
`pausenzeitEntwurf`-Zustand **neben** dem Seitenentwurf, und `speichern(zusatz)`
|
||||
nimmt den Wert als Argument entgegen — `setState` wirkt erst beim naechsten
|
||||
Durchlauf, der Seitenentwurf trueg im selben Rendern noch den alten.
|
||||
|
||||
Live in beiden geprueft (Regler bewegt, Knopf erscheint, "Verwerfen" stellt 15 Min.
|
||||
wieder her). **"Speichern" bewusst NICHT gedrueckt** — das schriebe einen neuen
|
||||
Schlaf-Timeout an den echten Dongle.
|
||||
|
||||
### Teilen-Erweiterung und Zwischenablage am iPhone
|
||||
|
||||
Die ausgelieferte `App.ipa` vom 03.09. wurde entpackt und geprueft, statt zu raten.
|
||||
**Fast alles ist in Ordnung:** die `.appex` traegt ein echtes arm64-Programm
|
||||
(110.320 Bytes), App und Erweiterung haben beide `group.app.datametric360` in ihren
|
||||
Entitlements, das URL-Schema `datametric360` steht im Info.plist, und
|
||||
`BelegZwischenablagePlugin` ist im App-Programm enthalten.
|
||||
|
||||
**Ein Befund, und er erklaert genau "die Erweiterung erscheint nicht":** die
|
||||
Versionsnummern stimmen nicht ueberein — App `2026.9.3.3`, Erweiterung `1.0`.
|
||||
Apples App Extension Programming Guide verlangt Gleichheit, und iOS registriert
|
||||
eine Erweiterung mit abweichender Nummer nicht. `ios-signieren.sh` schrieb die
|
||||
Version bis dahin nur in `ios/App/App/Info.plist`; `native/teilen/Info.plist`
|
||||
traegt die 1.0 fest. Jetzt bekommen **beide** Ziele dieselbe
|
||||
`CFBundleShortVersionString` und `CFBundleVersion`.
|
||||
|
||||
Dazu, aus der Lehre von Abschnitt AK (von fuenf Fehlern in der nativen Huelle haben
|
||||
vier einen erfolgreichen Archivlauf erzeugt): das Skript liest die **fertige .ipa**
|
||||
gegen — Programm in der `.appex` vorhanden, Versionen gleich, App-Gruppe auf beiden
|
||||
Zielen — und warnt, statt es dem naechsten Fehlerbericht zu ueberlassen.
|
||||
|
||||
Fuer die Zwischenablage kommt ein dritter Weg dazu: `UIPasteboard.itemProviders`.
|
||||
Manche Apps legen eine Datei nur als **Zusage** ab — dann gibt
|
||||
`data(forPasteboardType:)` nil zurueck und `urls` bleibt leer, nur der Anbieter
|
||||
kennt sie. Und `zwischenablage.ts` fragt jetzt `Capacitor.isPluginAvailable()`:
|
||||
fehlt der native Teil (eine App, die nur ueber OTA gewachsen ist), sagt die Meldung
|
||||
das, statt "Kein Zugriff auf die Zwischenablage" — die schickt in die falsche
|
||||
Richtung.
|
||||
|
||||
**Was das nicht kann:** ohne Mac laesst sich keine dieser Aenderungen ausprobieren.
|
||||
Der native Teil kommt ausschliesslich ueber einen Xcode-Lauf aufs Geraet, nie ueber
|
||||
das OTA-Buendel.
|
||||
|
||||
**Bewusst nicht angefasst:** die `NSExtensionActivationRule`. Sie ist heute
|
||||
grosszuegig (jede Datei, jeder Anhang) und laesst die App im Teilen-Blatt
|
||||
erscheinen; ein strenges Praedikat waere sauberer, koennte sie aber ungeprueft ganz
|
||||
verschwinden lassen.
|
||||
|
||||
### Fahrt `t-66c4209276e7` bleibt bei 3,0 km
|
||||
|
||||
Ausdrueckliche Ansage des Eigentuemers ("Fahrt nicht neu rechnen"). Das Screening
|
||||
fuellt grundsaetzlich nur leere Felder — der gespeicherte Wert bleibt damit von
|
||||
selbst stehen.
|
||||
|
||||
### Testinstanz: was von dieser Sitzung dort liegenbleibt
|
||||
|
||||
* **`f-8852746248fa` traegt jetzt `discount: 12.9`** — von Hand gesetzt, um die
|
||||
SmartDeal-Zeile ueberhaupt sichtbar zu machen (alle Testbelege hatten `null`).
|
||||
Sinnvoll fuer die naechste Sichtpruefung, aber es ist eine Aenderung an den Daten
|
||||
des Containers.
|
||||
* **`/config/www/dmapp/`** haelt das gebaute Webbuendel; unter
|
||||
`http://localhost:18123/local/dmapp/index.html` laeuft die App **gleichursprunglich**
|
||||
zur Testinstanz. Das ist der Weg, die App live zu pruefen, ohne an CORS zu
|
||||
scheitern: `cors_allowed_origins` in der `configuration.yaml` blieb wirkungslos
|
||||
(Preflight weiterhin 403), der eingetragene Block ist deshalb wieder entfernt.
|
||||
|
||||
Reference in New Issue
Block a user