Hubitat Elevation (Maker API)
Bridge a Hubitat Elevation hub into GEM via the local Maker API. Every device an integrator has paired into Hubitat (Z-Wave, Zigbee, Lutron, cloud apps) becomes a GEM zone addressable by Hubitat device id. No cloud token, no re-pairing of hardware.
Prerequisites
- Hubitat Elevation hub on platform 2.2.4 or newer.
- The built-in Maker API app installed: Apps → Add Built-In App → Maker API.
- Inside the Maker API app, the devices you want GEM to control already selected and saved.
- The hub on a reserved LAN IP (router DHCP reservation, or set statically in Hubitat).
Setup steps
- Open the Maker API app in Hubitat (Apps → Maker API). Note three values:
- App ID — shown at the top of the page (e.g.
142). - Access token — listed under "Local URLs", a long hex string.
- Hub IP — the IP shown in the Local URL.
- App ID — shown at the top of the page (e.g.
- Create a Device in GEM with driver
hubitat_elevation. Fill in:ip— hub IP.app_id— Maker API app id.api_key— the access token. Stored encrypted (the nameapi_keytriggers auto-encryption).
- Run the
get_devicescommand. The response is the full list of devices exposed by the Maker API, each withid,name,label,type, andcapabilities. - Create one GEM Zone per Hubitat device. Set
zone.addressto the numeric Hubitat device id. - Set each zone's subsystem (
lights,shade,lock,security,climate,plug, etc.) so verbs dispatch correctly.
Attribute reference
Required
| Attribute | Type | Description |
|---|---|---|
| ip | string | Hub LAN IP. No scheme — driver builds http://<ip>:<port> internally. |
| app_id | string | Maker API app id (numeric, but stored as string so leading zeros / textual ids survive). |
| api_key | string | Maker API access token. Stored encrypted. |
Optional
| Attribute | Type | Default | Description |
|---|---|---|---|
| port | int | 80 | Override if the hub runs behind a port-mapped NAT (rare; the hub serves Maker API on 80 by default). |
| status_interval | int | 15000 | Per-zone poll interval in ms. 2000–300000. Hubitat is single-threaded for API; sub-second polling will starve it. |
Zone address format
zone.address is the numeric Hubitat device id. It is visible in the Hubitat web UI when editing a device (the URL contains …/device/edit/<id>).
Commands
| Command | Args | Notes |
|---|---|---|
| on / off | address | Maps to Hubitat on / off. |
| set_level | address, level (0-100) | Maps to setLevel/<level>. |
| open / close | address | For shades and other openable devices. |
| lock / unlock | address | Locks. |
| arm_home / arm_away / disarm | address | Security panels with armHome, armAway, disarm capability. |
| push_button | address, button (default 1) | Hubitat button devices — push/<n>. |
| get_devices | Enumerate devices exposed by Maker API. | |
| get_status | address | Read current attributes for one device. |
| raw_command | address, hubitat_command, arg | Escape hatch — sends /devices/<id>/<command>[/<arg>] verbatim. Use this for capabilities the verb table doesn't cover (e.g. thermostat mode, fan speed, scene activation). |
| set_color | address, hue, saturation, level | TODO — not yet implemented. Returns {error: 'not yet implemented'}. |
State reporting
The status loop reads /devices/<id> for each zone, then writes back GEM attributes derived from the Hubitat attribute array. First match wins for zone.state:
| Hubitat attribute | GEM zone.state value |
|---|---|
| switch | on / off |
| contact | open / closed |
| lock | locked / unlocked |
| motion | motion / idle |
| windowShade | passthrough (lowercased) |
| presence | present / away |
Additionally:
level→zone.brightnesstemperature→zone.temperaturehumidity→zone.humiditybattery→zone.battery_level
Known limitations
- Polling only. Maker API does not push events. For fast motion / button reactions, build the rule on the Hubitat side and have Hubitat call a GEM macro via HTTP rather than relying on this driver's poll loop.
- No color control.
set_coloris a stub. Hubitat exposes hue / saturation / level as separate attributes and asetColorJSON command; we have not wired the multi-arg form yet. - Thermostat verbs are not mapped.
set_temperature, mode changes, and fan speed all go throughraw_commandfor now (hubitat_command: setHeatingSetpoint,arg: 72, etc.). - One Hubitat hub per GEM device row. Multi-hub installs need multiple device rows; that is normal — Hubitat itself doesn't pretend to federate hubs.
Troubleshooting
connectwarns "missing app_id" / "missing api_key": confirm both are saved on the device row. The api_key gets encrypted on save; reload the row to check it persisted.get_devicesreturns{error: 'Request failed with status code 401'}: access token is wrong or expired. Open the Maker API app in Hubitat, copy the token from "Local URLs" again, paste into the api_key attribute.get_devicesreturns an empty list: the Maker API app has no devices selected. Open the app in Hubitat, add devices, save.- Commands succeed but state never updates: make sure the corresponding capability is exposed in the Maker API app's "select devices" list. A device added to the hub but not to Maker API stays invisible to GEM.
- Hub slows down under polling: raise
status_interval. 15 s is the default for a reason; hubs with hundreds of devices want 30 s or higher.