Control an Orbit B‑hyve smart sprinkler timer over Wi‑Fi from Python, using
the unofficial api.orbitbhyve.com REST + WebSocket backend (the same one the
B‑hyve app uses). Built for a rooftop tomato garden in Seattle.
python3 -m venv .venv
./.venv/bin/pip install requests websocket-clientCreate .env (gitignored, chmod 600) with your B‑hyve app login:
BHYVE_EMAIL=you@example.com
BHYVE_PASSWORD=...
from bhyve import BhyveClient
c = BhyveClient.from_env() # logs in using .env
for d in c.devices():
print(d["name"], d["id"])
# manual run / stop (real-time, over WebSocket)
c.run("<device_id>", station=1, minutes=2)
c.stop("<device_id>")
# programs (schedules)
c.get_programs("<device_id>")
spec = c.build_program("<device_id>", slot="b", name="Program B",
start_times=["05:00","06:00"], run_times=[{"station":1,"run_time":2}])
c.create_program(spec) # POST (new)
c.update_program("<program_id>", spec) # PUT (edit)
c.delete_program("<program_id>") # DELETE
# rain delay (hours; 0 clears) — see caveat below
c.set_rain_delay("<device_id>", 24)
# live event stream + logging (recovers the history the REST API doesn't keep)
for evt in c.watch("<device_id>"):
print(evt)
c.log_events("<device_id>", "events.ndjson")./.venv/bin/python bhyve.py devices
./.venv/bin/python bhyve.py programs <device_id>
./.venv/bin/python bhyve.py run <device_id> <station> <minutes>
./.venv/bin/python bhyve.py stop <device_id>
./.venv/bin/python bhyve.py rain-delay <device_id> <hours>
./.venv/bin/python bhyve.py delete-program <program_id>
./.venv/bin/python bhyve.py watch <device_id>
./.venv/bin/python bhyve.py log <device_id> <file>| Device | Type | ID |
|---|---|---|
| Smart Sprinkler Timer | sprinkler_timer |
<device_id> |
| Wi‑Fi Hub | bridge |
<hub_id> |
Device IDs are account‑specific — find yours with bhyve.py devices. Optionally
store your timer's ID in .env as BHYVE_DEVICE_ID (gitignored) so you don't
paste it on every command.
- 1 station, drip, one 2 GPH emitter per plant, ~5–6 tomato plants in a shallow rooftop trough.
- Programs: slot a = "Rooftop Garden", slot b = "Program B" (the tomato cycle‑and‑soak schedule this repo manages).
The API keeps no watering history, so to answer "did it water today?" you
have to capture the live event stream yourself. monitor.py connects, prints
each watering event with a local timestamp, and auto-reconnects on drops.
Run it once in the foreground:
./.venv/bin/python monitor.py…or run it forever as a macOS launchd agent (survives logout/reboot, logs to
~/Library/Logs/bhyve-monitor.log):
# edit USERNAME/paths first
cp com.example.bhyve-monitor.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.bhyve-monitor.plist
# stop/remove:
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.example.bhyve-monitor.plistThen "did it water today?" is just:
grep "$(TZ=America/Los_Angeles date +%H | head -c0)" ~/Library/Logs/bhyve-monitor.log # or grep the date/event
grep watering_in_progress ~/Library/Logs/bhyve-monitor.log | tail./.venv/bin/python test_bhyve.pySee KNOWLEDGE.md for the full API reference and the watering
agronomy / decision log.