Skip to content

Add Growing Degree Days and per-bed ET/water-balance metrics - #5

Closed
spate141 wants to merge 5 commits into
mainfrom
claude/dashboard-derived-metrics-1t60mi
Closed

Add Growing Degree Days and per-bed ET/water-balance metrics#5
spate141 wants to merge 5 commits into
mainfrom
claude/dashboard-derived-metrics-1t60mi

Conversation

@spate141

@spate141 spate141 commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Adds a once-daily accumulation pipeline that computes, per bed:

  • GDD ((Tmax+Tmin)/2 - Tbase) from local sensor history, tracked
    cumulatively from a per-bed planted_on date, to derive growth stage
    and a harvest-date projection per vegetable.
  • Per-bed crop evapotranspiration (ETc = ET0 x Kc, reusing Open-Meteo's
    existing Penman-Monteith ET0) combined with rain and an irrigation
    estimate modeled from soil-moisture-rise, to give a per-bed water
    balance in place of the old whole-garden-only figure.

New pure functions live in garden/derived.py, persisted daily to a new
bed_daily_agronomy SQLite table, computed by a new cron job in
runner.py, surfaced via /api/insights, and rendered in the bed detail
panel on the dashboard.

claude added 5 commits July 8, 2026 22:02
Adds a once-daily accumulation pipeline that computes, per bed:
- GDD ((Tmax+Tmin)/2 - Tbase) from local sensor history, tracked
  cumulatively from a per-bed planted_on date, to derive growth stage
  and a harvest-date projection per vegetable.
- Per-bed crop evapotranspiration (ETc = ET0 x Kc, reusing Open-Meteo's
  existing Penman-Monteith ET0) combined with rain and an irrigation
  estimate modeled from soil-moisture-rise, to give a per-bed water
  balance in place of the old whole-garden-only figure.

New pure functions live in garden/derived.py, persisted daily to a new
bed_daily_agronomy SQLite table, computed by a new cron job in
runner.py, surfaced via /api/insights, and rendered in the bed detail
panel on the dashboard.
Corrects the placeholder GDD accumulation start date to the real
planting date across all four beds.
Renders a new row of 4 small-multiple charts showing each bed's
cumulative Growing Degree Days since planting, sourced from the new
/api/agronomy_series endpoint (backed by bed_daily_agronomy). Kept
independent of the existing 1h/3h/12h/24h/7d Trends range control
since GDD is a once-daily accumulator, not a live sensor series.
Trends now shows 8 chart cards instead of 12:
- The 4 per-bed GDD charts become one chart with a line per bed (same
  multi-line pattern already used for the Temperature chart), instead
  of 4 separate cards.
- The Pressure & dew point chart is dropped. Pressure's live value
  stays visible in the hero sky-strip chip (a separate code path);
  frost-risk alerting is unaffected since it runs server-side, not
  through this chart.
A code-review pass (4 parallel review angles) surfaced real bugs in the
GDD/water-balance work, several confirmed independently by multiple
review agents. Fixes:

- Cumulative GDD/water balance were chained off the previous row's
  stored total, so a forced same-day rerun (--agronomy, a documented
  flag) silently double-counted today's contribution on top of itself.
  Now recomputed from row history via SQL SUM each time, which is
  naturally idempotent under a rerun.

- planted_on was stored and displayed but never actually used to seed
  GDD accumulation -- it silently started from whichever day the cron
  first ran instead of the real planting date, understating the live
  dashboard's cumulative GDD by the entire deployment gap (confirmed:
  bed1 jumped from 95 to 1237.5 cumulative GDD after this fix, against
  the real config's May 15 planting date). Water balance is not
  backfilled (no historical weather data exists to backfill from),
  documented as a known gap.

- gdd_base_for_bed() picked the bed's growth-stage/harvest-date
  reference crop by "highest base temperature," unrelated to which
  crop actually takes longest to mature -- wrong for the real bed2
  (eggplant+okra) and bed4 (zucchini+eggplant), where the faster
  co-planted crop could make the bed read "ready to harvest" while a
  slower crop in the same bed was still mid-season. Now picks the
  crop with the longest maturity requirement instead.

- bed_agronomy_series()'s trailing-window cutoff used UTC "now" while
  the rows it filters are keyed by local-timezone dates -- an off-by-
  one-day risk near local-midnight-crossing-UTC-day boundaries.

- The nightly irrigation estimate only looked at the last 2 hours of
  soil-moisture data, missing any watering earlier in the day; widened
  to 24h.

- Two efficiency fixes (a bed-invariant DB query no longer repeated
  per bed; the dashboard's GDD chart no longer refetched every 60s for
  data that changes once a day) and one cleanup (collapsed duplicated
  once-per-day dedup logic into a shared helper).

Added storage/runner-level regression tests for the rerun-idempotency
and backfill fixes, verified end-to-end against the real config.yaml.
@spate141 spate141 closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants