Skip to content

Force schedule poll after manual zone start so zone state reflects controller state within minutes #56

Description

@simons-plugins

Problem

When a user manually triggers a zone watering run from Indigo (which invokes sprinklerStart on the controller device), Indigo's built-in sprinkler device updates its activeZone state immediately — so the controller visually shows "running". However, the zone device is a custom device type; its isIrrigating state only updates when the plugin next polls Netro's /schedules.json. That's up to 30 min on the default schedulesInterval, or the minimum 10 min if tightened. During that window the controller shows running but the zone does not.

Observed on 2026-04-24 after triggering a manual run in Indigo client — noticed mismatched UI state between controller and zone. Not a regression — it's pre-existing behaviour exposed by dogfooding the Whisperer-pairing PR (#55) on live hardware.

Proposed fix

In startZoneWithDelay (plugin.py around line 1917), after a successful start_watering API response, force self._next_schedules_update = now (and/or self._next_device_info_update = now) so the next runConcurrentThread iteration picks up fresh state within MINIMUM_POLLING_INTERVAL_MINUTES (~3 min) instead of waiting for the full interval.

Same treatment probably warranted for:

  • stopWatering / "all zones off" actions.
  • setMoisture action (already writes state optimistically, but a schedule re-poll would confirm Netro applied it).
  • noWater / rain-delay actions.

Acceptance

  • After a manual zone start, zone isIrrigating reflects truth within ~3 min (one runConcurrentThread tick).
  • No extra token burn on steady-state polling — only after a user-initiated action.
  • Tests cover: successful start → _next_schedules_update reset; failed start → timer unchanged.

Out of scope

  • Adding optimistic UI state writes to the zone from the action handler (higher risk; current approach keeps Netro as source of truth).
  • Eliminating the schedule-poll lag entirely (that would mean maintaining local state based on action side-effects, which drifts).

Context

Surfaced during PR #55 dogfooding. See plugin.py runConcurrentThread (line 1112) for the polling loop and _next_schedules_update semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions