Skip to content

Rain Bird ESP-TM2: integration loads schedule for 22 zones on a 4-zone controller, NAK on overshoot marks entity Unavailable #169672

@giordanomb

Description

@giordanomb

The problem

After installing an LNK2 WiFi module on an ESP-TM2 (4-zone) controller and adding it to Home Assistant via the Rain Bird integration, the controller entity becomes Unavailable within seconds of every reload, while individual sprinkler zone entities remain functional.

Debug logging reveals the root cause: the integration attempts to load schedule data for 22 zones despite the controller only reporting 4 available stations. The schedule fetch succeeds for the first several pages (controller-level info, program info, program start times, and zone duration pages covering zones 0-11), but fails on the page covering zones 12-13, which the controller correctly NAKs because those zones do not exist. The integration treats this expected NAK as a fatal UpdateFailed, marking the controller entity Unavailable.

The zone switches themselves work correctly (commands succeed and water flows), but the parent controller entity is permanently Unavailable.

This appears related to closed issue #164776 / PR #165030, but the fix in those does not resolve this specific case — the zone-count overshoot causes a fresh UpdateFailed on every coordinator refresh.

What version of Home Assistant Core has the issue?

2026.4.2

What was the last working version of Home Assistant Core?

N/A — this is a new install of the integration; never worked.

What type of installation are you running?

Home Assistant OS

Integration causing the issue

rainbird

Link to integration documentation on our website

https://www.home-assistant.io/integrations/rainbird

Diagnostics information

Hardware: Rain Bird ESP-TM2 (4-zone) with LNK2 WiFi module, firmware 2.10.

LNK2 isolated to local network only (no cloud connectivity).
Static DHCP reservation; controller reachable at a fixed local IP.
Rain Bird mobile app fully closed during testing.
ModelAndVersionResponse: modelID: 266, protocolRevisionMajor: 2, protocolRevisionMinor: 10
AvailableStationsResponse data: 83000F000000 → setStations bitmask 0F = 4 zones (zones 0-3 active)

Example YAML snippet

Anything in the logs that might be useful for us?

Successful initial fetch (zone state, rain sensor, rain delay all return cleanly in ~0.7s):

DEBUG [pyrainbird.async_client] Response: {'type': 'AvailableStationsResponse', 'pageNumber': 0, 'setStations': 251658240}
DEBUG [homeassistant.components.rainbird.coordinator] Finished fetching <ip> data in 0.784 seconds (success: True)

Then the schedule loader kicks in and announces the wrong zone count:

DEBUG [pyrainbird.async_client] Loading schedule for 22 zones
DEBUG [pyrainbird.async_client] Sending schedule commands: ['00', '0010', '0011', '0012', '0060', '0061', '0062', '0080', '0081', '0082', '0083', '0084', '0085', '0086', '0087', '0088', '0089', '008a']

Schedule pages 00, 0010-0012, 0060-0062, 0080-0085 all return successfully. Page 0086 (zones 12-13) is NAK'd by the controller:

Request (RetrieveScheduleRequest): 200086
Response from line: 002004
Response: {'type': 'NotAcknowledgeResponse', 'commandEcho': 32, 'NAKCode': 4}
ERROR [pyrainbird.async_client] Request (RetrieveScheduleRequest) failed with wrong response! Requested ({'A0'}), got 00:
ERROR [homeassistant.components.rainbird.coordinator] Error fetching <ip> Schedule data: Error communicating with Device: Unexpected response from Rain Bird device

Stack trace:

File "/usr/src/homeassistant/homeassistant/components/rainbird/coordinator.py", line 168, in _async_update_data
File "/usr/local/lib/python3.14/site-packages/pyrainbird/async_client.py", line 511, in get_schedule
File "/usr/local/lib/python3.14/site-packages/pyrainbird/async_client.py", line 585, in _process_command
    raise RainbirdApiException("Unexpected response from Rain Bird device")
pyrainbird.exceptions.RainbirdApiException: Unexpected response from Rain Bird device

The same NAK then repeats every coordinator refresh interval (~15 minutes apart in my logs).

Additional information

Likely root cause: pyrainbird appears to derive the zone count for schedule iteration from something other than the AvailableStationsResponse bitmask, leading to schedule page requests for zones that don't exist on the controller. For an ESP-TM2 with 4 zones, the schedule fetch should stop at page 0085 (zones 10-11) at the latest, or ideally at page 0080 (zones 0-1) plus 0081 (zones 2-3). Continuing to page 0086 and beyond guarantees a NAK on any sub-12-zone ESP-TM2 (-4, -6, -8 variants).

Suggested fix direction: Either (a) cap schedule iteration at the highest active zone from AvailableStationsResponse, or (b) treat NAKCode 4 on a RetrieveScheduleRequest as "end of valid schedule data" rather than a fatal error.

Side observation: ManuallyRunStationRequest consistently takes 15-20 seconds to receive an AcknowledgeResponse from the LNK2 (e.g. request at 20:21:23.508, ack at 20:21:41.448). All other commands return in 0.2-0.5s. This appears to be LNK2 firmware behavior, not an HA issue, but worth flagging in case it's relevant to anyone investigating coordinator timing.

Metadata

Metadata

Assignees

Type

No type

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions