Skip to content

Repository files navigation

Window Watcher

Window Watcher compares tado room temperatures with nearby outdoor weather for Untergiesing-Harlaching/Giesing so you can decide whether opening the windows will cool the flat. It records readings to a local JSONL history file, shows hoverable trend charts, and bases the recommendation on the outdoor temperature trend.

Run Locally

pnpm install
pnpm dev

The app runs on http://localhost:3000 using the standard TanStack Start Vite dev server with Vite reload/HMR.

Environment

Copy .env.example to .env if you want to override the defaults.

Important local files:

  • data/.tado-token.json: local tado OAuth token, ignored by git (.tado-token.json is the legacy fallback)
  • data/temperature-history.jsonl: persistent temperature history, ignored by git
  • SAMPLE_INTERVAL_MS: optional sampler override; defaults to one minute locally and ten minutes on Railway.
  • PREDICTION_HORIZON_MINUTES: comparison window for open versus closed room predictions; defaults to 90 minutes.
  • MIN_FORECAST_COOLING_WINDOW_MINUTES: how long forecast air must remain useful before the dashboard recommends opening later; defaults to 30 minutes.
  • DWD_OBSERVATION_MAX_AGE_MS, DWD_MINIMUM_STATIONS, and DWD_MAXIMUM_SPREAD_C: safety limits for the direct DWD fallback. Defaults require two observations no older than 90 minutes that agree within 3°C.

Authentication:

  • Locally, auth is inactive by default so the dashboard can run without Clerk keys.
  • On Railway, Clerk auth is inactive until explicitly enabled with the auth flags and Clerk keys.
  • Enable Google as a social connection in Clerk.
  • Set VITE_WINDOW_WATCHER_AUTH=true, WINDOW_WATCHER_AUTH=true, VITE_CLERK_PUBLISHABLE_KEY, and CLERK_SECRET_KEY.
  • Set AUTHORIZED_EMAIL to the single Google account that may access the dashboard.
  • The server function refuses to return temperature data unless the signed-in Clerk user has a verified Google OAuth account with that email.
  • When the tado authorization expires, the dashboard can start and complete a new tado device login. With Clerk enabled, the configured Google account authorizes the action. Without Clerk, production accepts the token only after tado proves that account belongs to the exact configured TADO_HOME_ID; the short-lived flow is bound to the initiating browser with a hardened cookie. Tokens stay server-side and are saved directly to the Railway volume.
  • Set WINDOW_WATCHER_AUTH=true only if you want the server to enforce Clerk auth locally too.

Commands

pnpm run check
pnpm run typecheck
pnpm run build
pnpm run start

Deploy

Railway is represented by nixpacks.toml. The service should run as an always-on web service so the dashboard remains available; production sampling defaults to every ten minutes on Railway.

Railway setup:

  1. Deploy from the public GitHub repo.
  2. To enable Google auth, add VITE_WINDOW_WATCHER_AUTH=true, WINDOW_WATCHER_AUTH=true, VITE_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, and AUTHORIZED_EMAIL as Railway variables. Leave the auth flags unset or false until Clerk keys are configured.
  3. In Clerk, enable Google sign-in and add the Railway production domain to the allowed production URLs/redirect configuration for the Clerk application.
  4. Add the location/tado variables from .env.example as needed. Set TADO_HOME_ID on Railway so a reconnect can never install credentials for a different household.
  5. Attach a Railway volume and set RAILWAY_VOLUME_MOUNT_PATH to the mount path. The app stores temperature-history.jsonl and .tado-token.json below that path. TADO_TOKEN_JSON may bootstrap an empty volume once, but remove it after the volume token is proven; later recovery belongs in the deployed reconnect panel.
  6. Start command is pnpm run start. Keep App Sleeping off, set BACKGROUND_SAMPLER=false, and use the separate ten-minute POST /api/sample cron service to record samples.
  7. Keep the sampler command identical to scripts/railway-sampler-command.txt. It treats typed rate-limit, invalid-authorization, and provider-unavailable responses as completed checks with no fresh value. Transport failures, bad trigger credentials, internal errors, edge errors, malformed success responses, and unexpected bodies still fail the cron.

Railway does not replace app-level auth here. Its "Login with Railway" feature is for letting applications authenticate Railway users and access Railway resources, while this dashboard needs Google sign-in for one private user. Clerk is the cleaner fit and is also one of Railway's documented frontend-auth options.

The app uses generated shadcn UI components for controls, including the chart range buttons. It normally reads Bright Sky's dedicated current DWD observation and Bright Sky/DWD forecast data. If Bright Sky has no current value, it queries DWD Open Data directly and only accepts a fresh consensus from at least two nearby stations; stale, missing, or conflicting readings remain unavailable. Predictions integrate the forecast across the configured horizon and only announce a future cooling window when it remains useful for the configured minimum duration.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages