Hayward Omnilogic
The Hayward Omnilogic driver controls Hayward's HLBASE / HLPRO pool & spa controllers via the public Hayward customer-portal API. It authenticates against haywardomnilogic.com, polls telemetry for the configured MSP site, and dispatches equipment commands (filter pumps, lights, heaters, valves, auxiliary relays) on demand. It is cloud-only — there is no on-LAN protocol published by the vendor.
Status
Built against the public HAAPI XML endpoint. Read paths (Login, GetSiteList, GetMspConfigFile, GetTelemetryData) and write paths (SetUIEquipmentCmd, SetHeaterEnable, SetUIHeaterCmd, SetStandAloneLightShow) are implemented. Schedule create/update, chemistry control, and salt-system commands are not yet wired — capture the EquipmentIds with get_config and use the equipment-on/off path until they land.
Prerequisites
- Active account at https://www.haywardomnilogic.com — same credentials as the Omnilogic mobile app.
- The Omnilogic controller is registered to the account and visible in the mobile app.
- Outbound HTTPS from the GEM controller to
www.haywardomnilogic.com(port 443).
Setup
- Verify the mobile app works. If the Omnilogic mobile app cannot reach the controller, this driver cannot either — the cloud is the only published path home.
- Create the device under System > Devices with driver
hayward_omnilogic. Set:username— yourhaywardomnilogic.comemailpassword— yourhaywardomnilogic.compassword (stored encrypted)
- Verify connection. From the Script Console:
You should see one or more entries likeawait gem.command({device_id: <device_id>, command: 'get_sites'});
[{MspSystemID: 12345, ...}]. The driver auto-selects the first site if the account owns one site; otherwise setmsp_system_idexplicitly:await gem.setAttribute('device', <device_id>, 'msp_system_id', '12345'); - Discover equipment IDs.
The response includes the full MSP configuration withawait gem.command({device_id: <device_id>, command: 'get_config'});
EquipmentIdvalues per pump / light / heater / aux. Note them down. - (Optional) Create one zone per piece of equipment with
addressset to the EquipmentId. The poller will surface state changes on each zone. - Test a command.
await gem.command({device_id: <device_id>, command: 'set_equipment', args: {address: 8, on: true}});
Attributes
Device
| Attribute | Required | Type | Notes |
|---|---|---|---|
username | yes | string | Hayward portal email. |
password | yes | string (secure) | Hayward portal password. |
msp_system_id | no | string | Omnilogic site ID. Auto-discovered if the account owns a single site; required for multi-site accounts. |
polling_interval | no | int | Telemetry poll interval in ms. Default 60000, minimum 10000; a value that is unparseable or larger than 2147483647 uses the default. |
request_timeout | no | int | HTTP request timeout in ms. A value that is unparseable, 0, negative or larger than 2147483647 uses 10 s. |
Runtime-populated (read-only, written by the poller):
| Attribute | Type | Source |
|---|---|---|
air_temp_f | int | Backyard.@_airTemp from the parsed telemetry blob |
water_temp_f | int | BodyOfWater.@_waterTemp |
flow_state | string | BodyOfWater.@_flow |
system_status | string | Backyard.@_status |
Zone
Zone address is optional. If set, it must match an Omnilogic EquipmentId from get_config.
| Attribute | Type | Source |
|---|---|---|
state | string | on / off derived from the equipment's reported state attribute |
speed | int | for variable-speed pumps |
temp_f | int | for heater equipment items |
Commands
| Name | Args | Description |
|---|---|---|
get_sites | — | List MSP system IDs visible to the account. |
get_config | — | Full MSP configuration (equipment IDs, names, capabilities). |
get_telemetry | — | Current telemetry snapshot. Refreshes attributes. |
set_equipment | address, on | Turn an equipment item on/off. address = EquipmentId. |
set_heater | address, enabled | Enable/disable a heater. address = HeaterId. |
set_heater_setpoint | address, temperature | Set heater setpoint in Fahrenheit. |
set_light_show | address, show | Set a ColorLogic light show by integer show ID. |
Each address must be a whole-number id from get_config. A missing, blank or unfilled ([address]) address is refused with missing address (...), and anything that is not a whole number up to 2147483647 with invalid address (...) — nothing is sent. Padding around an id is trimmed. on and enabled switch on for true, 1, on or yes in any case; every other value, or none, switches off. temperature and show are whole numbers (a fraction is truncated); a blank or unparseable value, or one past 2147483647, is refused.
A command answers an error, not success, when the cloud's reply carries a non-zero status (the error names the call, the status and the cloud's message) or when the reply is not a Hayward response at all, such as a maintenance page. get_sites, get_config and get_telemetry report a non-zero status the same way.
Connection and polling
When the device connects it logs in, picks the site and reads telemetry. If any of that fails — wrong credentials, the cloud unreachable, the controller offline — the device shows offline and the driver tries again on its own after 30 seconds, doubling the wait each time up to 15 minutes, so a site that was down when GEM started comes back without a reload. Once connected, a failed telemetry poll likewise doubles the wait before the next one (up to 15 minutes, or the poll interval if that is longer) and returns to the normal interval as soon as a poll succeeds. Requests running at the same time share one login, and a token the cloud refuses within a minute of being issued is reported as an error rather than triggering another login, so a bad password is not retried in a burst toward the portal's lockout.
A zone matches its equipment by number, so a zone addressed 08 picks up equipment 8. A zone with no address never receives equipment state.
Known limitations
- Cloud-only. There is no LAN path; all traffic goes through
haywardomnilogic.com. - Telemetry can lag a real-world equipment change by 30–60 seconds.
- Schedule create / edit / delete is not yet implemented.
- Salt chlorinator setpoint, ORP/pH dosing, and chemistry feeder commands are not yet implemented.
- Multi-body-of-water sites (pool + separate spa) are partially handled — telemetry parses the first BodyOfWater; per-body command targeting needs the EquipmentId from
get_config.
Troubleshooting
| Symptom | Check |
|---|---|
login status 2 or http 401 on first connect | Email or password is wrong. Sign in at https://www.haywardomnilogic.com manually to confirm the credentials work. |
GetTelemetryData returns empty Parameters block | Omnilogic controller is offline (no WAN path home). Check the controller display + home wifi. |
set_equipment returns success but the pool equipment never reacts | EquipmentId is wrong, OR an active schedule is overriding the manual command. Verify the EquipmentId via get_config; pause schedules in the Omnilogic mobile app to test. |
connect timeout | GEM controller cannot reach www.haywardomnilogic.com. Check DNS + outbound 443. |
SetUIEquipmentCmd status N: ... (or another call name) | The cloud refused the call; the text after the colon is the cloud's own message. Check the id with get_config. |
auth: re-auth: ... repeating in the device log | The portal is rejecting the credentials. Confirm the account is active and not locked out by a password policy. |