Skip to main content

WattBox PDU (SnapAV)

The WattBox driver controls SnapAV WattBox power distribution units on the customer LAN. It turns each switched outlet into a controllable zone — on, off, toggle, and two flavours of power-cycle — and polls the unit a few times a second for outlet state, whole-unit voltage/current/power, per-outlet metering on metered models, and battery telemetry on UPS-equipped units. It also watches the unit for two things that happen outside GEM: a UPS running on battery, and an on-board schedule (set in OvrC) that GEM was never told about.

Transports​

WattBox exposes three ways in, and the driver picks one per Transport (api_mode):

  • Integration protocol (tcp/23, plain telnet) — the vendor-supported control API: outlet set/toggle/reset, names, power-on delays, outlet modes, auto-reboot, whole-unit and per-outlet metering, UPS status, model/firmware/service tag. This is the preferred transport and the only one that carries the configuration commands below.
  • OvrC Embedded Server (HTTP Digest) — newer units (WB-800-IPVM-12 and similar). No status API; the driver reads the unit's web dashboard at /main and switches outlets at /outlet/{on,off,reset}. Also home to the debug log the schedule check reads.
  • Legacy IP-300 series (HTTP Basic) — XML at /wattbox_info.xml, switching at /control.cgi. This firmware mis-frames its chunked HTTP responses, so the driver fetches it with a tolerant raw reader; nothing to configure.

api_mode auto (the default) opens tcp/23 first. If the login succeeds the unit runs on the protocol; if the port is closed or filtered, the driver logs wattbox integration protocol unavailable, using http and detects which HTTP generation it is talking to, retrying the protocol every five minutes in the background. A protocol link that drops after it was up (the unit rebooting, say) is reconnected with a short backoff; after three failed reconnects in a row the http path takes over until the slow retry brings the protocol back, so state is never lost — only the extra verbs.

protocol insists on tcp/23 and reconnects forever without ever scraping. http never opens tcp/23 at all — for a unit where telnet was disabled with !SetTelnet, or a network that filters it.

Whichever transport is in use, the attributes below are named identically, so triggers and dashboards built on one keep working on the other. A site upgrading from an http-only build sees its units move to the protocol on the next connect with no change to the attribute set.

Prerequisites​

  • A WattBox on the same LAN as the GEM controller, reachable over HTTP and (for the full feature set) tcp/23. The IP-300 series and newer ship with both enabled.
  • The unit's username and password. WattBox ships with wattbox / wattbox — change these on the device and use the new credentials here. The same credentials serve the protocol and the web server.
  • A static IP (or DHCP reservation) for the WattBox.

Setup​

  1. Assign a static IP to the WattBox (or reserve its DHCP lease), and confirm you can reach its web UI in a browser.
  2. Create the device under System → Devices (Open Devices) with driver wattbox. Set:
    • WattBox IP (ip) — the unit's address, e.g. 192.0.2.24. You may include a port (192.0.2.24:8080) if the web UI is served somewhere other than port 80; the protocol port is separate.
    • Username (username) — defaults to wattbox.
    • Password (password) — stored encrypted.
    • (optional) Transport (api_mode) — auto (default), protocol, or http.
    • (optional) Protocol Port (protocol_port) — default 23.
    • (optional) Status Poll Rate (ms) (poll_rate) — default 3000.
    • (optional) Schedule Log Check Rate (ms) (schedule_poll_rate) — default 3600000 (hourly); 0 disables the check.
  3. Save. On the first successful poll the driver discovers the outlets and auto-creates one zone per outlet in the Power subsystem.
  4. Verify from the Script Console:
    await gem.command({device_id: <device_id>, command: 'get_status'});
    The log line wattbox integration protocol connected confirms the protocol transport; hardware_version, firmware_version and serial_number fill in on the first protocol poll.
tip

The DeviceCreator form shows a short inline quick-start for the driver and a View integration guide toggle that opens this page.

How outlets become zones​

On the first poll after each connect, the driver reads the outlet list (states and names) and creates a zone for every outlet it finds:

  • The zones land in the Power subsystem (recreated if it has been deleted).
  • Each zone's address is the 1-based outlet number, matching the physical labeling on the WattBox.
  • The zone's label comes from the outlet name configured on the WattBox; a still-generic name (Outlet 3) gives the label Outlet 3.
  • Each zone is created with the power_default control and reports its state (on / off).
  • Outlet names need not be unique, so a derived zone name that another zone already holds gets the outlet number appended. See auto-created zones.

Renames follow, in one direction, when safe. The driver keeps each outlet's unit-side name as outlet_<n>_name. When the name changes on the unit, a zone whose label still equals the old unit name is one nobody relabelled in GEM, so its label follows. A zone you relabelled in GEM is left alone. To rename in the other direction, use the set_outlet_name command.

Device attributes​

You enter the connection attributes; everything else is read from the unit and is read-only. Which telemetry appears depends on the transport, the model, and whether a UPS module is fitted.

AttributeTypeNotes
ipstringRequired. WattBox IP, optionally host:port for the web side.
usernamestringRequired. Default wattbox.
passwordstringRequired, stored encrypted.
api_modestringauto / protocol / http. Default auto.
protocol_portintIntegration protocol port. Default 23.
poll_rateint (ms)Status poll interval on whichever transport is in use. Default 3000.
schedule_poll_rateint (ms)Debug-log check interval. Default 3600000; 0 disables.
known_schedulesjsonExpected on-board schedule names — see below.
host_namestringUnit's host / system name.
hardware_versionstringModel (WB-800CH1U-IPVM-8).
firmware_versionstringFirmware version.
serial_numberstringService tag.
mac_addressstringMAC address (OvrC http only).
voltage_valuenumber (V)Whole-unit input voltage.
current_valuenumber (A)Whole-unit current draw.
power_valuenumber (W)Whole-unit power draw.
safe_voltage_statusintUnit's safe-voltage flag (0 normal). Protocol and legacy.
auto_rebootint1 when the unit's own ping-and-reboot is enabled.
outlet_<n>_statestringPer-outlet on / off (mirrors the outlet zone's state).
outlet_<n>_namestringOutlet name as set on the unit.
outlet_<n>_modestringenabled / disabled / reset_only. Protocol only.
outlet_<n>_power_on_delayint (s)Delay before the outlet powers on after a reset or power-up. Protocol only.
outlet_<n>_power_wnumber (W)Per-outlet power (metered models; protocol or OvrC).
outlet_<n>_current_anumber (A)Per-outlet current (metered models; protocol or OvrC).
hasUPSint1 when a UPS battery module is attached.
battery_chargeint (%)Battery charge (UPS units).
battery_loadint (%)Battery load (UPS units).
battery_healthstringBattery health as the unit reports it (UPS units, protocol or legacy).
est_run_timeint (min)Estimated battery runtime (UPS units).
power_lostint1 while input power is lost and the unit is on battery (UPS units, protocol or legacy).
audible_alarm, muteintUPS alarm enabled / muted (UPS units, protocol or legacy).
schedules_seenjsonEvery on-board schedule name observed, with its last fire and what it switched.
unknown_schedulesjsonNames in schedules_seen that are not in known_schedules.
last_schedule_fired / last_schedule_fired_atstringThe most recent on-board schedule fire.

On the protocol transport the driver polls outlet state and whole-unit power every tick, refreshes names, modes, delays, auto-reboot and UPS presence once a minute (every 20th poll), and reads per-outlet metering one outlet per tick, round-robin. A model that answers #Error to the per-outlet query is unmetered and is not asked again.

Legacy units are normalized to real units

Legacy firmware puts voltage and current on the wire in tenths (1200 = 120.0 V). The driver divides these by 10 so voltage_value / current_value / power_value read in real units on every transport and firmware generation.

Zone attributes​

AttributeTypeNotes
addressstringRequired. 1-based outlet number. Auto-set on discovery.
statestringon / off, refreshed every poll.

Commands​

getCommands() declares the following. The standard on/off verbs map to the matching commands, so an on/off control on an outlet zone works with no extra configuration; the named commands are there for macros and triggers. Commands marked protocol need the integration protocol and answer with an error on the http transports.

CommandAliasesTransportEffect
onpower_onanyTurn the outlet on. address = outlet number.
offpower_offanyTurn the outlet off.
toggle—anyFlip the outlet. On http it flips the last polled state.
reboot—anyPower-cycle from GEM: off, wait delay ms (optional, default 5000; 0 switches straight back on), on. A non-numeric or negative delay is refused.
reset—anyPower-cycle on the unit, honouring the outlet's own power-on delay. On legacy firmware this only works while the outlet is on.
set_outlet_name—protocolRename the outlet on the unit (name). No spaces — the protocol stops at the first one, so use underscores; braces and commas are rejected. A zone whose label matched the old name follows.
set_power_on_delay—protocolSeconds the outlet waits before powering on after a reset or unit power-up (delay).
set_outlet_mode—protocolmode = enabled (switchable), disabled (locked as is), or reset_only (can be reset but not switched off).
auto_reboot_on / auto_reboot_off—protocolEnable or disable the unit's own ping-and-reboot of hosts that stop answering.
set_auto_reboot_timeout—protocolTune auto-reboot; all four required: timeout (s a ping may take), count (failed pings before a host is down), ping_delay (s between pings), reboot_attempts.
reboot_device—protocolReboot the WattBox controller itself. Outlets come back per their power-on delays.
get_status—anyPoll the unit now and refresh all attributes.
check_schedules—OvrCRead the debug log now (see below).
await gem.command({device_id: <id>, command: 'reset', args: {address: '4'}});
await gem.command({device_id: <id>, command: 'set_outlet_name', args: {address: '2', name: 'Rack_Amp'}});
await gem.command({device_id: <id>, command: 'set_outlet_mode', args: {address: '4', mode: 'reset_only'}});
reboot vs reset

reboot is GEM's own off→wait→on and works on every transport, but a GEM restart mid-cycle leaves the outlet off. reset hands the cycle to the unit, which uses the outlet's power_on_delay (set it with set_power_on_delay) and completes whatever GEM does. Prefer reset where the protocol is available.

UPS telemetry and the ups_on_battery alarm​

On a unit with a battery module (hasUPS = 1) the driver reads the UPS status every poll: charge, load, health, runtime, and whether input power is lost. When power_lost goes to 1 the built-in UPS On Battery alarm (ups_on_battery) is raised on the device with the charge and estimated runtime in its message, and cleared when mains returns. It is decided only from polls that carry the field (protocol and legacy XML); the OvrC dashboard scrape has no power-lost indicator, so on that transport the battery attributes still update but the alarm does not fire. Like every built-in, the definition arrives with no recipients — give it notify steps under Insights → Alarms (alarms) to be paged.

caution

The protocol drops the session, without a word, if a UPS query reaches a unit with no UPS attached. The driver asks ?UPSConnection first and only then ?UPSStatus; a user script that sends UPS verbs by hand to an unequipped unit will see the connection reset.

On-board schedules and the unknown_schedule alarm​

Managing schedules

This driver can only detect on-board schedules. To list, add, edit, enable, disable or delete them, add the same unit through the OvrC cloud driver, which reads and writes the schedule list in OvrC. Both drivers write the same attribute names and can run side by side.

OvrC-firmware WattBoxes can run outlet schedules of their own (a nightly reboot of a media player, say) — but those schedules live in the OvrC cloud, not on the unit. The local protocol has an !ScheduleAdd verb and no ?Schedule query, and the embedded web server has no schedule page. The only local evidence that a schedule exists is the unit's debug log (/log_debug), which records each fire:

[09-20T03:30:00] Schedule Nightly Player Reboot Triggered
[09-20T03:30:00] SWITCHING OUTLET 2 [OFF]
[09-20T03:30:14] POWER ON DELAY!
[09-20T03:31:06] SWITCHING OUTLET 2 [ON]

So a schedule cannot be seen when it is created, only the first time it runs — for a daily schedule, within a day. The driver reads the log every schedule_poll_rate (hourly by default, on its own timer, never on the 3 s poll: the log is a full 20–80 KB dump every fetch and the unit rotates it by size every few days, so keep the rate well under a day) and:

  1. On the first check ever for the device, it records every schedule name already in the log as the installed baseline in known_schedules, and alarms on nothing.
  2. On every later check, a schedule that fires and is not in known_schedules raises the built-in Unknown Device Schedule alarm (unknown_schedule) on the device. The message names the schedule, when it last ran (in the unit's own clock) and what it switched, with outlet names: unknown schedule on rack wattbox: "Deck Off" (last 09-20T20:00:00: off 5 (DECK)). add the name to known_schedules to accept it.
  3. To accept the schedule, add its name to known_schedules on the device (a json array; a comma-separated string also works). The alarm clears at the next check. To reject it, remove it in OvrC — the alarm clears the same way once the name is listed, or stays open as a reminder until then.

schedules_seen keeps every name observed with its last fire, and last_schedule_fired / last_schedule_fired_at are trigger-friendly. check_schedules runs a check on demand and returns what it found. The check works on the protocol transport too (it fetches the log over HTTP Digest alongside); on a legacy unit the log is absent and the check switches itself off until the next connect.

To start with a hand-picked list instead of the log baseline, set known_schedules before the first check (an empty array [] means "nothing is expected", so the first fire of anything alarms).

Automation ideas​

  • Scheduled reboot of a stuck device. A macro schedule firing reset on the outlet feeding a flaky modem, AP, or media player overnight clears a lockup before anyone notices — and, done in GEM rather than OvrC, it is visible in History rather than only in the unit's log.
  • Recovery trigger. Pair a device-offline condition with a reset of that device's outlet to auto-power-cycle gear that has hung, with a guard so it doesn't loop. Or let the unit do it: auto_reboot_on with hosts configured on the WattBox.
  • Power telemetry. power_value (and per-outlet outlet_<n>_power_w) charts draw over time; trigger on an unexpected drop to zero to catch a tripped breaker or a load that died.
  • UPS-aware shutdown. On battery-equipped units, act on the ups_on_battery alarm or on est_run_time dropping below a threshold to shed non-critical outlets before the battery is exhausted.
  • Lock the critical outlets. set_outlet_mode with reset_only on the network switch outlet means a mis-tap on a UI can still reset it but never leave it off.

Troubleshooting​

SymptomWhat to check
wattbox integration protocol unavailable, using http in the logstcp/23 is closed or filtered between GEM and the unit — telnet disabled on the WattBox (!SetTelnet), a firewall, or a wrong protocol_port. The unit keeps working over http meanwhile; the protocol is retried every five minutes. Set api_mode to http to stop trying.
login rejected on the protocolThe protocol uses the same username/password as the web UI — verify them there.
401 / "Unauthorized" on every http requestOvrC-firmware units require HTTP Digest rather than Basic — the driver auto-detects this, so a persistent 401 almost always means wrong credentials or an unreachable address.
"could not detect api mode" in the logsNeither the legacy XML endpoint nor the OvrC dashboard answered. Confirm the configured IP/port serves the WattBox web UI directly (not a captive portal or a redirect).
Protocol-only command answers "requires the wattbox integration protocol"The device is on an http transport. Check the two rows above, or the unit is a legacy model without the protocol.
?OutletPowerStatus never populates outlet_<n>_power_wUnmetered model; the unit answers #Error and the driver stops asking.
reboot leaves the outlet offThe 5 s default delay was too short for that load to settle — pass a larger delay (ms), or use reset and let the unit's power-on delay govern.
Outlet flips back unexpectedlyIf the WattBox is also cloud-managed through OvrC, a concurrent OvrC command or schedule can race GEM's. Check schedules_seen; decide on one controller for switching.
set_outlet_name refuses a name with a spaceThe integration protocol takes the name verbatim and stops at the first space (verified on a live unit), so a spaced name would be silently truncated. Use underscores, or rename in the WattBox web UI or OvrC, where spaces work; the zone label follows either way.
Schedule alarm for a schedule that has existed for monthsThe log rotates by size, so a schedule that fires rarely (weekly) may not have been in the log at the first check and gets flagged on its first observed fire. Add it to known_schedules.
  • Devices — adding and configuring the WattBox device.
  • Zones — the auto-created outlet zones and their labels.
  • Alarms — the ups_on_battery and unknown_schedule built-ins and how to give them recipients.
  • Commands — how the on/off/reset verbs are dispatched.
  • Triggers and Macros — building the automation ideas above.
  • OvrC Cloud (WattBox) — the same unit through the OvrC cloud, for listing, editing and deleting its schedules.
  • CyberPower UPS — the other PDU/UPS power driver, over SNMP.