Home Assistant integration
LocalSky ships a native Home Assistant integration, distributed through HACS from github.com/silenthooligan/localsky-hacs. It turns a running LocalSky instance into a first-class HA device: every weather reading, zone valve, soil probe, verdict, and threshold slider becomes an HA entity, and run/stop/pause become HA services you can call from automations.
LocalSky stays the brain. The integration is a thin client over LocalSky’s REST and SSE API; if HA goes down, watering continues unaffected.
Two pieces, in this order. LocalSky is a server you run yourself (one Docker container, see the Quick start); this integration is only the bridge that surfaces it inside Home Assistant. Installing the integration without a running LocalSky gives you nothing to pair with. Server first, integration second.
Pick one path into HA, never both. LocalSky can also publish entities through MQTT discovery (
sensor.localsky_*via your broker). Running MQTT discovery and the HACS integration at the same time creates two copies of every entity. New setups should use the HACS integration; if you previously used MQTT discovery, disable LocalSky’s MQTT publishing and clear the retainedhomeassistant/.../configdiscovery topics before adding the integration (see Troubleshooting below).
What you get
One HA device per LocalSky instance, populated from LocalSky’s live entity manifest (GET /api/v1/sensors/manifest). Updates arrive over Server-Sent Events by default, so zone state changes show up in HA in under a second; a 30 second poll is the fallback. Adding a zone or sensor in LocalSky surfaces in HA automatically, no reconfiguration needed.
Requirements
- Home Assistant 2024.11.0 or newer (enforced by HACS).
- LocalSky 0.2.0 or newer. The integration probes
GET /api/v1/infoduring setup and refuses to pair with older instances (you will see a “service too old” error in the config flow). - Network reachability from HA to LocalSky’s HTTP port (default 8090).
Install
1. Add the custom repository
The integration is not yet in the HACS default catalog, so this step is required first:
- In Home Assistant, open HACS.
- Open the three-dot menu (top right) and choose Custom repositories.
- Add
https://github.com/silenthooligan/localsky-hacswith category Integration. - Search for LocalSky in HACS and install it.
- Restart Home Assistant.
2. Pair with your LocalSky instance
LocalSky announces itself on the LAN via mDNS as _localsky._tcp.local., so in most cases HA discovers it on its own: a “LocalSky” card appears under Settings > Devices & Services > Discovered. Click Configure and confirm.
If discovery does not fire (separate VLANs, mDNS blocked), add it manually:
- Settings > Devices & Services > Add Integration, search for LocalSky.
- Enter the host (for example
192.168.1.100) and port (default8090).
Pair against LocalSky directly on port 8090, not through a reverse proxy. If you front LocalSky with Caddy/nginx plus an auth gate, the gate’s redirects will break the integration’s API calls and the SSE stream. The proxy is for your browser; HA should talk to the instance directly on the LAN.
Options
After pairing, the integration card exposes three options (Configure on the integration entry):
| Option | Default | Range |
|---|---|---|
| Use SSE push updates | on | on/off |
| Poll interval (fallback when SSE is off) | 30 s | 5 to 600 s |
| Default run duration for valve/switch open | 600 s | 60 to 7200 s |
Authentication
If your LocalSky instance has an owner account (see authentication.md), the /api/v1/info probe reports auth_required and the config flow adds a token step.
Create the API token in LocalSky first, before adding the integration:
- In LocalSky, open Settings > Account.
- Under API tokens, create a token with a recognizable name (for example
home-assistant). - Copy the token; LocalSky shows it once.
- Paste it into the config flow’s token step. The integration validates it against
GET /api/v1/auth/sessionbefore finishing.
If the token is later revoked, or you enable auth on a previously open instance, the integration receives a 401 and starts HA’s reauthentication flow: a repair issue appears asking for a fresh token. Create a new one in Settings > Account and paste it in.
Entity reference
Entity inventory comes from LocalSky’s manifest, so the exact set depends on your sources and zones. The tables below list what a typical install produces. Entity ids are generated by HA from the device and entity names; check Settings > Devices & Services > LocalSky for the exact ids on your install.
Weather
One weather.* entity built from the live station snapshot, with a 7 day daily forecast, plus individual sensors:
Units below are LocalSky’s native (imperial) reporting units; Home Assistant converts sensors with supported device classes (temperature, wind speed, precipitation, pressure, distance) to your configured unit system automatically.
| Sensor | Unit |
|---|---|
| Air temperature, feels like, dew point, wet bulb | °F |
| Humidity | % |
| Pressure | inHg |
| Wind speed, gust, lull | mph |
| Wind direction | ° |
| Solar irradiance | W/m² |
| UV index, illuminance | index, lx |
| Rain today, rain last minute, rain intensity | in, in/hr |
| Lightning strikes (last hour), average distance | count, mi |
| Station battery | % |
Irrigation
| Entity | Platform | Notes |
|---|---|---|
| Irrigation verdict | sensor | today’s run/skip verdict from the engine |
| Irrigation reason | sensor | the human-readable “why” behind the verdict |
| ET₀ today | sensor | mm |
| Days since rain | sensor | days since significant rain |
| Rain tomorrow probability | sensor | % |
| Heat multiplier | sensor | engine’s heat adjustment factor |
| Water level | sensor | controller water level % |
| Max wind, Min temp, Rain skip | number | skip-threshold sliders (0-50 mph, 20-60 °F, 0-1 in; about 0-80 km/h, -7 to 16 °C, 0-25 mm). These sliders do not convert to HA’s unit system; set them in imperial |
| HA reachable | binary_sensor | connectivity diagnostic |
| Irrigation suspended | binary_sensor | on while a pause is active |
| Any zone running | binary_sensor | on while any zone runs |
Per zone
| Entity | Platform | Notes |
|---|---|---|
valve.<zone> | valve | the canonical control: open = run (default duration from options), close = stop |
<zone> running | binary_sensor | device class running |
<zone> soil bucket | sensor | engine bucket state, mm |
<zone> soil moisture | sensor | live probe %, unavailable when no probe assigned |
<zone> soil temperature | sensor | °F, native Ecowitt probes |
<zone> soil EC | sensor | µS/cm, native Ecowitt probes |
<zone> soil battery | sensor | probe battery % |
<zone> planned run | sensor | seconds planned for the next run |
<zone> run today | sensor | minutes actually run today |
switch.<zone> run | switch | legacy shim, disabled by default; prefer the valve |
Service reference
Five services, registered under the localsky domain. All accept an optional entry_id to target one instance when several LocalSky deployments are paired; without it the call fans out to every entry.
| Service | Fields | Limits |
|---|---|---|
localsky.run_zone | zone (slug, required), seconds (required) | seconds clamped to 1-7200; LocalSky’s server enforces the same 2 hour cap |
localsky.stop_zone | zone (required) | |
localsky.stop_all | stops every running zone | |
localsky.pause | hours (default 24) | 1-720 hours; schedules and manual runs will not fire while paused |
localsky.resume | clears an active pause |
Example automations
Get notified when the engine decides to skip, with the reason:
automation:
- alias: "LocalSky: notify on skip"
triggers:
- trigger: state
entity_id: sensor.localsky_irrigation_verdict
to: "skip"
actions:
- action: notify.mobile_app_your_phone
data:
title: "Watering skipped today"
message: "{{ states('sensor.localsky_irrigation_reason') }}"
Give the dog-run zone a five minute rinse when a helper toggles:
- alias: "LocalSky: quick rinse"
triggers:
- trigger: state
entity_id: input_boolean.rinse_dog_run
to: "on"
actions:
- action: localsky.run_zone
data:
zone: dog_run
seconds: 300
Pause watering for three days when vacation mode turns on, resume on return:
- alias: "LocalSky: vacation pause"
triggers:
- trigger: state
entity_id: input_boolean.vacation_mode
to: "on"
actions:
- action: localsky.pause
data:
hours: 72
- alias: "LocalSky: vacation resume"
triggers:
- trigger: state
entity_id: input_boolean.vacation_mode
to: "off"
actions:
- action: localsky.resume
Outage behavior
- LocalSky restarts or the network blips: the SSE streams reconnect automatically with backoff (2 s growing to 30 s). In polling mode, failed polls mark the entities unavailable until the next successful fetch.
- HA restarts or goes down: nothing changes on the LocalSky side. Scheduling, skip rules, and controller dispatch all run inside LocalSky; HA is a window into the system, not part of the watering path. (The one exception is the
ha_service_callcontroller, which routes valve commands through HA; see migrating-from-ha.md for why and how to move off it.)
Troubleshooting
LocalSky is not discovered. mDNS does not cross VLANs or Docker bridge networks by default. LocalSky’s compose file runs with network_mode: host so the announcement reaches the LAN; if your HA and LocalSky sit on different subnets, skip discovery and add the integration manually with host and port.
Setup fails with “service too old”. The integration requires LocalSky 0.2.0 or newer. Upgrade the LocalSky container and retry.
Repeating 401 / reauth loop. The stored token is no longer valid. Open LocalSky Settings > Account, delete the old token, create a new one, and complete the reauth prompt in HA. If you are fronting LocalSky with a proxy auth gate, re-pair against port 8090 directly; the gate’s redirects can masquerade as auth failures.
Duplicate entities. You have both MQTT discovery and the HACS integration active. Choose one:
- Keep the HACS integration (recommended): disable MQTT publishing in LocalSky’s config, then clear the retained discovery topics on your broker, for example
mosquitto_sub -h <broker> -t 'homeassistant/#' --remove-retained --retained-only -W 5. The stalesensor.localsky_*MQTT entities disappear after an HA restart. - Keep MQTT discovery: remove the LocalSky integration entry under Settings > Devices & Services.
Catalog status
Today the integration installs as a HACS custom repository. Submission to the HACS default catalog is planned and gated on a soak period for the custom-repo install path, LocalSky’s /api/v1/* surface being declared stable, and the integration’s test suite. Until then, the custom repository step above is required exactly once per HA install.
See also
- standalone.md: everything LocalSky does without HA
- migrating-from-ha.md: moving the watering brain out of HA
- api.md: the REST and SSE surface the integration consumes
- authentication.md: owner accounts and API tokens