Skip to content

feat(charger): multiple chargers, image upload and control - #147

Merged
gnacho merged 14 commits into
mainfrom
feat/146-charger-tabs
Oct 11, 2026
Merged

gnacho merged 14 commits into
mainfrom
feat/146-charger-tabs

Conversation

@gnacho

@gnacho gnacho commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Closes #146. Closes #145.

Multiple chargers

  • carCharger.chargers[]: several chargers, each with its own entity
    ids, display name and stable key (first charger gets main;
    existing single-charger config migrates automatically).
  • Charger page: Inverters-style segmented tabs per charger (same
    height cards), each with live state, today curve and its own
    history.
  • Daily energy moves to a daily_charger table (migration v7 copies
    the old totals to main); accumulation, backfill and day curve are
    per charger with isolated kv counters.

Car photo (uploadable, not in the repo)

  • imageUrl per charger, editable from the card: small top-right
    button uploads a picture (client rescale to 460 px height preserving
    transparency) and stores it server-side in dataDir/charger-images;
    served session-gated from /api/charger/image/:key (admin writes).
  • Photo panel blends with light/dark themes (transparent in dark).

Control

  • Big on/off button (comfortable on mobile) via the charger switch.
  • Charging current presets bound to a configurable HA number/select
    entity; valid options are exposed in the live snapshot when the
    entity provides them.

Fixes

gnacho added 14 commits October 9, 2026 12:17
chargerDayCurve iterated the full 0-1440 minute range holding the last
known power state, so an in-progress day kept drawing its last value all
the way to 00:00. For today, cap the last bucket at the current minute;
past days keep the full 24h curve.
- carCharger.chargers[]: several chargers, each with its own entities,
  name and stable key (main for the first, migration from the old flat
  config keeps everything).
- Charger page: Inverters-style segmented tabs per charger, power
  button next to the state chip (switch on/off) and charging current
  presets bound to a configurable number/input_select/select entity.
- Daily energy moved to daily_charger (per charger, migration v7 copies
  the old totals to main); accumulation, backfill and day curve are
  per charger with isolated kv counters.
- POST /api/charger/action (admin only): switch on/off and amp change
  with strict entity and range validation (6-32 A).
- Settings: charger list with add/remove and a per-charger form.
- e2e: tabs, power button and amp presets (fake HAOS); tests 132/132.
- ChargerCfg.imageUrl: public path or URL; the hero shows the picture
  instead of the CarFront icon when set (Settings field + i18n).
- app/public/chargers/: pared.png (BYD Atto 3) and portatil.png (BMW
  i3), 512 px wide cutouts with transparency (112 KB + 169 KB).
- e2e: hero shows the car <img> when imageUrl is set.
- Photo fills the card height on a plain white panel (no accent tint).
- Right column: state chip, power button, amp presets and temperature.
- Power/session/lifetime stats move into the "Carga de hoy" card.
- Photo panel goes dark (neutral-900) in dark mode; white in light.
- Both car cutouts normalized to the same 1024x520 canvas at equal
  height so both tabs show the same visual scale.
- Both cutouts trimmed to the car at equal 460px height so they render
  at the maximum available size (no transparent letterbox canvas).
- Temperature value sits next to its label instead of far right.
- Hero card gets the charger name as title ("Cargador de pared" /
  "Cargador portatil" via config) with the state chip beside it.
- Power on/off becomes a large full-width button (h-14, brand filled
  when off, emerald when on), comfortable on mobile; amps and
  temperature fill the remaining height of the card.
- Content row gets a fixed 320px height on desktop: both charger cards
  end up exactly the same height (first card's height).
- Photo panel and power button grow (h-16, text-lg); amp chips go to
  h-9/text-sm and temperature/amps labels to text-sm/base.
- Car photos move out of the repo: server stores them per charger in
  dataDir/charger-images and serves them session-gated from
  /api/charger/image/:key (GET/PUT/DELETE, admin writes, 4 MB cap).
- Uploading updates the config imageUrl and re-resolves; no restart.
- Card gets small top-right buttons (change / remove image); the
  client rescales to 460 px height preserving transparency.
- Photo panel blends with the dark theme (transparent over the card
  instead of neutral-900).
- public/chargers removed; server tests 136/136.
- Single small button (top-right of the card) to change the car photo;
  the remove button goes away (it wiped the image by accident).
- Photo panel is transparent in dark mode so it blends with the card
  background instead of a mismatched grey.
- Image upload logic moves to ChargerImageButtons component.
- HAClient.callService was missing: the on/off and amp endpoints
  answered 502 ("ha.callService is not a function"). Added the method
  building the standard HAOS websocket message (type call_service,
  target entity, service_data).
- CSP had no img-src, so image data: URLs were blocked and uploads
  failed with a generic error before reaching the server. Added
  img-src 'self' data: tiles (same as the overlay).
… user helper

- Live exposes ampOptions (valid options of the amp entity, e.g.
  input_select) and the UI shows only those, falling back to presets.
- CT config: portatil ampId points to the user's input_select helper.
- Pending upload diagnostics shipped (detailed toast + server log).
@gnacho
gnacho merged commit 6074fcb into main Oct 11, 2026
4 checks passed
@gnacho
gnacho deleted the feat/146-charger-tabs branch October 11, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant