Skip to content

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:

  1. users.latest_weather_forecast — single JSONB cell that the nightly optimizer reads first.
  2. weather_forecasts — append-only history the weekly model refit reads to fill outdoor-temp gaps in sensor_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.

Auth: Required (Bearer JWT)

Terminal window
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, "..."]
}
}'
{
"forecast": {
"hourly_temps_f": [54.2, 53.8, 53.5, "..."],
"hourly_humidity": [62, 64, 65, "..."],
"hourly_wind_mph": [3.1, 2.8, 2.5, "..."]
}
}
FieldTypeRequiredValidation
forecast.hourly_temps_farray[float]Yes24–72 hourly values, each in [-50, 150] °F. Starts at hour 0 of the push date and walks forward.
forecast.hourly_humidityarray[float] | nullNoSame length as hourly_temps_f. Each value in [0, 100] percent. Omit or send null to skip.
forecast.hourly_wind_mpharray[float] | nullNoSame length as hourly_temps_f. Each value in [0, 200] mph. Omit or send null to skip.
{
"accepted_hours": 48,
"pushed_at": "2025-11-18T03:30:00+00:00"
}
FieldTypeNotes
accepted_hoursintegerNumber of hourly entries stored from hourly_temps_f
pushed_atstringUTC ISO 8601 timestamp when the row was saved
StatusDetailCause
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

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_weather

Adjust 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.