Statistik-Icon-Groesse, Batteriediagramm-Ueberarbeitung, Temperatur-Kopplung mit 300s-Fenster, letzte gueltige Spannung als Fallback
- Statistik-Tab-Icon per zentrierter Stauchung an die Fuellflaeche der anderen Tab-Icons angeglichen (Panel + companion-app), auf Nutzerwunsch anschliessend 10% groesser. - Batteriediagramm neu gezeichnet: dynamische viewBox (1 Einheit = 1 Pixel, kein preserveAspectRatio-Verzerren mehr), ein Punkt je Ruhespannungsmessung statt Datumsbeschriftung, Tageshoechstwert nur noch im Tooltip. Generator- spannungen (> AGM_RUHE_MAX_V = 13,0 V, vom Nutzer festgelegt) bleiben aus dem Diagramm aussen vor; der SOC-Kurve-Eckwert "100% / voll" bleibt bei den ursprünglich recherchierten 12,8 V. companion-app auf dieselbe lineare SOC-Interpolation umgestellt (vorher eine abweichende Stufenkurve). - Außentemperatur wird jetzt auch beim Batterieverlauf-Import nachgetragen (vorher nur live) - Kopplung an die naechstgelegene Messung innerhalb NEBENWERT_MAX_ABSTAND_S (verlauf.py), vom Nutzer nach Live-Daten-Analyse auf 300s festgelegt. Merge-Logik in ablage.py ergaenzt: ein erneuter Import kann eine zuvor fehlende Temperatur jetzt tatsaechlich nachtragen, auch wenn sich der Tagesminimalwert selbst nicht aendert. - "Mein Audi"/Zustand zeigt bei unplausibler Live-Messung (z. B. Dongle offline) die zuletzt gemessene Spannung statt "unbekannt". Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -3442,6 +3442,281 @@ correctly exceeding `UNPLAUSIBLE_KMH=300` and therefore now rejected; a real pla
|
||||
(`durchschnitt_kmh(22.0, 1200)` → `66.0` km/h) correctly passes through unaffected. No companion-app source
|
||||
changes this round (backend-only). Manifest bumped to `2026.8.27.8`.
|
||||
|
||||
## X. Statistik-Tab-Icon zu groß, Batteriediagramm im Breitbildschirm "professioneller" gestaltet (2026.8.27.9)
|
||||
|
||||
**Owner report 1: "statistic icon seems to be too large in comparison to Car icon or Petrol-Station
|
||||
icon."** Measured live rather than guessed (`getBBox()` on all five rendered tab SVGs in
|
||||
`audi_ha_test`, all share one `viewBox="0 0 24 24")`: the hand-drawn tab icons (home/audi/trips/fuel)
|
||||
fill 32-72% of their box - they were drawn with deliberate internal padding, the usual convention for
|
||||
this icon style. `CI.pollsS` (the Statistik tab's CI icon since section R) is drawn edge-to-edge and
|
||||
fills 91.7% - a real, measured mismatch, not just a subjective impression. Fixed by wrapping the icon
|
||||
in a centered `scale(0.7)` (`translate(3.6,3.6) scale(0.7)`, about (12,12)) rather than a special-cased
|
||||
pixel size - this keeps it correctly proportioned at both of `.tab svg`'s breakpoints (26px mobile,
|
||||
22px desktop in `audi-dashboard-ios.css`) without maintaining two numbers. Re-measured after the fix:
|
||||
44.9% fill, now within the sibling range (32-72%), close to "trips" (46.7%). Same mismatch confirmed
|
||||
and fixed in companion-app's `symbole.tsx` `SymbolStatistik` (parity rule) - it shares the identical
|
||||
`CI.pollsS` path via the same `Rahmen` wrapper as `SymbolAudi`/`SymbolFahrten`/`SymbolTanken`.
|
||||
|
||||
**Owner report 2: "The Diagram for Battery Voltage shall use the max. available screen wide... find a
|
||||
solution to make it look professional."** The wide-screen width fix from section U (fixed
|
||||
`height:${BV_H}px`, `width:100%`, letting only the X-axis stretch) was functionally correct but bare at
|
||||
772px column width: still only 3 x-axis labels (start/middle/end, computed from fixed fractions
|
||||
regardless of real pixel width) and a plain unfilled line - looked sparse rather than "finished".
|
||||
Panel-only, per the same reasoning section R/S already established for this exact chart ("the diagram
|
||||
in question doesn't exist as a separate wide layout in companion-app" - confirmed with the owner at the
|
||||
time; `Verlaufsdiagramm` in companion-app's `Batterie.tsx` uses a fixed `height:120px` box with no
|
||||
wide-layout breakpoint, nothing to change there). Two additions to `bvZeichnen()`, both restrained and
|
||||
consistent with the project's iOS-HIG direction (Apple's own Health/Stocks charts use exactly this
|
||||
pattern) rather than a heavier redesign:
|
||||
- A low-opacity linear-gradient area fill under the line (`<linearGradient id="bvGrad">`, `var(--fg)`
|
||||
fading `0.16 → 0`), purely decorative, no new information, drawn between the gridlines and the line
|
||||
so the grid still shows through.
|
||||
- The x-axis tick count is now computed from the SVG's actual rendered pixel width
|
||||
(`svg.getBoundingClientRect().width`, ~110px minimum spacing per label, clamped 3-6) instead of a
|
||||
fixed `[0, 0.5, 1]` - a narrow phone chart still shows 3, the 772px desktop column shows up to 6.
|
||||
Also added `stroke-linecap="round" stroke-linejoin="round"` to the polyline for cleaner corners.
|
||||
- Verified live at 1400px: SVG measured 736×170px (fixed height preserved, no distortion regression),
|
||||
axis text confirmed still 11px (no repeat of the earlier text-scaling bug from section U's `.5`
|
||||
entry), 6 tick labels generated, gradient `<defs>`/area `<path>` both present in the rendered markup.
|
||||
The test container's actual battery history only spans ~2 days, so several of the 6 labels read the
|
||||
same day-precision date (`09.08.26`/`10.08.26` repeated) - a property of this container's narrow
|
||||
synthetic dataset, not a defect in the tick logic itself; a real multi-week history would show 6
|
||||
distinct dates.
|
||||
|
||||
Verified: `node --check` clean on the panel JS, companion-app `tsc --noEmit` clean. Manifest bumped to
|
||||
`2026.8.27.9`, `audi_ha_test` restart confirmed clean via log (single `audi_dashboard` loader warning),
|
||||
both fixes re-verified live in the browser after the restart (icon fill-percentage measurement above,
|
||||
chart dimensions/gradient/ticks above). `npm run ota` rerun (companion-app source changed:
|
||||
`symbole.tsx`), bundle rebuilt at `2026.8.27.9`, sha256
|
||||
`66fef05581b26086d76500d864af5704cd568a39474ece47df88fb7c9c51dc50`.
|
||||
|
||||
**Follow-up (2026.8.27.10): Statistik-Icon auf Nutzerwunsch 10% größer** - Faktor 0.7 → 0.77
|
||||
(`translate(2.76,2.76) scale(0.77)`), identisch in beiden Codebasen.
|
||||
|
||||
**Follow-up (2026.8.27.11): das Batteriediagramm war immer noch falsch - ein echter Darstellungsfehler
|
||||
plus ein Filter, der 7 von 9 Messtagen verschluckt hat.** Owner sent a screenshot ("thats still not
|
||||
fine") plus four instructions: no dates under the diagram, every measurement as a dot, date visible on
|
||||
click, and zoom must keep working when more dots appear; then a fifth: only the minimum gets a dot, the
|
||||
maximum appears as text on click.
|
||||
|
||||
Two genuine defects behind the screenshot, both found by measuring rather than by eye:
|
||||
1. **`preserveAspectRatio="none"` on a fixed 320-unit viewBox distorted everything horizontally.** At
|
||||
the 736px desktop column that is a 2.3× horizontal stretch applied to the whole coordinate system -
|
||||
the axis numbers rendered visibly wide (measured: "10,0" ≈ 50px wide at font-size 11), and the six
|
||||
date labels from `.9` collided with each other because their text stretched while their anchor
|
||||
spacing did not. This is the same class of bug as section U's `.5` entry (text scaling with the
|
||||
coordinate system), which was fixed there by pinning the height - the horizontal axis had the same
|
||||
problem and was missed. Fixed properly this time: `bvZeichnen()` measures the rendered width and
|
||||
sets `viewBox="0 0 <gemessene Breite> 170"`, so **one coordinate unit is exactly one pixel** and
|
||||
nothing can distort at any width; `preserveAspectRatio` is removed entirely. `BV_W` is now only a
|
||||
starting value (`bvBreite` holds the live width), `bvSkalaX()`/the gridline width use `bvBreite`,
|
||||
and `bvPlotRahmen()` collapsed to plain pixel arithmetic. A `ResizeObserver` on the SVG redraws on
|
||||
window resize, so the viewBox cannot go stale (setting the viewBox does not change the element's
|
||||
size, so no feedback loop).
|
||||
2. **The chart filtered out every day without a resting-voltage reading.** `bvPunkte` was built with
|
||||
`e.min != null && e.min <= AGM_RUHE_MAX_V` - so days where the car never stood still long enough
|
||||
(minimum still above 12,8 V, i.e. alternator voltage) vanished from the chart completely. In the
|
||||
test container that reduced 9 recorded days to **2**, which is exactly the near-empty two-dot chart
|
||||
in the owner's screenshot, and why the range read "09.08.26 – 10.08.26" instead of the real
|
||||
09.08–25.08. The filter is dropped for the chart (owner: "every Battery-Measurement as a dot"); the
|
||||
values that genuinely need resting voltage keep it via a **new, separate `bvRuhePunkte`** - the SOC
|
||||
readout (`letzter`) and `bvSohBewertung()` both switched to it, otherwise a generator reading would
|
||||
have shown a permanent "100 % · Sehr gut".
|
||||
|
||||
Per the owner's instructions: the x-axis date labels are gone entirely (the period still stands under
|
||||
the chart as `#bvRange`, and a single measurement's date/time comes from tapping its dot); one dot per
|
||||
recorded day, drawn at the **minimum** only; the tooltip now reads
|
||||
`18.08.2026 · 08:57 Uhr · Min 13,02 V · Max 13,47 V` (plus outside temperature when recorded) - that is
|
||||
where the maximum lives now, it has no dot of its own. `BV_MB` dropped 22 → 12 since nothing is written
|
||||
under the plot any more. Zoom/pan is untouched and confirmed still working.
|
||||
|
||||
**companion-app (parity rule):** its chart never had defect 2 (it already filtered only `min != null`,
|
||||
no AGM cut) and had no date labels either, so those two needed nothing. It *did* differ on the owner's
|
||||
other two points: no dots at all, and the daily maximum drawn as a permanent second grey line. Ported:
|
||||
one `<circle>` per measurement, the max line removed, tap-a-dot shows the same
|
||||
date/time/Min/Max/temperature line underneath, and the same dynamic-viewBox treatment (measured width +
|
||||
`ResizeObserver`, `preserveAspectRatio="none"` removed) - needed there too, because with `none` the new
|
||||
dots would have rendered as horizontally stretched ellipses. **Zoom/pan was deliberately NOT ported**:
|
||||
the panel's pinch/wheel/drag handling is ~150 lines of pointer bookkeeping (`bvZeiger`/`bvGestStart`/
|
||||
`bvDomainKlemmen`) with no counterpart in companion-app, and building it there is its own work package
|
||||
rather than part of this fix - flagged here per the parity rule's "say so explicitly" clause instead of
|
||||
being left silently undone.
|
||||
|
||||
Verified live in `audi_ha_test` at a 1400px viewport after the restart (`2026.8.27.11 eingerichtet`,
|
||||
clean log): `viewBox="0 0 736.0 170"` against a 736px-wide element (exactly 1:1, `preserveAspectRatio`
|
||||
absent), **9 dots** instead of 2, the only remaining `<text>` elements are the four y-axis labels
|
||||
(`10,0 / 11,7 / 13,3 / 15,0` - no dates), range label now spans the true `09.08.26 – 25.08.26`, and
|
||||
"10,0" measures **21,7 × 12 px** (undistorted at font-size 11; it was ~50px wide before). A synthetic
|
||||
pointerdown/up on the 6th dot produced the tooltip quoted above. Five wheel-zoom steps narrowed the
|
||||
range to `14.08.26 – 20.08.26` showing 4 dots, and "Zoom zurücksetzen" restored the full range -
|
||||
zoom confirmed intact. companion-app: `tsc --noEmit` clean, suite green at 146/146 (the
|
||||
render-every-page smoke test covers the reworked chart), `npm run ota` rebuilt at `2026.8.27.11`,
|
||||
sha256 `d0f77e854a2664331314ffc64a26712e0982c80e145aed7b25cabc41907e5974`.
|
||||
|
||||
**Follow-up (2026.8.27.12): the two codebases' SOC (Ladezustand) curves disagreed.** Owner asked "how is
|
||||
soc calculated" - answering it surfaced that the panel (`bvSocProzent()`, 11-point linear interpolation)
|
||||
and companion-app (`ladezustand()`, a 6-step lookup) genuinely disagreed on the same voltage - worst case
|
||||
15 percentage points apart (12.1 V: 40% panel vs 25% app), and the app also only ever looked at the
|
||||
*newest* stored day rather than walking back to the last resting reading like the panel does, so it could
|
||||
show "—" on a day the panel showed a real number. Owner: "ok use the interpolated for both". Ported the
|
||||
panel's exact 11-point table and linear-interpolation math into companion-app's `ladezustand()` -
|
||||
`Batterie.tsx`. **Deliberately NOT ported**: the "walk back to the last resting reading" selection logic
|
||||
- that's a separate, larger behavior change beyond "align the curve" and wasn't asked for; flagged here so
|
||||
it isn't mistaken for done. No dedicated tests referenced the old stepped values (grepped first), so
|
||||
nothing else needed updating. Verified: `tsc --noEmit` clean, suite green 146/146.
|
||||
|
||||
**Follow-up (2026.8.27.13): the battery temperature field, why it was always empty, and two real "match
|
||||
must be close in time" gaps found and fixed.** Owner: "i cant see any temperature at the battery" -
|
||||
investigated live rather than assumed. Root cause was mundane: `AUSSENTEMP_SENSOR` was correctly mapped
|
||||
and healthy (30°C, fresh), but the FMM003 voltage source was offline (dongle down), so every 5-minute
|
||||
`pruefen()` tick in `batterie.py` was rejecting the reading at the `SPANNUNG_MIN_V=10.0` plausibility
|
||||
floor **before ever reading temperature** - confirmed via the recurring log line
|
||||
`Batteriespannung 0.0 V unter der Plausibilitätsgrenze`. Separately, all 9 stored entries predate the
|
||||
temperature feature (2026-08-25/section R) entirely, so none carry `min_temp_c` regardless.
|
||||
|
||||
Owner pushed back on "nothing to backfill" with "i bet there is a temperature recorded the same time when
|
||||
the voltage was measured" - correct, and worth the correction: queried the recorder directly rather than
|
||||
assuming, and outside-temperature history exists for every one of the 9 stored days (recorder now keeps a
|
||||
year, section F). That exposed a **real, previously-unnoticed gap**: `historienimport.py`'s
|
||||
`_batterie_importieren()` never fetched `AUSSENTEMP_SENSOR` history at all (`verlaeufe` dict had no
|
||||
`"aussentemp"` key) - so even running the historical import over that same window would never have
|
||||
backfilled it. Fixed: `verlaeufe["aussentemp"]` added to `importieren()`'s fetch, and each day's minimum
|
||||
now looks up the nearest temperature reading via the recorder history, same pattern as the existing
|
||||
GPS/liter pairing helpers.
|
||||
|
||||
**Then the owner set a hard constraint: "temperature must be same time as voltage. 60 seconds delay is
|
||||
fine but not longer. is ther always a temperature when voltsge vomes?"** Measured rather than assumed
|
||||
(live recorder query over 48h on the container's then-mapped `cupra_eu_data_act` temperature sensor): NO
|
||||
- 22.4% of its own update gaps exceeded 60s, with a max gap of ~36.6 hours (duplicate-timestamp template
|
||||
sensor, not a real device). That answer justified building a real distance bound rather than trusting an
|
||||
unbounded nearest-match:
|
||||
- New `wert_in_naehe(zielzeit, verlauf, max_abstand_s=NEBENWERT_MAX_ABSTAND_S)` in `verlauf.py` - same
|
||||
nearest-match algorithm as the existing `naechster_wert()`, but returns `None` instead of an arbitrarily
|
||||
distant value when even the closest point exceeds the bound. `NEBENWERT_MAX_ABSTAND_S = 60`, the owner's
|
||||
own number, documented as owner-set rather than derived.
|
||||
- **Import path** (`historienimport.py`): switched from `naechster_wert()` to `wert_in_naehe()` for the
|
||||
temperature pairing.
|
||||
- **Live path** (`batterie.py`): this had the same latent gap and nobody had asked about it yet -
|
||||
`zustand_oder_none()` returns whatever a stale entity's last value was, no matter its age, so a live
|
||||
reading could just as easily have paired a many-hours-old temperature with a fresh voltage measurement.
|
||||
Fixed by comparing the two sensors' own `last_updated` timestamps (via `hass.states.get()` directly,
|
||||
bypassing `zustand_oder_none()`'s attribute-stripping for this one lookup) against each other - not
|
||||
against wall-clock "now", since both are read from the current `hass.states` snapshot but can carry
|
||||
different ages. Same `NEBENWERT_MAX_ABSTAND_S` bound, imported from `verlauf.py` (no circular-import risk:
|
||||
`verlauf.py` has no local imports of its own, unlike the `SPANNUNG_MIN_V` situation elsewhere in this
|
||||
file that needed a function-local import).
|
||||
- Verified the boundary itself with a deterministic Python check (`wert_in_naehe()` called directly with
|
||||
synthetic 3s/60s/61s/36h-offset timestamps) rather than relying on live timing: 3s and 60s pass through
|
||||
unchanged, 61s and 36h correctly return `None`.
|
||||
|
||||
**Then the owner remapped `AUSSENTEMP_SENSOR` from the flaky `cupra_eu_data_act` sensor to the real FMM003
|
||||
CAN sensor and asked to check again.** Confirmed live: the FMM003 temperature and voltage entities update
|
||||
in the same telemetry batch (~3s median gap between temperature updates, sub-second gap between the two
|
||||
sensors' own timestamps) - a fundamentally different reliability profile from the old sensor, so the 60s
|
||||
guard should pass consistently going forward. One caveat surfaced and reported honestly rather than
|
||||
glossed over: this FMM003 temperature entity's own history only reaches back to ~2026-08-25 (confirmed via
|
||||
a recorder query for 2026-08-09: zero points), so a re-import can never backfill temperature for the
|
||||
five oldest stored days (08-09 through 08-24) - only 08-25 onward is reachable with this sensor, no matter
|
||||
how the import logic is written.
|
||||
|
||||
Attempted a real live write to confirm end-to-end (temporarily POSTing a plausible voltage value on a
|
||||
repeating interval, same technique used earlier this session), but the owner flagged mid-wait that the
|
||||
FMM003 itself is currently offline - correctly stopped rather than waiting on a device that was never
|
||||
going to answer; the interval was cleared and the sensor reset to `0`, confirmed no stray entry was written
|
||||
to `batteriespannung.jsonl` in the meantime.
|
||||
|
||||
**Owner then asked to "import the available data"** - ran `audi_dashboard.historie_importieren` live
|
||||
(`2025-08-28` through now) via the real service call. Result (`sensor.audi_dashboard_import_status`):
|
||||
`batterie_tage: 9`, plus one genuinely new entry the live path had never captured on its own
|
||||
(`2026-08-27`, min 12.149 V / max 15.439 V - real recorder history from earlier the same day, before the
|
||||
dongle went offline). Its `min_temp_c` came back `null`; verified this is correct, not a bug - the nearest
|
||||
FMM003 temperature reading to that day's exact minimum timestamp was **180 seconds** away (25 points in a
|
||||
60-minute window around it, so the sensor was reporting, just not within the 60s bound at that specific
|
||||
moment). The 9 pre-25-08 entries stayed without temperature, exactly as predicted by the FMM003 history-gap
|
||||
finding above - not a defect, the data genuinely isn't there for that sensor over that window.
|
||||
|
||||
Verified throughout: all touched Python files `py_compile` clean via the container (`verlauf.py`,
|
||||
`historienimport.py`, `batterie.py`), companion-app `tsc --noEmit` clean and suite green 146/146,
|
||||
`audi_ha_test` restarted clean at each step ending on `2026.8.27.13` (single `audi_dashboard` loader
|
||||
warning, no traceback). `npm run ota` rebuilt at `2026.8.27.12`, sha256
|
||||
`5ef88ee826431b5b2cff5020c83430be88d729b51284459f36a5388963e441f3` (companion-app source changed for the
|
||||
SOC curve; `.13`'s backend-only changes needed no OTA rebuild).
|
||||
|
||||
**Follow-up (2026.8.27.14): `NEBENWERT_MAX_ABSTAND_S` raised from 60s to 300s, with real FMM003 telemetry
|
||||
as the reason - not a guess.** Owner suspected voltage and temperature were being compared across the
|
||||
wrong sensors; investigated rather than assumed - confirmed via `config/entity_registry/list` that both
|
||||
`external_power_voltage` and `can_ambient_air_temperature` belong to the same single FMM003 device
|
||||
(`device_id 3667296563855653c6895ed57b6b9030`, platform `flespi`) - no duplicate device, no sensor mixup.
|
||||
Also double-checked against a documented past mistake in this file (section B): confirmed `voltage` used
|
||||
`external_power_voltage` (the car's 12V bus), not `battery_voltage` (the FMM003's own internal backup
|
||||
cell) - both exist on this device and are easy to conflate.
|
||||
|
||||
Owner then asked why there'd be any delay at all if both come from the same device. Answer, grounded in
|
||||
a live-pulled table rather than general knowledge: a GPS/telematics tracker like the FMM003 reads dozens
|
||||
of independent CAN parameters (70+ entities on this one device) and transmits them at different rates to
|
||||
save cellular data - voltage changes constantly and gets reported often, ambient temperature barely moves
|
||||
and gets reported rarely. Measured over 46h: 851 voltage state-changes vs. 187 temperature state-changes
|
||||
on the same device. Pulled an actual table for the owner's named 12:00-13:00 local drive (`t-da363d681915`,
|
||||
resampled to one row per minute, collapsed into ranges): normal (non-blackout) temperature gaps of 8s,
|
||||
19s, 34s, 174s, and **593s** all occurred during otherwise-healthy reporting - not a connectivity problem,
|
||||
just the device's own per-parameter reporting cadence. Separately, a real 45-minute stretch
|
||||
(10:14-10:59 UTC) showed **both** sensors going completely silent at once - a genuine connectivity
|
||||
dropout, the same root cause already documented in section P, not a reporting-cadence issue.
|
||||
|
||||
Recommended widening the window from 60s to 300s (5 minutes) on three grounds: (1) the worst *normal*
|
||||
gap measured was 593s, so 60s was rejecting healthy pairings, not just genuinely stale ones; (2) outside
|
||||
air temperature is physically slow-changing, so several minutes of staleness introduces negligible real
|
||||
error, unlike GPS position or the voltage reading itself; (3) `batterie.py`'s `pruefen()` only runs every
|
||||
5 minutes anyway, so demanding sub-minute precision from the pairing doesn't buy anything the measurement
|
||||
itself doesn't already lack. Owner picked 300s over the alternative 600s suggestion. `NEBENWERT_MAX_ABSTAND_S`
|
||||
in `verlauf.py` changed `60 → 300`; `wert_in_naehe()`'s own algorithm is unchanged (still "nearest in
|
||||
time, `None` if even the closest point exceeds the bound") - only the bound moved, confirmed via the same
|
||||
kind of deterministic boundary test as the `.13` entry: 299s/300s pass, 301s and the real 593s/2700s cases
|
||||
correctly return `None`.
|
||||
|
||||
Verified: `py_compile` clean on `verlauf.py`, `audi_ha_test` restarted clean on `2026.8.27.14` (single
|
||||
`audi_dashboard` loader warning, no traceback). No companion-app source changed this round (the constant
|
||||
lives only in the backend), so no OTA rebuild needed.
|
||||
|
||||
**Follow-up (2026.8.27.15): a real merge-logic bug meant the `.14` widening could never actually backfill
|
||||
anything - re-running the import kept showing `min_temp_c: null` even for entries the new 300s window
|
||||
should have caught.** Owner: "i still dont see a single temperature at a measured voltage." Traced to
|
||||
`ablage.py`'s `batterieverlauf_tageswert_aktualisieren()`: it only ever wrote `min_temp_c` inside the
|
||||
`if spannung < eintrag["min"]:` branch - i.e. only when a measurement set a *new, lower* minimum. Re-running
|
||||
the import over an already-recorded day computes the exact same historical minimum it found before (same
|
||||
source data, deterministic), so `spannung < eintrag["min"]` is always `False` on a second pass - the branch
|
||||
that would apply the newly-reachable temperature never ran, no matter how wide `NEBENWERT_MAX_ABSTAND_S`
|
||||
got. This directly contradicts the `.13` entry's own docstring claim ("ein erneuter Import ... ergänzt sie
|
||||
dort nachträglich") - that claim was aspirational, not actually true, until this fix. Added an `elif`
|
||||
branch: `spannung == eintrag["min"] and eintrag.get("min_temp_c") is None and aussentemp is not None` →
|
||||
fill in `min_temp_c` without touching `min`/`min_ts` (they're already correct; only the temperature was
|
||||
ever missing). Live and import paths both benefit automatically - no separate change needed in either
|
||||
`batterie.py` or `historienimport.py`, both already call through this one shared function.
|
||||
|
||||
**Verified by actually re-running the import, not just by re-reading the code:** before the fix, all 9
|
||||
importable entries still showed the state from the `.13`-era import (only `2026-08-27` even attempted,
|
||||
and it alone stayed `null` at 180s > the then-60s bound). After deploying `.15` and re-running
|
||||
`audi_dashboard.historie_importieren` over the same window: **6 of the 9 entries now carry a real
|
||||
`min_temp_c`** (08-15: 26.0°C, 08-17: 26.0°C, 08-23/24/25/27: 20.0°C) - direct proof the fill-in-gap logic
|
||||
works, not just that it compiles. Two entries (08-16, 08-18) still show no temperature - checked why rather
|
||||
than assuming a bug: a first ±3h recorder query for both returned suspiciously identical `10800.0s`
|
||||
(exactly 3h) distances, which turned out to be an artifact of that query window's own edge, not the true
|
||||
nearest point. Widening to ±24h found the real answer: the nearest FMM003 temperature reading is **14.7h**
|
||||
away for 08-16 and **13.8h** away for 08-18 - genuinely no temperature data near those specific moments on
|
||||
the device's side, unrelated to the 300s bound or this fix. The two oldest entries (08-09, 08-10) remain
|
||||
without temperature for the already-documented reason in the `.13` entry (FMM003 history starts ~08-25 for
|
||||
this specific test device... **correction**: the temperature history actually reaches back to at least
|
||||
08-15, per this round's own findings - the `.13` entry's "history starts ~08-25" claim was based on a
|
||||
single spot-check at 08-09 and turned out to be an overgeneralization; the accurate statement is simply
|
||||
"no temperature data near this specific moment," checked per-day rather than assumed as a blanket cutoff
|
||||
date. Worth remembering: a live spot-check at one date does not establish a device's reporting start date -
|
||||
check the specific timestamp that actually matters.
|
||||
|
||||
Verified: `py_compile` clean on `ablage.py`, `audi_ha_test` restarted clean on `2026.8.27.15` (single
|
||||
`audi_dashboard` loader warning, no traceback), re-running the import produced the 6-of-9 result quoted
|
||||
above via direct file inspection, not just a trusted service-call return. No companion-app source changed
|
||||
(backend-only), no OTA rebuild needed.
|
||||
|
||||
---
|
||||
|
||||
## Working conventions (observed — keep them)
|
||||
|
||||
Reference in New Issue
Block a user