Commit Graph
14 Commits
Author SHA1 Message Date
Nate EmmertandClaude Sonnet 4.6 7665146b44 Add dashboard analytics, public conditions page, and station data features
- Dashboard: account-protected station data recorder with PBKDF2 auth and
  HMAC-signed sessions; Chart.js time-series charts with 1h–3y range selectors;
  wind rose canvas; auto-refresh every 2 min; 1-min polling cron
- Analytics endpoints: all-time records, rain totals (7d/30d/YTD), heating/cooling
  degree days, CSV export, year-over-year overlay, hourly anomaly detection
- Dashboard UI: pressure trend arrow, rain tile row, HDD/CDD tiles, anomaly tile,
  YoY toggle, collapsible records panel, CSV export, backfill progress bar
- Public conditions page at /conditions (no auth) with auto-refresh every 2 min
- Rain rate push alert via web-push and ntfy when threshold exceeded
- Station data stored as per-day JSONL files; backfill imports up to 1yr from Ambient

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 14:26:51 -04:00
Nate EmmertandClaude Sonnet 4.6 46e927370a Add Ambient historical data backfill to dashboard
- POST /api/station/backfill: pages backward through Ambient's historical API
  at 1 req/sec, deduplicates against existing JSONL records, writes to daily files
- GET /api/station/backfill/status: polls live progress (days done, readings inserted)
- Dashboard settings panel: day-range selector (7d/30d/90d/180d/1y), Import button,
  progress bar with live count; auto-reloads charts when complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 14:02:27 -04:00
Nate EmmertandClaude Sonnet 4.6 4aca8df808 Add API key settings panel to dashboard
- Station API Keys section at bottom of dashboard (auto-opens if unconfigured)
- Shows configured/missing status on load
- Fields for Ambient API Key and Application Key; saves via existing endpoint
- POST /api/ambient-config now requires dashboard auth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 13:39:27 -04:00
Nate EmmertandClaude Sonnet 4.6 fa4895a741 Add station dashboard with auth and historical data recording
- Protected /dashboard route with PBKDF2 password + HMAC-signed cookies
- First-run setup flow at /dashboard/setup
- Records Ambient station readings to daily JSONL files in app/data/station/
- Deduplicates on dateutc so 1-min polling never writes duplicate rows
- Dashboard charts: temp, humidity/dew, wind+gusts, wind rose, pressure,
  rain rate, rain accumulation, UV, solar radiation
- History range selector: 1h / 6h / 24h / 7d / 30d / 90d / 1y / 2y / 3y
- Auto-downsamples to 720 points for long ranges
- Cron interval changed from 10 min to 1 min (with dedup guard)
- app/data/ added to .gitignore (contains keys and session secret)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 13:32:18 -04:00
Nate EmmertandClaude Sonnet 4.6 fdc374b8bd Use Ambient station readings for wind/temp threshold alerts in cron
When station keys are configured and the last reading is < 15 min old,
the alert cron uses windgustmph and tempf from the station instead of
Open-Meteo model values. AQI still comes from Open-Meteo (no station
equivalent). Alert bodies now include "(station)" or "(forecast model)"
so the source is visible in the notification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-19 12:19:29 -04:00
Claude 0005698264 Use station data for current conditions; persist keys server-side
Station overlay:
- When Ambient Weather station data is present and fresh (<15 min),
  its readings replace the model's current conditions: temp, feels-like,
  humidity, dewpoint, wind speed/direction, gusts, pressure (inHg→hPa),
  UV index, rain today, wind peek summary, and data-panel readouts
- A small "📡 My Station" badge appears in the hero when active
- applyStationOverlay() is called at the end of renderWeather (instant
  if station data already loaded) and again whenever station data
  refreshes (so the display stays live every 60 s)
- Hourly/daily forecasts continue to use Open-Meteo

Server-side key persistence:
- POST /api/ambient-config saves keys to data/ambient-config.json
  (same persistent volume as VAPID and subscriptions)
- GET /api/ambient-config returns {configured: bool} without exposing keys
- /api/ambient checks query params → saved config → env vars in order
- Settings Save button posts keys to server after a successful test;
  confirms "saved for all devices" in the status line
- On page load, if no localStorage keys but server is configured,
  the station loads automatically on any device
2026-08-19 15:53:10 +00:00
nmemmertandClaude b9e2b463f5 Add Ambient Weather personal station integration
* Add Ambient Weather personal station integration

Fetches live data from the user's Ambient Weather station via their
REST API and displays it as a "My Station" card in the conditions tab.

- server.js: add /api/ambient endpoint with 60s cache using
  AMBIENT_API_KEY and AMBIENT_APP_KEY env vars
- docker-compose.yml: expose AMBIENT_API_KEY/AMBIENT_APP_KEY env vars
- index.html: add collapsible "My Station" drawer to conditions tab
  showing temp, humidity, wind, gusts, daily rain, pressure, UV,
  solar radiation, and indoor readings
- app.js: add fetchAmbientStation() and renderAmbientStation(),
  auto-refresh every 60s, peek text summary in drawer header
- style.css: station drawer styles
- .gitignore: add .env so API keys stay off git

Co-Authored-By: Claude <noreply@anthropic.com>

* Move Ambient Weather keys to Settings panel

Users can now enter their API Key and Application Key directly in the
Settings tab under "Ambient Weather Station". Keys are saved to
localStorage and sent per-request to the server proxy.

- index.html: add API Key + Application Key inputs with Save button
- app.js: persist keys in localStorage, populate inputs on load,
  wire Save button (validates by testing the connection), pass keys
  as query params in fetchAmbientStation and its auto-refresh loop
- server.js: accept apiKey/appKey from query params with env var
  fallback; cache keyed per-user so multiple callers don't collide

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-19 11:35:16 -04:00
Nate EmmertandClaude Sonnet 4.6 a25864d9ed Upgrade maps to MapLibre GL JS; compact header; move search to settings
- Replace Leaflet with MapLibre GL JS v4.7.1 across all map instances
- CARTO dark/light and Esri satellite raster basemaps (no API key)
- All overlays (hurricane, wildfire, SPC, wind arrows) ported to GeoJSON sources/layers
- AQI, alert, temp, sun/moon markers via maplibregl.Marker with custom HTML
- Radar animation pre-loads all frames on load for smoother playback
- Compact loc-header: tighter padding and font sizes, all info preserved
- Search bar moved from header to Settings tab under Location section
- Service worker bumped to weather-v7

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 11:04:32 -04:00
Nate Emmert 1863f6784b Fix XSS, validation, and CSS regressions; refactor proxy retry logic
- Sanitize geocode suggestion rendering to prevent XSS
- Add lat/lon validation and cache eviction to weather proxy endpoints
- Extract shared fetchWithRetry helper, dedupe retry/timeout logic
- Stop leaking upstream error details to clients
- Fix radar provider metadata and drop dead nowcast field
- Fix missing --surface-radius-sm var and duplicate/conflicting CSS rules
2026-06-15 08:51:18 -04:00
Nate Emmert 950e2708ab Enhance mobile UX: learn guide, alerts actions, and shareable weather cards 2026-03-17 14:21:32 -04:00
Nate Emmert 14995987ae Stabilize SW and cache headers to match backup behavior 2026-03-17 11:36:12 -04:00
Nate Emmert b242232e0c Fix geolocation and map rendering 2026-03-16 12:37:33 -04:00
Nate e4c631f9a8 Add lightning strikes and wind overlay toggles to Maps tab 2026-03-16 11:56:03 -04:00
Nate e397f11285 Initial commit 2026-03-16 09:40:48 -04:00