/* * Home Assistant entity IDs for this installation. * * Entity IDs are not secrets, so unlike the token in app_config.h they are * tracked. They are also not stable: renaming a device or reinstalling an * integration changes them, and a wrong ID fails silently as "unavailable" * rather than as an error. Re-check with tools/ha_discover.py after touching * anything in HA. */ #ifndef HA_CONFIG_H #define HA_CONFIG_H /* --- Weather station (Ambient Weather, exposed locally through HA) ------- */ #define HA_ENT_OUTDOOR_TEMP "sensor.moonlight_beach_temperature" #define HA_ENT_OUTDOOR_HUMIDITY "sensor.moonlight_beach_humidity" #define HA_ENT_INDOOR_TEMP "sensor.moonlight_beach_inside_temperature" #define HA_ENT_INDOOR_HUMIDITY "sensor.moonlight_beach_humidity_indoor" #define HA_ENT_DEW_POINT "sensor.moonlight_beach_dew_point" #define HA_ENT_PRESSURE "sensor.moonlight_beach_relative_pressure" #define HA_ENT_RAIN_TODAY "sensor.moonlight_beach_daily_rain" #define HA_ENT_RAIN_RATE "sensor.moonlight_beach_precipitation_intensity" /* * The anemometer has been offline since 2026-07-27: wind speed, gust and * direction all read "unavailable". The display shows blanks for these by * design -- no substituting forecast wind for station wind. * * Do not be tempted by sensor.moonlight_beach_max_gust. It is NOT unavailable; * it still reports its last value from 2026-07-28 and would render as a * plausible live number. Anything using it needs a staleness check first. */ #define HA_ENT_WIND_SPEED "sensor.moonlight_beach_wind_speed" #define HA_ENT_WIND_GUST "sensor.moonlight_beach_wind_gust" #define HA_ENT_WIND_DIR "sensor.moonlight_beach_wind_direction" /* --- Forecast and sun ---------------------------------------------------- */ /* met.no via HA. Supplies the textual condition and the daily forecast. */ #define HA_ENT_WEATHER "weather.forecast_home" #define HA_ENT_SUN "sun.sun" /* --- Lights -------------------------------------------------------------- */ /* * The X-macro is load-bearing, not decoration. * * The JSON template asks HA for these entities as an ordered array, and the * firmware reads the reply back by index. Two hand-maintained lists would * drift the first time one is reordered, and the failure mode is silent: the * Dining Room tile would just start controlling the Blue Lamp. Generating the * template's entity list and the C table from one source makes that * impossible. * * X(entity_id, label, dimmable, icon) * * `dimmable` is false for the patio, which is a TP-Link smart plug in the * switch domain -- on/off only, and it needs switch.turn_on rather than * light.turn_on. See ha_service_domain(). * * `icon` is an ICON_* macro from main/ui/ui_icons.h. It rides along in this * list (rather than a parallel array in the UI) so a reorder here can never * put the sofa icon on the patio. Only ui_manager.c expands it; the api-layer * consumers ignore the argument, so this header does not include ui_icons.h. * * light.main_room used to be here and was removed deliberately: it is a * GROUP of blue_lamp, brown_lamp and landing_chandelier -- three of the * other tiles. One tap restyled four tiles at once, which both confused the * optimistic-hold logic and triggered a redraw storm big enough to glitch * the panel (see README on PSRAM bandwidth). Groups spanning other tiles do * not belong in this list. light.tv_room is also a group (of 2), but of * lights that have no tile of their own, which is fine. */ /* Labels must fit one line of Montserrat 16 in a ~125px tile -- roughly 11 * characters. Longer ones are truncated with an ellipsis, which reads as a * mistake. "Dining Room" is one character too wide, hence "Dining". */ #define HA_LIGHT_LIST(X) \ X("light.tv_room", "TV Room", true, ICON_TV) \ X("light.dining_room", "Dining", true, ICON_DINING) \ X("light.blue_lamp", "Blue Lamp", true, ICON_FLOOR_LAMP) \ X("light.brown_lamp", "Brown Lamp", true, ICON_DESK_LAMP) \ X("light.landing_chandelier", "Chandelier", true, ICON_CHANDELIER) \ X("switch.tp_link_smart_plug_f048_outdoor_hanging_lights", "Patio", false, ICON_STRING_LIGHTS) #endif