Weather
If your Home Assistant has a weather.* entity wired up (most installs do), push the hourly forecast once daily so the nightly optimizer uses your local data rather than the Open-Meteo fallback. The Energy Dashboard does this for you automatically; custom integrations should set up a daily rest_command.
The push is written to two places:
users.latest_weather_forecast— single JSONB cell that the nightly optimizer reads first.weather_forecasts— append-only history the weekly model refit reads to fill outdoor-temp gaps insensor_readings.
If no fresh push is available when the nightly job runs (older than 24 hours, or never pushed), the optimizer falls back to Open-Meteo for that user.
POST /api/v1/weather
Section titled “POST /api/v1/weather”Auth: Required (Bearer JWT)
Example
Section titled “Example”curl -X POST https://api.hungrymachines.io/api/v1/weather \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "forecast": { "hourly_temps_f": [54.2, 53.8, "...(24-72 values)"], "hourly_humidity": [62, 64, "..."], "hourly_wind_mph": [3.1, 2.8, "..."] } }'Request body
Section titled “Request body”{ "forecast": { "hourly_temps_f": [54.2, 53.8, 53.5, "..."], "hourly_humidity": [62, 64, 65, "..."], "hourly_wind_mph": [3.1, 2.8, 2.5, "..."] }}| Field | Type | Required | Validation |
|---|---|---|---|
forecast.hourly_temps_f | array[float] | Yes | 24–72 hourly values, each in [-50, 150] °F. Starts at hour 0 of the push date and walks forward. |
forecast.hourly_humidity | array[float] | null | No | Same length as hourly_temps_f. Each value in [0, 100] percent. Omit or send null to skip. |
forecast.hourly_wind_mph | array[float] | null | No | Same length as hourly_temps_f. Each value in [0, 200] mph. Omit or send null to skip. |
Response (201)
Section titled “Response (201)”{ "accepted_hours": 48, "pushed_at": "2025-11-18T03:30:00+00:00"}| Field | Type | Notes |
|---|---|---|
accepted_hours | integer | Number of hourly entries stored from hourly_temps_f |
pushed_at | string | UTC ISO 8601 timestamp when the row was saved |
Errors
Section titled “Errors”| Status | Detail | Cause |
|---|---|---|
| 400 | "forecast.hourly_temps_f must contain between 24 and 72 hourly values" | Array length out of bounds |
| 400 | "forecast.hourly_temps_f[<i>]=<v> is outside the allowed range [-50, 150]" | Value out of range or non-finite |
| 400 | "forecast.hourly_humidity length must match hourly_temps_f" | Array lengths disagree |
| 401 | "Not authenticated" | Missing or invalid token |
| 503 | "Database unavailable" | Supabase not reachable |
| 503 | "Failed to store weather forecast" | DB write failed |
When to push
Section titled “When to push”Push once per day, ideally between 02:30 and 03:30 UTC — before the nightly optimization window opens at 04:00 UTC. The optimizer’s freshness check accepts any push from the last 24 hours, so missing one day falls back to Open-Meteo (or to the most recent prior push if Open-Meteo is also unavailable).
A typical Home Assistant rest_command + automation:
rest_command: hm_push_weather: url: "https://api.hungrymachines.io/api/v1/weather" method: POST headers: Authorization: "Bearer !secret hm_access_token" Content-Type: "application/json" payload: > { "forecast": { "hourly_temps_f": {{ state_attr('weather.home', 'forecast') | map(attribute='temperature') | list | tojson }} } }
automation: - alias: "HM — push weather forecast at 03:30 UTC" trigger: - platform: time at: "03:30:00" action: - service: rest_command.hm_push_weatherAdjust the entity (weather.home) and forecast attribute path to match what your weather integration exposes. Open-Meteo’s HA integration returns forecast as a list of dicts with a temperature field; some integrations use templow/temperature per day instead — verify in Developer Tools → States first.