Zum Inhalt springen

Dashboard 2 - Control Panel

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Files: dashboards/dashboard_2_control_panel.yaml, packages/grow_dashboard.yaml, packages/grow_climate.yaml, packages/grow_actuators.yaml, packages/grow_irrigation.yaml, packages/grow_light.yaml, packages/grow_air.yaml, packages/grow_energy.yaml, packages/grow_alarms.yaml

Overview view (landing tab)

The first tab you land on when opening Dashboard 2 - intended as a true single-pane-of-glass view of the whole environment, so you don’t have to open every other tab just to confirm nothing needs attention.

Since Phase 9 (2026-08-28, “Environment Status” redesign): an “Environment Status” section at the top gives one line per module, each reusing the exact live state each module’s own view already reads (same entities, same conditions - condensed to a single glance-friendly line rather than that view’s fuller wording):

  • The Alarms module’s own all-clear/active-alarms banner, shown first and most prominently, since Alarms already consolidates every other module’s fault flags into one place (Climate safety pause, Light/Air fault watchdogs, Irrigation failsafe, Dashboard 1 mapping issues).
  • Setup - the same mapping-validation summary as before.
  • Climate - control on/off, current mode, paused flag.
  • Irrigation - control on/off, failsafe tripped, daily limit reached, VWC Lock active.
  • Light - control on/off, Top/Under-Canopy fault flags.
  • Air - control on/off, CO2 safety ceiling exceeded, each fan’s fault flag.
  • Energy - whether Total/Light/Climate power tracking is set up.

Below that: the Grow Tracker card (batch/cycle name, current phase, day in phase, flower day, expected harvest date - the read-only “where’s the grow at” info), and small Temperature/Humidity/VPD tiles. The editable cycle fields (Grow Cycle ID, cycle-start dates, Harvest Completed) were moved off this view entirely as of the earlier redesign - see “Overview redesign: Environment Status + Cycle Configuration moved (2026-08-28)” below. Grow Tracker’s read-only fields are the same sensor.grow_tracker_* entities from packages/grow_tracker.yaml shown elsewhere too, plus (since the follow-up below) sensor. grow_tracker_cycle_name - a read-only mirror of the Grow Cycle ID, added purely so this view can show the batch name without a second editable copy of it.

Since Phase 9 (2026-08-28, “more Overview features” follow-up): below the Temperature/Humidity/VPD tiles, the Overview now also has a “Climate & Irrigation” section (a condensed combined historical chart

  • Temperature/Humidity/VPD/VWC/EC - with its own 1h/6h/24h/3d/7d range selector, independent from the Climate & VPD and Irrigation views’ own selectors) and a “Light” section (Top Light / Under-Canopy live power tiles, plus the same on/off timeline the Light view has). See “Overview follow-up: combined chart, Light power/timeline, batch name, Cycle ID reset+save” further down for the full design writeup.

Scope (Climate & VPD view)

Phase 2 adds the first view of Dashboard 2 - the live control panel. This view is display-only:

  • Live tiles for current Temperature, Humidity, and VPD.
  • Historical charts (Temperature / Humidity / VPD together) with a time-range selector: 1h, 6h, 24h, 3 days, 7 days, and a link out to the native History page for any custom range.

No active climate control yet. Turning the dehumidifier/humidifier on or off automatically based on these readings is Phase 3. This view only reads and displays - it does not write to any actuator.

Requirements

  • HACS installed, with the apexcharts-card custom card added via HACS (Frontend section). Without it, the historical chart cards will show as “Custom element doesn’t exist” - the gauge tiles at the top still work without it.
  • packages/grow_core.yaml deployed with the Phase 2 update (adds sensor.grow_temperature_current / sensor.grow_humidity_current).
  • At minimum, Temperature and Humidity mapped on Dashboard 1 (same requirement as Phase 1) - Phase 2 does not add any new required mapping.
  • Since Phase 9 (2026-08-28): the card-mod, mushroom, and expander-card HACS frontend cards, for the dynamic gauge coloring, the device/Master-Control tile redesign, and the collapsible explainer notes respectively - see “Growlink polish” further down for exactly what needs each one and what happens if any is missing. expander-card is also used on Dashboard 1 and Dashboard 3, not just this one.

How the time-range selector works

input_select.grow_chart_range (defined in packages/grow_dashboard.yaml) holds the currently selected range. The dashboard has five pre-built custom:apexcharts-card cards, each with a fixed graph_span (1h, 6h, 24h, 3d, 7d) wrapped in a type: conditional card that only shows when input_select.grow_chart_range matches that range. Switching the dropdown swaps which chart is visible - only one chart renders (and queries the Recorder) at a time.

This design was chosen over trying to template graph_span directly inside a single apexcharts-card instance, since Jinja-templated graph_span is not reliably supported across apexcharts-card versions. Five small static chart configs is more verbose but works everywhere.

“Custom” is intentionally not one of the dropdown options - there’s a markdown card below the charts linking to Home Assistant’s native History page (/history?entity_id=...), which already has a full date-range picker. Rebuilding that inside apexcharts-card would duplicate functionality HA already provides for free.

Climate Setpoints card (Phase 3)

Added below the live values, on the same “Climate & VPD” view: a “Master Control” mushroom-tile row (Auto Control, Follow Light, Paused - see “Master Control & fault redesign” under Growlink polish further down for why these three moved out of the entities card), followed by an entities card starting with a “Mode & status” section (the grow_climate_mode selector - RH/Temp Direct vs. VPD Driven -, grow_climate_is_daytime, and grow_climate_last_decision), then the day/night setpoint + tolerance fields for RH/Temperature/VPD. See docs/docs/module-climate.md for what each mode does and the safety behavior. A markdown note below the card explains which setpoints apply to which mode, shows a 🔄 banner while the daytime sync is active, and surfaces a warning banner when control is off or paused.

Devices view (Phase 3)

A second view, “Devices”, with one card per mapped actuator (dehumidifier, humidifier, AC, up to 4 top lights, up to 4 under-canopy lights, both irrigation pumps, exhaust fan, intake fan, circulation fan, drain pump, CO2 valve - 18 total as of Phase 7’s optional Intake Fan addition, see docs/docs/module-light.md and docs/docs/module-air.md). Tap a card to toggle the device by hand, regardless of what (if anything) is automatically controlling it - useful for manual overrides, and for verifying a device is wired/mapped correctly. Built on switch.grow_actuator_* template switches from packages/grow_actuators.yaml (stable proxies to whatever’s currently mapped - same pattern as the Phase 2 pass-through sensors) rather than referencing mapped entities directly, for the same reason those sensors exist: static dashboard YAML can’t reference “whatever is currently mapped.”

Since Phase 9’s Growlink polish (2026-08-28), these are custom:mushroom-template-card (HACS “mushroom”) instead of the original stock tile cards, specifically to give “not mapped” its own honest visual language instead of looking like a fault: 🟢 green icon = on, blue-grey = off, grey with a “Not mapped” secondary line = that function isn’t assigned on Dashboard 1 (or the mapped device is unreachable) - deliberately never red, since an unmapped optional slot isn’t a problem. The same conversion was applied to the Irrigation-pump tiles, the Light/Air “Devices” grids further down, and the Energy view’s Live Power tiles. Real faults are never shown on any of these cards - they’re reported separately on each module’s own Master Control card. Without the mushroom HACS card installed, these specific cards show “Custom element doesn’t exist” (unlike card-mod, which degrades gracefully - see “Growlink polish” further down).

Manual toggles here can be overridden by automatic climate control if it’s enabled and that device is one it manages (dehumidifier/humidifier/ AC) - the regulation automation may switch it back on its next cycle.

Irrigation & Substrate view (Phase 4)

A fourth view with everything for packages/grow_irrigation.yaml: a status banner (control off / failsafe tripped / daily limit reached / VWC Lock active - new 2026-08-27), a “Master Control” mushroom-tile row (Auto Control, Failsafe, VWC Lock - since Phase 9’s broader Growlink polish, see further down), a 2-column row with the safety-limits/status entities card + failsafe clear button on the left and the two per-pump schedule.* entities (tap either to open its own unlimited weekly block editor - no fixed slot count) + pump tile buttons on the right, a time-range-selectable historical chart overlaying substrate VWC, EC, and both pumps’ on/off activity so you can see how watering actually affects moisture, live substrate readings, and the manual-run section (duration, zone, estimated volume, “Run Now” button). The safety-limits/status entities card also has a VWC Lock section (enable toggle, threshold, currently-locked sensor) and a lifetime delivered-volume field, added 2026-08-27 - see “VWC Lock” and “Lifetime delivered-volume tracking” in docs/docs/module-irrigation.md. A Crop-Steering Preset card (added 2026-08-28, Phase 5/R12) sits between the P1/P2 explainer and the “Clear Failsafe” button: a “Vegetative”/“Generative” dropdown plus an “Apply Preset” button that bulk-sets VWC Lock Threshold, Failsafe VWC Threshold, P1/P2 shot sizes, and Max Events/Day to that preset’s starting values - nothing changes until Apply is tapped, and every field stays individually adjustable afterward, see “Crop-Steering Presets” in docs/docs/module-irrigation.md. Redesigned 2026-08-25 from an earlier fixed-6-slot layout - see docs/docs/module-irrigation.md for why, and for what each setting does.

Light view (Phase 6)

A fifth view with everything for packages/grow_light.yaml: a status banner (control on/off, fault flags, last decision), a “Master Control” mushroom-tile row (Auto Control, Under-Canopy, Top Fault, UC Fault) with a “Status Log” entities card below it for the automation-managed Last Decision field (since Phase 9’s broader Growlink polish, see further down), a “Top Light” and an “Under Canopy” entities card (each a start time + duration-in-hours pair, the same window shape as the irrigation P1 window), “Top Light Slots” / “Under Canopy Slots” mushroom- tile rows (4 on/off toggles each, for which of up to 4 physical lights per group are actually in use - also converted from entities cards in the same pass), a 4x2 tile grid for the eight light actuators for manual override, a “Light Output” section (added 2026-08-27, optional - live measured power, running %, and a live PPFD estimate, for both Top Light and Under Canopy - depends on the Energy module’s per-device power mapping from Dashboard 1; the per-group Max Wattage and PPFD calibration inputs that used to sit in this same section moved to Dashboard 1’s “Light Output Calibration” card on 2026-08-29, alongside the project’s other one-time setup fields), and a simple two-row “Light Timeline” beam chart (native history-graph card, no HACS dependency) showing when each light group was actually on. Went through several redesigns on 2026-08-25 (a per-grow-phase layout, a UI-created-schedule:-helper layout, a 5-range apexcharts-card overlay for the chart, then extending from 2 to 4 lights per group with per-slot enable toggles) before settling on this design per direct user feedback - see docs/docs/module-light.md for the full version history and what each setting does, including the Wattage %/PPFD estimator added 2026-08-27.

Air & CO2 view (Phase 7)

A sixth view with everything for packages/grow_air.yaml: a status banner (control on/off, CO2 safety banner, fault flags including Intake, last decision), a “Master Control” mushroom-tile row (Auto Control, CO2 Dosing, CO2 Ceiling, Exhaust/Circ./Intake/CO2 Fault - 7 tiles, since Phase 9’s broader Growlink polish, see further down) with a “Status Log” entities card below it for the automation-managed Last Decision field, an Exhaust card (mode selector

  • Off / Duty Cycle / Always On - plus duty-cycle length + on duration) with an explainer of its modes and triggers (duty cycle, Climate override, CO2 safety override - the last one applies in every mode), an Intake Fan card (optional - no config, just shows whether it’s mapped and following Exhaust’s decision), a Circulation card (same 3-way mode selector plus its own independent duty cycle), a CO2 card (live ppm reading, setpoint, tolerance, safety max) with a plain-language banner on whether a CO2 sensor is mapped yet and a sealed-room-mode banner when applicable, a 4-tile grid for manual override of the exhaust/intake/circulation/CO2-valve actuators, and a simple beam timeline (native history-graph, same style as the Light view) showing when each device was actually on. Built per direct user request (“lets start with the next phase air exchange and co2”) ahead of Phase 5, with CO2 dosing built fully optional/dormant since the user has no CO2 sensor or valve hardware yet; the mode selectors and Intake fan were added in a v2 follow-up (“i miss the simple option to run the circulation fans permanently… same for the exhaust fan” plus the intake fan and sealed-room-scenario requests) - see docs/docs/module-air.md for the full design, especially the CO2-to- exhaust safety interlock the Phase 0 plan itself calls out as a health-risk item, and the sealed-room walkthrough.

Energy view (Phase 8)

A seventh view with everything for packages/grow_energy.yaml: a status banner (whether Total is sourced from the Power Master meter or calculated from mapped devices, plus which groups are tracking, last decision), a “Cycle Baseline” entities card (a manual “reset this cycle baseline” button, last decision - the currency selector and price per kWh/liter fields that originally lived in this card, added 2026-08-27, moved to Dashboard 1’s “Energy: Master Config” section on 2026-08-29), an explainer of the power -> kWh -> cost pipeline and per-device sub-metering, a “Live Power Draw” tile row (Total / Light / Climate, in W - individual per-device readings are deliberately NOT shown here, only the group totals), a “Money Spent on This Grow” section and a “Money Spent - Lifetime” section (both Jinja-templated markdown showing kWh + cost per group with the selected currency’s symbol, since a template sensor’s unit_of_measurement can’t itself be templated by currency - see docs/docs/module-energy.md), a “Nutrient Solution Cost” section and a “Total Grow Cost (Electricity + Nutrients)” section (both added 2026-08-27, this-cycle and lifetime figures, depends on the Irrigation module’s lifetime volume accumulator), a banner showing how many of each group’s devices are currently mapped (n/8 Light, n/7 Climate), and a simple power-draw beam/line timeline (native history-graph, same no-HACS-dependency pattern as the Light/Air views) with a note that the 3 kWh sensors can optionally be added to Home Assistant’s own native Energy dashboard. Built per direct user request (“lets continue with the next phase, energy. Don’t forget to add an option to put the electricity price in either USD, Pound or Euro…”) - the sub-metering itself was redesigned the same day, before first deployment, from one sensor per group to one OPTIONAL sensor per individual device (Dashboard 1’s new “Energy Sub-Metering” cards), summed automatically into Light/Climate, per direct follow-up: “i need the option to put the sensors in for every device individually and then put them together into usage groups.” A nutrient-cost tracker and combined “Total Grow Cost” were added 2026-08-27 per further follow-up (“Make a cost tracker out of it… create an option to put a price per l for the nutrient solution”). See docs/docs/module-energy.md for the full design, including why “cost” is disclosed as a recomputed estimate rather than a true price-over-time integral.

Alarms view (Phase 8, second half)

An eighth view with everything for packages/grow_alarms.yaml (module M7): a status banner (all clear, or the list of currently active alarms - fault watchdogs from Climate/Light/Air/Irrigation, or a Dashboard 1 mapping issue), a “Notification Channels” mushroom-tile row (7 tiles: the master “Notifications” switch - defaults on, unlike other modules’ master switches, since this one never commands an actuator; one push toggle per registered mobile device; the E-Mail enable toggle - since Phase 9’s broader Growlink polish, see further down), a “Notification Settings” entities card (the E-Mail notify-service text field, a “Send Test Notification” button, and the automation-managed “Last Event” log), and an explainer covering the two possible-duplicate push devices found during setup and how to add your own SMTP integration for the E-Mail channel. This module doesn’t detect any new faults itself - it consolidates what every other module already raises into one Push+Persistent+E-Mail alert (R9), on top of (not instead of) each module’s own notification. See docs/docs/module-alarms.md for the full design and rollout checklist.

Cameras view (Phase 9, Module M13)

A ninth view for packages/grow_camera.yaml (Module M13, decision R19): live-monitoring tiles for up to 4 cameras in the tent - pure monitoring, no recording, no motion detection, no security-style overlays. A “View Settings” entities card holds the layout switcher (input_select.grow_camera_layout: 1/2/4 Cameras) and the focus picker (input_select.grow_camera_focus, used only by the 1-Camera layout), then one type: conditional Markdown card per layout option shows the matching tiles - the 1-Camera layout shows the focused slot large plus the other 3 as small thumbnails, 2-Cameras always shows Slots 1 and 2 side by side, 4-Cameras shows all 4 slots in a 2x2 grid regardless of which are actually enabled (an unconfigured/disabled slot renders its own grey placeholder tile rather than being hidden, so you always know the slot exists and why it’s not showing anything).

Why Markdown cards, not picture-glance/picture-entity. Which camera a tile shows is picked dynamically at runtime (via the input_text.grow_camera<N>_entity_id mapping on Dashboard 1) - but stock Lovelace cards take a literal entity: in their YAML config, they cannot template which entity to show. Markdown is the one stock card that templates its content: with Jinja, so each tile is Jinja that resolves the mapped camera, then embeds Home Assistant’s own signed camera-proxy snapshot URL (entity_picture) with a cache-busting query parameter tied to sensor.grow_camera_refresh_tick (a trigger-based sensor ticking every 5 seconds), so the browser actually re-fetches the image on a schedule.

Known MVP tradeoff, documented on purpose: a frequently refreshing snapshot (every ~5s), not a continuous WebRTC-grade video feed, and tapping a tile does not open Home Assistant’s native more-info/fullscreen dialog the way a real picture-glance card would. Continuous streaming and native tap interactions are listed as later expansion stages, not MVP.

Each tile’s status dot mirrors sensor.grow_camera<N>_status (green = Online, grey = Not Configured/Disabled, red = Offline). Camera connections (stream URL, credentials, connection testing) are never configured on this view or anywhere else in GrowAssistant - only a reference to an already-working camera.* entity, set up through Home Assistant’s own native integrations (Generic Camera / ONVIF / MotionEye / go2rtc), is mapped on Dashboard 1. See module-camera.md for the full design, the camera-setup how-to, and the rollout checklist.

Dynamic gauge coloring (2026-08-28, card-mod)

The native gauge card only supports monotonic 3-zone severity coloring (green -> yellow -> red in one direction) via its severity: option. VPD’s healthy range - and Temperature’s and Humidity’s, once Phase 3’s day/night setpoints exist - is in the middle of its scale (too low and too high are both bad), which a monotonic band can’t express. Fixed via the card-mod HACS frontend card: severity: was removed from all 3 gauges on this view and replaced with a card_mod: style: block that templates the gauge’s --gauge-color CSS custom property live, against whichever day/night setpoint + tolerance is currently active for that parameter (respects input_boolean.grow_climate_is_daytime automatically) - green within tolerance, yellow within 2x tolerance, red beyond that, grey if the source sensor is unavailable. This is a genuine improvement over the old static thresholds, not just a cosmetic reskin: the color now reflects the actual currently-configured regulation target instead of a fixed number that could drift out of sync with the setpoints. All 3 templates were dry-run tested against mocked states (in-range/warning/error/unavailable, both day and night) before shipping.

Requires the card-mod HACS frontend card in addition to apexcharts-card (already required above): HACS -> Frontend -> Explore & Add Repositories -> search “card-mod” -> Install -> add the resource if HACS doesn’t do it automatically -> reload the dashboard. Without it, these 3 gauge cards still render and still work, they just show as plain gauges with no dynamic coloring (the card_mod: key is silently ignored by Lovelace if the custom element isn’t registered - it does not break the card).

Device-tile redesign (2026-08-28, mushroom)

All 35 device/power tile cards across the Devices view, the Irrigation pump tiles, the Light “Light Devices” grid, the Air “Air Devices” grid, and the Energy view’s “Live Power Draw” grid were converted to custom:mushroom-template-card. The point isn’t cosmetic - it fixes a real ambiguity the original UX audit flagged (see CHANGELOG [0.17.0]) more completely than the text-only clarification could: an unmapped/optional slot now gets its own distinct color (grey, “Not mapped”) instead of sharing the same greyed-out “unavailable” look every native tile card uses regardless of why it’s unavailable, which visually crowded together “not installed yet” with “something’s wrong.” 🟢 green = on, blue-grey = off, grey = not mapped - never red, since none of these three states is a fault. The 3 sensor-based Energy tiles (Total/Light/Climate power) follow the same color language (amber = actively drawing power, blue-grey = zero, grey = not mapped) and show the live value + unit as their secondary line, same information as the old tile cards just styled consistently with the rest.

Requires the mushroom HACS frontend card: HACS -> Frontend -> Explore & Add Repositories -> search “mushroom” -> Install -> reload. Unlike card-mod above, these cards do not degrade gracefully without it - custom:mushroom-template-card is itself the card type, so a missing install shows “Custom element doesn’t exist” on all 35 of these tiles until it’s installed, not a fallback to plain tiles.

Deliberately not done in this pass: a broader mushroom conversion of every other card on Dashboard 2 (the dense config/setpoint/calibration entities cards, the Master Control toggle rows) - mushroom’s per-row chip style doesn’t add much for dense numeric config forms, and doing it everywhere risked a much larger, less-verified change than this bounded device-tile slice. Scoped explicitly with the user before starting. Superseded by the Master Control & fault redesign below - the user asked for the broader pass next.

Master Control & fault redesign (2026-08-28, mushroom)

A third mushroom slice, done immediately after the device-tile redesign above per direct user request (“eine breitere mushroom politur zuerst” - a broader mushroom polish first). Converts every remaining on/off toggle row that has a clean, unambiguous good/bad or on/off meaning, across the Climate, Irrigation, Light, Air, and Alarms views: 32 rows total, extracted out of their old entities: cards into new standalone “Master Control” mushroom-tile grids (plus the Light/Air “Slots” rows, which get their own tile grids rather than a “Master Control” label since they aren’t control-enable toggles).

Two distinct color/interaction patterns are used, depending on what the toggle actually means:

  • Enable switches (Auto Control, Follow Light, Under-Canopy, VWC Lock, CO2 Dosing, the notification channels, the light/under-canopy slot toggles): green = on, blue-grey = off, grey = unavailable; secondary line shows the capitalized state (“On” / “Off”); tappable to toggle, hold for more-info. On = good here, so green-on is correct.
  • Fault/problem booleans (Paused, Failsafe, the four Air/Light fault flags, CO2 Ceiling exceeded): red = on, green = off, grey = unavailable; secondary line shows a short status word (“Active” / “Clear” / “Tripped” / “Exceeded”). These are automation-managed status flags, not user controls, so they’re not toggleable - tapping only opens more-info. On = bad here, so the color polarity is deliberately inverted from the enable-switch pattern (e.g. “Failsafe Tripped”: on is red, not green - verified by dry-run testing every affected entity’s polarity individually before shipping, since a copy-paste mistake here would have silently flipped a safety-relevant color).

Each new grid got a ”### Master Control” markdown header so it doesn’t float without context, and the two module entities cards left holding only a single automation-managed text field afterward (Light, Air) were retitled from “Master Control” to “Status Log” so the label still matches their contents.

Deliberately still excluded, and expected to stay that way: read-only counters/sensors (Events Run Today), input_select dropdowns (Regulation Mode, Currency), informational-but-not-clean-good/bad states (Daytime Active, Currently Locked, P1 Window Active - these don’t map to a clear green/red meaning), dense numeric config (setpoints, thresholds, calibration, prices), text fields, buttons/scripts, and the Cycle Configuration card (Grow Cycle ID + cycle-start dates) - left as plain entities rows on purpose, per the earlier UX-audit fix’s intent to guard that card against accidental taps; it is not getting mushroom-ified.

All 67 mushroom-template-cards on this dashboard (35 from the device-tile slice + 32 from this slice) were re-verified together: parsed via yaml.safe_load, every icon_color/secondary/primary/icon template rendered against mocked on/off/unavailable/numeric states with a plain Jinja environment, and the red/green polarity of each fault-vs-enable entity spot-checked individually. Zero template errors.

Collapsible explainer notes (2026-08-28, expander-card)

A fourth Growlink-Politur slice, requested directly by the user (“können wir die infos auf allen dashboards als dropdown textfelder machen, sodass man diese nur sieht wenn man sie öffnet”) - collapse every static “how this works” / “what this means” explainer note on all three dashboards into a click-to-expand card, so a view shows only its live tiles/status/ controls by default. Scoped via AskUserQuestion up front on two questions: which HACS card to use (a custom:expander-card accordion vs. a plain native <details>/<summary> tag inside the existing markdown cards - user chose the HACS card), and which text actually qualifies as collapsible “info” (explainer notes only, vs. also collapsing live status/ warning banners - user chose explainer notes only, banners stay visible).

What moved and what didn’t. Every markdown card whose text reads the same regardless of current entity state - mode explanations (“How Regulation Mode works”), “not a fault” tile-color clarifications, safety- limit rationale (the Cycle Configuration warning), one-time setup instructions (Schedules), chart/history pointers, module overviews (how the Alarms module works) - is now wrapped in a custom:expander-card, expanded: false by default, with a short ℹ️-prefixed title as the always-visible clickable header. Anything whose content is actually live - is_state()/states() driven banners like the Setup Status card, the “Automatic irrigation is OFF” / failsafe-tripped / VWC-lock-active banner, every module’s on/off + fault-flag status line, the Energy cost figures, the Alarms all-clear/active-alarms banner - was left exactly as a plain, always-visible markdown card. 26 cards on Dashboard 2, plus 2 each on Dashboard 1 and Dashboard 3 (30 total) were converted.

Splitting hybrid cards. Several existing cards mixed static explanation and live conditionals in one Jinja block - e.g. the Climate view’s “Regulation Mode decides…” explainer, immediately followed by {% if daytime_follows_light %}/{% if control off %}/{% if paused %} banners in the same content: string. These couldn’t be wrapped whole without hiding a live warning behind a click, so each was split in two: the static sentence moved into its own expander, the live conditionals stayed as a separate, always-visible markdown card immediately below (or in the same position as before). This happened on the Climate & VPD view (Regulation Mode explainer vs. sync/off/paused banners), the Air & CO2 view’s Intake Fan card (mirrors-Exhaust explanation vs. mapped/unmapped status), and its CO2 card (dosing safety-interlock rules vs. sensor- mapped-status/sealed-room-mode banners).

Section headers stayed untouched. Short structural markdown cards that are just a ### Section Name heading with no body text (e.g. ”### Master Control”, ”### Exhaust Fan”, ”#### Top Light Slots”) are not “info” and were left as plain, always-visible markdown - collapsing a section’s own title behind a click would hide the section itself, not an explanation of it. Where a header previously had explainer prose folded into the same markdown block (”### On/Off Cycle per Light Group” plus a paragraph explaining it), the header line was kept as its own small always-visible markdown card and only the paragraph moved into the new expander below it.

Requires the expander-card HACS frontend card (custom:expander-card, MelleD/lovelace-expander-card - available directly from HACS’s default store, no custom-repository step needed: HACS -> Frontend -> Explore & Add Repositories -> search “expander card” -> Install -> reload). Like mushroom, this does not degrade gracefully if missing: custom:expander-card is the card type itself, so every collapsed note shows “Custom element doesn’t exist” instead of its ℹ️ title until installed - no entity, control, or live banner is affected, only these notes become temporarily unreachable.

All 30 new expander-card blocks were re-validated after every edit with yaml.safe_load, and every markdown card’s Jinja content (97 across all three dashboards - the pre-existing count plus these) was parsed with a plain Jinja Environment to confirm no template syntax broke during the splits. One mistake was caught and fixed during this pass: an early edit to the Energy view’s cost-explainer card used a truncated copy of the original paragraph (an artifact of a diagnostic script’s own 600-character print limit, not the file’s actual content) as the text to replace, which silently matched a partial-word substring and left the tail of the original sentence dangling at the wrong indentation - caught immediately by the next yaml.safe_load validation pass (a scanner error, not a silent corruption) and fixed by re-reading the card’s full, real content before re-editing.

Overview redesign: Environment Status + Cycle Configuration moved (2026-08-28)

A fifth Growlink-Politur slice, requested directly: the user wanted the Overview to actually work as a single-pane-of-glass view of the whole environment, and wanted the Cycle Configuration fields moved to the Configuration dashboard (Dashboard 1) instead of duplicated on the Overview. Scoped via AskUserQuestion on two points before touching any YAML: how to handle the Cycle Configuration move (user chose the smaller option - Dashboard 1’s existing “Grow Tracker” card already has every one of these fields, so the fix is removing the duplicate from the Overview, not restructuring Dashboard 1), and how much detail the new cross-dashboard status section should show (user chose compact text status lines per module, reusing each module’s already-live state, over either a minimal Alarms-only rollup or a full row of mushroom-style tiles).

Cycle Configuration duplication removed. The Overview’s “⚠️ Cycle Configuration (rarely changed)” expander and its editable entities card (Grow Cycle ID, all 4 cycle-start dates, Harvest Completed) were deleted outright - Dashboard 1’s “Grow Tracker” card already has every one of these fields (see dashboard-1-configuration.md), so this was a pure duplicate, not a second place doing something new. The Overview keeps only the read-only “Grow Tracker” card (Current Phase, Day in Phase, Flower Day, Expected Harvest Date) - genuinely “the infos regarding the cycle” rather than the ability to edit it. Editing the cycle now happens in exactly one place.

New “Environment Status” section. Replaces the old single Setup+ Climate status line with a small, always-visible group of cards: a ”### Environment Status” header, the Alarms module’s own all-clear/ active-alarms banner (shown first, since it already aggregates every other module’s faults), then one consolidated card with a line per module (Setup, Climate, Irrigation, Light, Air, Energy). Each line reads the same entities each module’s own view already reads for its own status banner - not a second, parallel source of truth - condensed to a short glance-friendly phrase instead of that view’s fuller instructional wording (e.g. Irrigation’s own view says “Automatic irrigation is OFF. Enable it below once your schedules and safety limits are configured.”; the Overview just says ”⚪ off”). Devices doesn’t get a line - it’s a manual-override control page, not a monitored module with its own on/off/fault state.

All new Jinja templates were dry-run tested across representative scenarios (everything off/clear, an active alarm, and every module on with every fault flag simultaneously tripped) with a plain Jinja Environment and mocked states()/is_state()/state_attr()/ has_value() - 0 template errors in any scenario, and the full-dashboard regression check (all markdown content: blocks across all three dashboard files parsed for Jinja syntax errors) stayed clean.

Icon-button sizing + readability fix, all mushroom-template-card tiles (2026-08-28)

Requested directly: “make the button icons on the irrigation page only 50px height and some of the icon buttons like the ones under air & Co2 master control are not readable, as most of the word cuts off.” Two separate fixes, both via card_mod: blocks added directly to individual custom:mushroom-template-card cards (no change to the cards’ own primary/secondary/icon config) - mushroom-template-card renders on top of Home Assistant’s native Tile-card internals (<ha-card><div class="content"><ha-tile-icon>…<ha-tile-info>), and ha-tile-info is itself a separate custom element with its own shadow root holding the .primary/.secondary label text - reaching it needs card_mod’s shadow-piercing key$: syntax, not a plain style: string.

Irrigation & Substrate view - compact 50px tiles. All 5 mushroom-template-card tiles on this view (the 3-card Master Control grid: Auto Control/Failsafe/VWC Lock, and the 2-card Irrigation Pump 1/2 grid) got:

card_mod:
style:
.: |
ha-card {
height: 50px !important;
min-height: 50px !important;
}
.content {
padding: 4px 8px !important;
gap: 6px !important;
}
ha-tile-icon$: |
ha-state-icon {
--mdc-icon-size: 20px;
}
ha-tile-info$: |
.primary {
font-size: 12px !important;
line-height: 1.1;
white-space: nowrap !important;
}
.secondary {
font-size: 10px !important;
line-height: 1.1;
}

Forcing ha-card to 50px overrides the card’s own default flex sizing (normally height: 100% driven by its content, with 10px padding and a ~40px icon) without shrinking anything inside it automatically, so the padding, icon size, and both text sizes were all reduced to fit legibly in the smaller footprint; text stays single-line (white-space: nowrap, same as the tile’s own default) rather than wrapping, since wrapping to two lines would need more height than 50px allows. Only this view’s tiles were touched - no other page’s tiles were shortened, since only this page was named.

Text-cutoff fix - all 4-column mushroom-template-card grids. The named example (Air & CO2’s 7-card Master Control grid: Auto Control/CO2 Dosing/CO2 Ceiling/Exhaust Fault/Circ. Fault/Intake Fault/CO2 Fault) sits in a columns: 4 grid, the narrowest tile width used anywhere on this dashboard - ha-tile-info’s own default CSS is white-space: nowrap; overflow: hidden; text-overflow: ellipsis, so any primary label too long for that width gets silently clipped rather than wrapped or shrunk. Since every other columns: 4 grid on the dashboard has the same narrow-tile risk and several have equally long or longer labels, the fix was applied to all of them, not just the reported one: Light’s 4-card Master Control grid (Auto Control/Under-Canopy/Top Fault/UC Fault), Air’s own 4-card device-tile grid (Exhaust/Intake/ Circulation/CO2 Valve), and the Alarms view’s 7-card notification-target grid (Notifications/iPad/iPhone 2 (older?)/iPhone 2 (active)/iPhone (Elena)/iPhone 15 Pro (Elena)/E-Mail) - the last of these has by far the longest labels on the whole dashboard (up to 21 characters) and was the worst-affected even though it wasn’t the one named. The 3-column and 2-column grids elsewhere (Climate & VPD, Devices, Irrigation) were left untouched - they weren’t reported and have noticeably more width per tile already. Each of these 22 cards got:

card_mod:
style:
ha-tile-info$: |
.primary {
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
}

This lets .primary wrap onto a second line instead of truncating with an ellipsis; it’s a pure improvement for short labels too (e.g. “iPad”, “CO2 Valve”) since they already fit on one line and simply keep doing so - nothing about their layout changes. These tiles are not height-constrained the way Irrigation’s are, so the grid row is free to grow taller to fit a two-line label instead of clipping it.

Both fixes together touch 27 mushroom-template-card cards (5 height + 22 text-wrap) via targeted line-position insertion (not a full YAML re-parse/re-dump, to avoid disturbing any existing comments or formatting), each insertion’s target line re-confirmed with an exact grep before writing. Validated the same way as every prior slice: yaml.safe_load after the edit, plus the full-file Jinja regression check (0 syntax errors, unaffected by this change since no content: blocks were touched) and mkdocs build --strict for the docs. Not yet visually confirmed on the live instance - re-verify the 50px Irrigation tiles are actually legible in practice (not just non-clipped) and that the wrapped two-line labels on Light/Air/Alarms look acceptable, once re-imported.

Follow-up correction: the actual “huge” Irrigation buttons were native button cards, not mushroom tiles (2026-08-28)

The previous slice’s 50px fix targeted every custom:mushroom-template-card tile on the Irrigation view (Master Control’s Auto Control/Failsafe/VWC Lock, and the Pump 1/2 grid) - but the user reported the “irrigation action buttons” were still huge and attached a screenshot. The screenshot showed a large octagon-with-exclamation icon over the text “Clear Failsafe” - not any of the tiles fixed in the previous slice at all. Checking the dashboard’s own YAML confirmed why: “Apply Preset”, “Clear Failsafe”, and “Run Now” (Manual Run) were never mushroom-template-cards - they were plain native Lovelace type: button cards, left over from before the mushroom redesign reached this view, and native button cards render with a large default icon and name underneath by design. The previous fix genuinely never touched them, since it only edited existing mushroom-template-card blocks.

Fix: converted all 3 to custom:mushroom-template-card, bound to each action’s own script.* entity (scripts have a real on/off state while running, so this is more than a cosmetic swap) and given the same 50px card_mod treatment as every other Irrigation tile:

  • Apply Preset (script.grow_irrigation_apply_crop_steering_preset)
    • icon blue-grey idle / orange while running, secondary text “Tap to apply” / “Running…”.
  • Clear Failsafe (script.grow_irrigation_reset_failsafe) - icon turns red with secondary “Tripped - tap to clear” whenever input_boolean.grow_irrigation_failsafe_tripped is actually on (the same boolean the rest of the dashboard already watches), orange while the clear script itself is running, blue-grey/“No failsafe active” otherwise - a real status cue added on top of the original buttons’s static look, not just a size fix.
  • Run Now (script.grow_irrigation_manual_run) - same idle/running pattern as Apply Preset.

All three kept their original tap_action: call-service exactly as before (calling the same script), and gained hold_action: more-info for consistency with every other tile on the page. Dry-run tested the 6 new template fields (icon_color/secondary x 3 cards) across 4 scenarios (idle, script running, failsafe tripped, failsafe tripped + running) - all rendered correctly. yaml.safe_load and the full-file Jinja regression check both stayed clean; no type: button cards remain anywhere in the dashboard file. Not yet visually confirmed on the live instance - this is a genuine root-cause fix (wrong card type, not a missed style), but still worth confirming these three buttons are actually compact now, and that the originally-fixed Master Control tiles (Auto Control/Failsafe/VWC Lock) are separately confirmed OK too, since the screenshot only showed the “Clear Failsafe” button.

Overview follow-up: combined chart, Light power/timeline, batch name, Cycle ID reset+save (2026-08-28)

Requested in the same message as the button-sizing screenshot: “i also want to add more features to the overview like the climate & irrigation diagramm with the option to switch between 1 hour, 6 hour, 12h, 24h, 3d, 7d. i also want to see the currently running light power and the light on off diagramm. the grow tracker also misses the name of the current running batch and the the batch counter has no reset or save feature on the configuration page.” Scoped via AskUserQuestion before writing any YAML - one combined chart chosen over two separate ones; the user explicitly chose to skip adding a 12h range option anywhere rather than add it to one selector only; Light power chosen as a per-group breakdown (Top Light and Under-Canopy shown separately) rather than one combined total; and “batch counter” was clarified by the user, on a follow-up question, to mean the existing Grow Cycle ID field, not a new counter entity - there is no separate counter anywhere in this project. A second follow-up question on what “Save” should concretely do (Home Assistant’s input_text already auto-commits on edit) came back “no preference,” so the recommended option was used.

New “Climate & Irrigation” section. A condensed combination of the existing Climate & VPD chart (Temperature/Humidity/VPD) and Irrigation chart (VWC/EC) into one apexcharts-card, with its own new range selector, input_select.grow_overview_chart_range (packages/grow_dashboard.yaml)

  • same 1h/6h/24h/3d/7d options as every other range selector in this project, deliberately not 12h, per the user’s own call to skip that option rather than add it to just one place. Kept fully independent from grow_chart_range (Climate & VPD) and grow_irrigation_chart_range (Irrigation) - changing the range here never changes what those tabs show, matching this project’s existing precedent of one selector per view rather than a shared one. Built the same way as every other range-switchable chart in this project: 5 fixed-graph_span apexcharts-card instances behind type: conditional cards (apexcharts’ own templated graph_span isn’t reliably supported across versions, so this project has never relied on it). Squeezing 5 series onto one chart without it turning into visual noise needed one design decision: Humidity and VWC share one 0-100% axis (both are already percentage scales, so this isn’t a stretch), VPD keeps its own 0-3 axis on the right (as on the Climate & VPD view), and Temperature (~10-35) and EC (~0-5 mS/cm) still plot as lines but without a visible axis of their own - the same “hidden axis” technique the Climate & VPD chart already uses for Temperature/Humidity. Pump-activity overlay (present on the dedicated Irrigation chart) was left out here on purpose - the Overview’s chart is meant as an at-a-glance summary, not a full replacement for the per-domain views, and a note in a collapsed “ℹ️ About this chart” expander says so directly, pointing back to the Climate & VPD and Irrigation & Substrate tabs for full detail.

New “Light” section. Two live power tiles (sensor.grow_light_top_power_w, sensor.grow_light_undercanopy_power_w

  • the same per-group power sensors from the wattage-%/PPFD estimator feature, packages/grow_light.yaml) side by side, per the user’s chosen per-group breakdown, plus a history-graph “Light On/Off Timeline” card identical to the one already on the Light view (binary_sensor. grow_light_top_active / binary_sensor.grow_light_undercanopy_active, hours_to_show: 24) - no new entities needed, both already existed.

Batch name on the Grow Tracker card. The Overview’s Grow Tracker card now leads with “Batch / Cycle Name”, but shows sensor. grow_tracker_cycle_name (a new trivial read-only mirror sensor, packages/grow_tracker.yaml) rather than the real input_text. grow_tracker_cycle_id entity directly - the earlier Overview redesign deliberately consolidated all cycle-field editing onto Dashboard 1 only, and showing the raw input_text here would have quietly reopened a second editable copy of it. The mirror sensor just returns “Not set” when the field is empty, otherwise echoes the value verbatim.

Cycle ID Reset/Save (Dashboard 1 only, not this file). See dashboard-1-configuration.md and module-grow-tracker.md for the full writeup - two new scripts (script.grow_tracker_save_cycle_id/script.grow_tracker_reset_cycle_id in packages/grow_tracker.yaml) back two plain native button cards placed directly under Dashboard 1’s Grow Tracker entities card. Deliberately not mushroom-template-card - Dashboard 1 has stayed free of the mushroom/card_mod HACS dependency throughout this project, and these are low-frequency configuration actions with no meaningful “running” state worth templating, unlike the Irrigation page’s frequently-tapped action buttons.

Process notes. No new HACS dependency for any of this - the combined chart reuses apexcharts-card, already required since Phase 2. Package changes this time (packages/grow_dashboard.yaml’s new input_select, packages/grow_tracker.yaml’s new template sensor and two scripts) mean this slice needs an actual package redeploy and Home Assistant restart (or the equivalent Developer Tools -> YAML reload for input_select, Template Entities, and Scripts), not just a dashboard re-import - the first Overview-related slice all session that wasn’t dashboard-YAML-only. Validated the two new script message templates and the mirror sensor across empty/set/unavailable scenarios with a plain Jinja Environment and mocked states() - all rendered correctly; yaml.safe_load clean on all 3 dashboard files and both touched packages; the full-dashboard regression check (all markdown and mushroom-template-card template fields across all 3 dashboard files) stayed at 0 syntax errors; mkdocs build --strict re-run clean. Not yet visually confirmed on the live instance - none of this has been seen rendered for real yet.