Skip to main content

ControlByWeb Relay / I/O

The control_by_web driver controls a ControlByWeb WebRelay / I/O board (WebRelay-Quad, X-410, and similar) over the LAN. Each relay output becomes a controllable GEM zone you can turn on, turn off, or pulse as a dry-contact trigger; each digital input becomes a read-only zone that reports its contact state. It is the general-purpose relay board for jobs where you need GEM to throw a hard contact — triggering a gate or garage operator, driving a lighting contactor, latching a lock strike, or switching a power circuit.

The controller talks to the board over HTTP, polling its /state.json page for live relay and input state and switching relays with short query-string writes. Optional HTTP Basic authentication is supported if you have locked the board's web page.

How relays and inputs map to zones

One ControlByWeb board is one GEM device. Every relay and input on that board is a separate zone bound to the device:

  • Relay zones (relay_1, relay_2, …) are outputs. They accept on / off / pulse (and the open / close aliases).
  • Input zones (input_1, input_2, …) are read-only. They report the state of a wired dry contact but reject control commands.

On first connect the driver reads /state.json, discovers every relay and input the board reports, and auto-creates a zone for each one it does not already have. Auto-created zones land in the Gates subsystem with a default gate control — a sensible default for the most common use (gate/garage triggering), but almost always something you re-home once you know what each relay actually drives. See Re-home your zones below.

Prerequisites

  • The ControlByWeb board on the network with a known IP. Use a DHCP reservation — the driver addresses the board by IP.
  • Outbound HTTP from the GEM controller to the board (default TCP 80).
  • If the board's web page is password-protected, the HTTP username and password.
  • A Gates subsystem on the site for the initial auto-created zones. A default GEM install ships one; the driver matches any subsystem whose name contains gate. If every gate-type subsystem was deleted, create one under Subsystems first or no zones will be created.

Setup

  1. Add the device. Go to System → Devices → Add Device on the Devices page and choose the driver ControlByWeb. Enter the ControlByWeb IP Address. If the board's web page requires a login, fill in HTTP Username and HTTP Password; otherwise leave them blank. Change HTTP Port only if the board isn't on 80. Enable and save.
  2. Zones auto-create. On connect the driver reads the board and creates one zone per relay and input under the Gates subsystem. Open the Zones page to see them — they are named <device> relay_1, <device> input_1, and so on.
  3. Re-home and rename. Move each relay zone into the subsystem that matches what it drives (Lights, Power, Doors, Garages, …) and give it a friendly label. The relay-to-state mapping follows the new subsystem automatically — see Relay state and subsystems.
  4. Tune per-relay behavior. On a relay zone set Pulse Delay (ms) for how long a pulse holds the contact, and toggle Normally Closed if the relay is wired to a normally-closed contact (this inverts both the reported state and the pulse direction).
Re-discovering relays later

If you wire up more relays or inputs after the device was first added, press Reload on the device (in the device editor) to re-run discovery, or run the sync_zones command against the device. Discovery only adds missing zones — it never deletes or renames zones you have already customized.

Attributes

Device

AttributeUI labelRequiredTypeDefaultNotes
ipControlByWeb IP AddressyesstringBoard LAN IP (DHCP reservation recommended).
portHTTP Portnoint80HTTP port of the board's web page.
usernameHTTP UsernamenostringOnly if HTTP Basic auth is enabled on the board.
passwordHTTP Passwordnostring (secure)Stored encrypted. Only if Basic auth is enabled.
status_intervalStatus Poll Interval (ms)noint2000How often the driver reads /state.json. Minimum 500.

The driver also writes a read-only relay_N / input_N attribute on the device for each discovered point, holding that point's raw contact state (open / closed) as last polled.

Zone

Relay and input zones carry an Address in the form relay_N or input_N (e.g. relay_1, input_2). Auto-created zones get theirs automatically; if you add a zone by hand, enter the address in that form — the field hint on the Zones page shows the same.

AttributeUI labelApplies toTypeDefaultNotes
delayPulse Delay (ms)relayint1000How long pulse holds the contact before releasing. Minimum 100.
normally_closedNormally Closedrelay / inputboolfalseInvert reported state and pulse direction for NC-wired contacts.

Commands

NameArgsDescription
onaddressEnergize the relay (contacts close).
offaddressDe-energize the relay (contacts open).
openaddressAlias of off — de-energize the relay.
closeaddressAlias of on — energize the relay.
pulseaddress, delayMomentarily flip the relay and return it — a dry-contact trigger. Uses the delay arg if given, otherwise the zone's Pulse Delay (ms), otherwise 1000 ms.
get_statusRead /state.json now and refresh all relay/input states.
sync_zonesRe-run discovery: create a zone for any relay or input that doesn't have one yet.

address is the zone address (relay_N). You rarely type these by hand — sending an on / off / pulse verb to a zone supplies the address for you. Only relay_* zones accept control commands; sending a command to an input_* zone is rejected.

Relay state and subsystems

The board reports each relay as energized or de-energized, and the driver translates that into a semantic zone state that fits the zone's subsystem. The default subsystem mappings are:

SubsystemRelay energized (contacts closed)Relay de-energized (contacts open)
Gates, Garages, Liftsopenclosed
Doors, Locksunlockedlocked
Lights, Fans, Power, Wateronoff
Shadesopenclosed
Securityarmeddisarmed

So the same relay reads as "open" when the zone lives in Gates and as "on" when you re-home it to Lights — you don't rewire or reconfigure anything, just move the zone. This is why the setup step is "re-home the zone", not "pick a state mapping".

Two per-zone overrides adjust this:

  • Normally Closed flips the mapping for a relay wired to a normally-closed contact (energized now reads as the closed/off state instead of open/on).
  • For anything the table above doesn't cover, set a relay_states JSON attribute on the zone (or its subsystem) with your own { "closed": "...", "open": "..." } pair. See Relay semantics for the full precedence order.

Pulse behavior

pulse is the dry-contact trigger used for gate and garage operators and any device that wants a momentary button-press rather than a latched state:

  • Normally-open (default): the relay energizes (contacts close), holds for the pulse delay, then de-energizes (contacts open) — a momentary closure.
  • Normally Closed = true: the sequence reverses — the relay de-energizes, holds for the pulse delay, then re-energizes — a momentary open on a contact that rests closed.

Set the hold time on the relay zone's Pulse Delay (ms), or pass an explicit delay arg when you call pulse from a macro. If a gate operator ignores the trigger, lengthen the delay — some operators need more than 500 ms of contact to register.

Known quirks

  • Auto-created zones always land in Gates with a default gate control. Re-home relays that actually drive lights, power, locks, or shades so their state and controls read correctly.
  • Only relays are controllable; inputs are monitor-only and reject commands.
  • The board exposes relay writes over an unauthenticated-looking query string; if you enable HTTP Basic auth on the board, be sure to fill in HTTP Username / HTTP Password or every read returns an empty body (see Troubleshooting).
  • Older GEM installs may have relay zones addressed as a bare number with a separate type attribute. Those are migrated to the relay_N / input_N form automatically the next time the device connects — no action needed.

Troubleshooting

SymptomCheck
sync_zones creates nothing but the board has relaysOpen http://BOARD_IP:PORT/state.json in a browser. A wrong username/password makes the board return an empty body, so the driver sees no relays. Fix the credentials, then Reload the device.
No zones created at allConfirm a subsystem whose name contains gate exists (the default Gates). If the defaults were deleted, recreate one under Subsystems, then Reload the device.
Pulse fires but the gate/garage doesn't moveIncrease Pulse Delay (ms) on the relay zone — many operators need >500 ms of contact closure to register.
Input or relay state reads invertedToggle Normally Closed on the zone, or set a custom relay_states mapping.
A relay reads the wrong word (e.g. "open" when you expect "on")The zone is in the wrong subsystem. Move it to the subsystem that matches the load — see Relay state and subsystems.
Newly wired relays don't appearPress Reload on the device, or run the sync_zones command, to re-discover points.
  • Zones — addresses, subsystems, and per-verb command overrides.
  • Subsystems — where relay zones live and how their default state mapping is chosen.
  • Relay semantics — how relay open/closed states map to on/off, locked/unlocked, and open/closed across subsystems.
  • Commands — how on / off / pulse verbs route to a device.