Orbit B-hyve
Cloud REST integration for the Orbit B-hyve line of smart irrigation hardware — the Wi-Fi sprinkler controllers (Indoor / Outdoor, XR Pro, XD) and the Smart Hose Faucet Timer family. One B-hyve account becomes one GEM device row; each watering station (one per sprinkler-controller channel, or one per hose timer) becomes a zone.
What this integration covers
- Manual zone start with a per-call run-time (minutes), capped at 240 minutes (Orbit hardware limit).
- Stop — cancels the active watering run on the controller. (Orbit has no per-station stop; stopping any zone stops all.)
- Rain delay — applies a controller-wide rain delay in hours; pass 0 to clear.
- Status polling of watering state (which station is currently active), connectivity (online / offline), and battery level for hose timers.
What this integration does NOT cover (yet)
- Program / schedule management. Building, editing, or pausing scheduled programs from GEM is not wired — use the B-hyve mobile app.
- WebSocket push events. Orbit publishes a live event stream at
wss://api.orbitbhyve.com/v1/events. GEM polls the cloud on a timer instead, so a manual start from the B-hyve app shows up at the next poll (withinstatus_interval) rather than instantly. Live push is not wired up. - Per-station stop. Orbit's API has no
stop_stationevent — thestopcommand is controller-wide. This is a vendor-side limitation. - Soil-moisture sensors / smart-watering decisions. The driver only surfaces what the controller is doing, not the decisions B-hyve's cloud made.
- Spray-runtime calibration and historical usage reports.
Prerequisites
- A free B-hyve account at https://bhyve.orbitonline.com or via the B-hyve mobile app.
- Each controller or hose timer paired into the account using the B-hyve mobile app — this driver does not onboard hardware.
- Outbound HTTPS reachability from the GEM controller to
api.orbitbhyve.com.
Setup steps
- Pair every B-hyve controller and hose timer into the account using the B-hyve mobile app.
- In GEM, go to System → Devices → Add Device (Open Devices) and pick Orbit B-hyve as the driver.
- Enter the B-hyve account
emailandpassword(the password is stored encrypted). - Save. After a few seconds the device row should show as Connected — the driver signs in, reads the account's device list, then starts polling.
- Run the
get_devicescommand. Each entry shows the OrbitdeviceId, the device type, and its station count — you need thedeviceIdto build the zone addresses in the next step. - For each watering station you want to control, create a zone bound to this B-hyve device, under the Water subsystem (see the note below), with
address = "<deviceId>:<station>". For a single-station hose timer the baredeviceIdalso works (station defaults to 1). The driver does not create these zones for you — add one per station by hand. - (Optional) Set the zone's
default_run_minutesto override the device-level default for that specific station.
GEM seeds a Water subsystem out of the box — there is no separate "irrigation" subsystem. This driver hints irrigation, which does not match any seeded subsystem name, so the New Zone editor does not pre-select a subsystem for you: choose Water yourself from the Subsystem picker. The subsystem only controls how the zone is grouped and presented in the UI — it does not affect whether watering commands work.
Attribute reference
Device attributes
| Name | Type | Required | Description |
|---|---|---|---|
email | string | yes | B-hyve account email. |
password | string | yes | B-hyve account password. Stored encrypted. |
api_base | string | no | Override https://api.orbitbhyve.com/v1. Leave empty unless directed. |
default_run_minutes | int | no | Run-time used when a start command supplies no duration (default 10, max 240). |
status_interval | int | no | Poll cadence in ms (default 30000; min 10000, max 600000). A non-numeric, zero or negative value falls back to 30000. |
request_timeout | int | no | Per-request timeout (default 15000 ms). |
Zone attributes
| Name | Type | Description |
|---|---|---|
address | string | "<deviceId>:<station>" (required). |
default_run_minutes | int | Per-zone override of device.default_run_minutes. |
state | string | Maintained by the driver: on while this station is actively watering, off otherwise. |
connection_state | string | connected / offline — mirrors device.is_connected from the B-hyve cloud. |
battery | int | Hose timers only — battery percentage (0–100). Absent on mains-powered controllers. |
The driver writes state, connection_state, and battery live as it polls, and all three are cataloged in the Attribute registry — they autocomplete in the Attribute editor and can drive attribute triggers (for example, alert when a hose-timer battery drops below 20, or when a station's connection_state becomes offline). The two default_run_minutes defaults are entered as device/zone settings rather than read back from the controller.
Zone address format
"<deviceId>:<station>", e.g. abcd1234-ef56-7890-abcd-ef1234567890:3. deviceId is the Orbit UUID from get_devices; station is the 1-based channel number on the controller (1 for a hose timer; 1..8 on Indoor / Outdoor; 1..16 on XR Pro). For a single-station hose timer the bare deviceId is also accepted. The station must be a whole number; an address such as abcd:1.5 is rejected without contacting Orbit.
Commands
| Command | Args | Notes |
|---|---|---|
on / start_zone | address, optional duration | Start the addressed station. duration is in whole minutes, rounded down and capped at 240 by Orbit. An empty, zero, non-numeric or sub-minute value falls back to the zone's default_run_minutes, then the device's, then 10 — it never starts a zero-minute run. |
off / stop | address | Stop watering on the addressed station's controller. Controller-wide — stops all stations on that controller. |
rain_delay | address, hours | Apply a rain delay to the addressed controller. Pass 0 to clear. Per-controller, not per-zone. A blank hours is rejected rather than read as 0, so an empty argument never clears an active delay. |
get_devices | — | Enumerate every controller / timer on the account. |
get_status | optional address | Read live state for the addressed station's controller, or every controller if address omitted. |
refresh_token | — | Force a re-login (debug). |
Known limitations
- Cloud-only. Orbit hardware speaks only to
api.orbitbhyve.com; when Orbit has an outage every zone goes offline. - Polling during an outage. If the cloud cannot be reached, including when GEM starts while the internet is down, the driver keeps retrying on its own. The first retry comes after the normal
status_interval, and each further failure doubles the wait, up to 10 minutes (orstatus_interval, if that is longer). The first failure is logged once rather than on every attempt, and the device comes back online at the first successful poll without a reload. - 240-minute run-time cap per manual start — enforced by the controller firmware, not the driver. Requests beyond 240 are silently clamped by Orbit.
- No per-station stop. Stopping any zone stops the whole controller. This is an Orbit API limitation, not a driver simplification.
- Rain delay is controller-wide. Setting
rain_delayon any zone applies to the whole controller — there is no per-zone delay. - API is reverse-engineered. This is the same cloud API the official B-hyve mobile app uses (and the same one the long-running open-source
pybhyve/homebridge-bhyve/ OpenHAB integrations rely on), stable in practice, but Orbit does not formally publish it as a customer-facing API. If an Orbit firmware update changes a response shape, the integration may need an update — capture the device log and contact support.
Troubleshooting
login rejected (HTTP 401/403)— wrong email / password. Confirm in the B-hyve mobile app, then re-enter on the device row.HTTP 401after running fine for weeks — the session token expired (~30 days of inactivity). The driver auto-re-logs-in on the next request; if it persists, runrefresh_token.address must be "<deviceId>:<station>"(or bare deviceId for a single-station hose timer) — the zone address is malformed. Runget_devicesto find thedeviceId, then setaddress = "<deviceId>:<station>".- Zone never updates — confirm
get_statusreturns the controller. If the controller showsis_connected: false, the timer is offline (out of Wi-Fi range, battery dead, or unplugged). The B-hyve cloud cannot start watering on a disconnected device. - Stop appears to do nothing — check that something is actually watering. Stopping an idle controller returns success but has no observable effect.
- Rain delay clears unexpectedly — Orbit decrements the controller-side delay every hour; setting a fresh delay overwrites the existing one. The B-hyve app and this driver share the same delay value.
Related documentation
- Devices — adding and configuring the B-hyve device row.
- Zones — creating one zone per watering station and binding it to the device.
- Subsystems — the Water subsystem these zones belong to.
- Commands — running
get_devices,start_zone,stop, andrain_delayfrom the admin UI or a macro.