Skip to main content

RainMachine (Local API)

GEM driver for RainMachine smart irrigation controllers via the local HTTPS REST API. Covers the Touch HD 12/16, Mini-8, and Pro-8/16 running firmware 4.x. All control is on-LAN — no RainMachine cloud account is required.

Feature coverage:

  • Per-zone manual start (with duration) and stop
  • Zone status polling — reflects running / queued / pending / off onto the GEM zone state attribute, plus remaining_seconds when the controller reports it
  • Stop-all (halts every running zone and any running program at once)
  • Program start / stop by id
  • Raw GET / POST escape hatches for anything the controller exposes that isn't first-classed here (rain delay, weather adjustments, snapshots, etc.)

Prerequisites

  • Firmware. Local API v4 is required. Older Touch / Mini firmware in the 3.x range (or the original RainMachine cloud SDK) is not supported. Update from the RainMachine web UI: Settings → Firmware Updates.
  • LAN reachability. Reserve or note the controller's LAN IP. The Local API listens on all interfaces once network is joined; it accepts connections from any host on the same LAN.
  • Controller password. From the RainMachine web UI open Settings → Remote Access → Set Password. This is the same password the RainMachine mobile app uses in Local mode (not the cloud login). If you can't remember it, resetting from this screen does not affect programs or history.

Test reachability by opening https://<controller-ip>:8080/api/4/apiVer in a browser (accept the self-signed certificate warning). You should see a JSON payload with apiVer, hwVer, and swVer fields.

Setup steps

  1. Confirm the API is up. Load https://<controller-ip>:8080/api/4/apiVer in a browser and confirm you get a JSON response.
  2. Add the device in GEM. In Devices, create a new device with driver rain_machine. Fill in:
    • ip — controller LAN IP
    • password — the Local Access password from the controller's Settings → Remote Access screen (stored encrypted)
    • Leave port on the default 8080 unless you're on an older Touch HD firmware that exposed 8081.
  3. Enumerate zones. Open the device's Script Console tab and run:
    await gem.command({device: <device_id>, action: 'get_zones'})
    The response is an object with a zones array. Note the integer uid of each zone (1-based; equal to the terminal number on the controller face).
  4. Create GEM zones. For each RainMachine zone you want to control from GEM, create a zone under an irrigation subsystem. Set zone.address to the RainMachine zone uid (e.g., 1, 2, 3 …).
  5. Verify. From the Script Console, run a short manual start:
    await gem.command({device: <device_id>, zone: <zone_id>, action: 'on', level: 60})
    Confirm the zone starts on the controller face and that the GEM zone state attribute flips to on within a poll cycle (default 20s).

Attributes

Device — required

NameTypeDescription
ipstringLAN IP or hostname of the RainMachine controller.
passwordstring (secure)The password set from Settings → Remote Access on the RainMachine web UI. Same value the mobile app uses in Local mode.

Device — optional

NameTypeDefaultDescription
portint8080Local API port. Firmware 4.x defaults to 8080; some older Touch HD firmware exposed 8081.
default_durationint (seconds)600Duration used by the on command when no duration_seconds argument is supplied. RainMachine has no truly indefinite manual-on mode.
status_intervalint (ms)20000How often to refresh zone state from the controller. Minimum 5s.
request_timeoutint (ms)10000HTTP request timeout per call.

Zone — address

FieldDescription
addressRainMachine zone id — a 1-based integer matching the Zones page in the controller's web UI (1..16 depending on model). Discover via get_zones.

Commands

NameArgsDescription
onaddress, duration_secondsStart a manual run on the specified zone for duration_seconds (falls back to the device default_duration attribute, capped at 43200s / 12h).
offaddressStop the specified zone if running.
stop_allStop all running zones and any running programs on the controller.
run_programprogram_idStart a program by id. Enumerate via get_programs.
stop_programprogram_idStop a specific program.
get_zonesList every zone on the controller with id, name, active flag, and current state.
get_zoneaddressFull detail for one zone.
get_programsList every configured program.
get_statusReturn the controller's /provision payload (system info + running list).
refresh_tokenForce a fresh login. Rarely needed — the driver re-authenticates automatically on token expiry or 401.
raw_getpathAdvanced: GET any /api/4/<path> resource on the controller.
raw_postpath, bodyAdvanced: POST to any /api/4/<path> resource. body is a JSON string.

Auth model

The Local API is bearer-token based:

  1. POST /api/4/auth/login with {"pwd": "<password>", "remember": 1}.
  2. Response returns {access_token, expiration, statusCode}.
  3. Subsequent calls pass ?access_token=<token> as a query parameter.

The driver caches the token in memory and refreshes automatically when it expires (default 24h) or when the controller returns a 401. There is no long-lived refresh token — the same password is used on each renewal, so a password change on the controller invalidates the driver until the new password is saved on the device row.

Known limitations

  • No indefinite manual on. The on verb always carries a duration in seconds. If you don't pass duration_seconds, the driver falls back to default_duration (600s / 10 min by default). Durations larger than 12 hours are clamped by the controller.
  • HTTPS only. The Local API refuses plaintext HTTP even on-LAN. The driver disables certificate verification because the controller uses a self-signed cert.
  • No first-class rain-delay commands. Rain delay, weather adjustments, and program schedule edits are all reachable via raw_get / raw_post but not exposed as verbs here. See the RainMachine Public API v4 documentation for the endpoint list.
  • No cloud fallback. Everything is on-LAN. If the controller is unreachable (Wi-Fi drop, LAN outage), commands fail — there is no cloud proxy path.

Troubleshooting

SymptomCheck
Connect logs auth failed (statusCode=…)Verify the password by logging into the RainMachine mobile app in Local mode. Reset from Settings → Remote Access on the controller if lost.
Timeout on every requestConfirm the controller is reachable at https://<ip>:8080/api/4/apiVer from another host on the same LAN. LAN firewalls or VLAN isolation are the usual culprit.
zone.state stays off even during a runConfirm zone.address matches a real RainMachine zone uid from get_zones. Wrong ids poll fine but never see running.
on completes but the zone does not startThe zone may be marked inactive on the controller (Zones → toggle Active). A running program or a rain delay can also block a manual start.
Frequent reconnectsBump status_interval if you're on a busy LAN — RainMachine controllers rate-limit the auth path and log warnings when the token is renewed frequently.
stop_all returns success but a program keeps runningRainMachine occasionally lags on stop-all when a program has queued zones. Re-issue after ~5s.
  • rainbird.js — LNK-Wifi/IP-based Rain Bird controllers. Different vendor, similar category.
  • hydrawise.js — Hunter Hydrawise cloud controllers (GraphQL). Cloud-only.
  • orbit_bhyve.js — Orbit B-Hyve cloud smart timers.
  • opensprinkler.js — OpenSprinkler open-hardware controller (local HTTP).