GET /api/dashboard/alert-history?days=N reads daily .jsonl files from
data/alerts/ and returns entries newest-first. Dashboard gets a lazy-loaded
collapsible panel with a table showing time, type (NWS/threshold badge),
event name, and details, with 7d/30d/90d range selector.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NWS alerts and all threshold firings are now appended to daily .jsonl
files in data/alerts/ (same pattern as data/station/). NWS alerts are
deduplicated by alert ID across subscribers to avoid duplicate log lines.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ecobee API is closed to new developer registrations and iOS sub-daily
automations are no longer available, making the HomeKit push approach
unworkable. Removes all related code:
- server.js: HomeKit push endpoints, token management, data files
- dashboard.html: thermostat section card, indoor stat tiles, indoor
charts, HomeKit settings panel, HVAC badge CSS, all related JS
- index.html: Indoor Temp stat card
- app.js: indoor sensor display logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add Ecobee thermostat integration to dashboard
- Server: PIN-based OAuth flow to authorize Ecobee access without
exposing redirect URIs; tokens stored server-side and auto-refreshed
- Server: /api/ecobee/config, /api/ecobee/auth/pin,
/api/ecobee/auth/complete, /api/ecobee/data, /api/ecobee/runtime
endpoints behind dashboard auth
- Dashboard: Ecobee section card showing indoor temp, humidity,
heat/cool setpoints, HVAC mode, equipment status badge, and
per-sensor temperature readings from remote sensors
- Dashboard: stacked bar chart of daily heating/cooling runtime hours
for the past 7 days
- Dashboard: Ecobee setup panel with API key entry and step-by-step
PIN authorization flow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMhuFaecxraQzUPN4h9nsB
* Replace ecobee API integration with HomeKit push endpoint
Ecobee removed public developer API access, so pivot to HomeKit:
- Add POST /api/homekit/push accepting thermostat data from iOS Shortcuts
- Add GET /api/homekit/data returning latest reading to dashboard
- Add GET /api/homekit/config and POST /api/homekit/config/regenerate for token management
- Auto-generate auth token on first run, persist to data/homekit-config.json
- Auto-convert Celsius→Fahrenheit if temp < 50 (HomeKit always returns Celsius)
- Update dashboard section card to show temp, setpoints, humidity, mode, HVAC state
- Replace ecobee settings panel with push URL, token copy, and Shortcut setup instructions
- Remove runtime chart (not available without API access)
* Support GET query params on homekit push endpoint for iOS Shortcuts compatibility
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add Ecobee thermostat integration to dashboard
- Server: PIN-based OAuth flow to authorize Ecobee access without
exposing redirect URIs; tokens stored server-side and auto-refreshed
- Server: /api/ecobee/config, /api/ecobee/auth/pin,
/api/ecobee/auth/complete, /api/ecobee/data, /api/ecobee/runtime
endpoints behind dashboard auth
- Dashboard: Ecobee section card showing indoor temp, humidity,
heat/cool setpoints, HVAC mode, equipment status badge, and
per-sensor temperature readings from remote sensors
- Dashboard: stacked bar chart of daily heating/cooling runtime hours
for the past 7 days
- Dashboard: Ecobee setup panel with API key entry and step-by-step
PIN authorization flow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMhuFaecxraQzUPN4h9nsB
* Replace ecobee API integration with HomeKit push endpoint
Ecobee removed public developer API access, so pivot to HomeKit:
- Add POST /api/homekit/push accepting thermostat data from iOS Shortcuts
- Add GET /api/homekit/data returning latest reading to dashboard
- Add GET /api/homekit/config and POST /api/homekit/config/regenerate for token management
- Auto-generate auth token on first run, persist to data/homekit-config.json
- Auto-convert Celsius→Fahrenheit if temp < 50 (HomeKit always returns Celsius)
- Update dashboard section card to show temp, setpoints, humidity, mode, HVAC state
- Replace ecobee settings panel with push URL, token copy, and Shortcut setup instructions
- Remove runtime chart (not available without API access)
---------
Co-authored-by: Claude <noreply@anthropic.com>
- NWS active alerts shown as color-coded cards at top of dashboard (5-min cache), auto-refresh every 5 min
- Station location (lat/lon) configurable in settings; falls back to push subscription coordinates
- Consecutive dry/wet streak tile in extended stats (60-day lookback, 0.01" rain threshold)
- Indoor sensor tiles (Temp In, Humidity In, Dew Point In) auto-show when station reports tempinf/humidityin
- Indoor temperature and humidity history charts when indoor data is present in selected range
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Alerts (server):
- Station temp high/low threshold alerts via push + ntfy
- Freeze warning at ≤34°F (station reading)
- Station wind gust threshold alert from real readings
- Station offline alert when no data for >20 min (auto-clears on reconnect)
Dashboard:
- Trend arrows (▲/▼/–) on temp, humidity, dew, wind, pressure, UV, solar tiles
comparing current vs 1h ago via new /api/station/trend endpoint
- Offline banner when station last reported >15 min ago
- Monthly summary table (avg temp, high temp, max gust, total rain, readings)
- Temperature calendar heatmap — GitHub-style year grid, blue→orange scale
- Alert threshold settings UI: temp high/low, wind gust, rain rate
saved to all push subscriptions via new /api/subscriptions/thresholds
- Station name setting — persisted in auth file, served on conditions page
- Change password form in settings (no recovery flow needed)
Server:
- GET/POST /api/dashboard/station-name
- POST /api/dashboard/change-password
- GET /api/station/monthly-summary
- GET /api/station/trend
- GET /api/subscriptions, POST /api/subscriptions/thresholds
- /api/conditions/public includes stationName field
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- getDailyRecoveryToken(): HMAC of SESSION_SECRET + current day — changes
every 24h, requires no extra storage
- Logs token to console on startup (visible in CasaOS container logs)
- GET/POST /dashboard/recover: validates token, sets new password
- dashboard-recover.html: enter token + new password, with instructions
- dashboard-login.html: 'Forgot password?' link + success message after recovery
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
- 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>
- 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>
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>
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
* 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>
- 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>