Ubiquiti UniFi Network
The UniFi Network driver connects GEM to a Ubiquiti UniFi Network controller for two things:
- Internet / WAN status. Whether the site is online, which WAN is carrying traffic, whether it has failed over to a backup WAN, the public IP and ISP, latency and availability. Each WAN can also be its own zone.
- UniFi managed switch control (USW / Pro / Enterprise). Turn PoE on or off per port, power-cycle a powered device, enable or disable a port, and reboot the switch, plus read each port's live PoE draw and link state.
The classic switch use is putting the power to a PoE camera, access point, or PoE-powered display under automation. The classic WAN use is a trigger that alerts or changes behaviour when the internet drops or the site fails over to its backup line.
This driver was called UniFi Switch (unifi_switch) before WAN status was added.
GEM talks to your UniFi Network controller: the UniFi OS console (UDM, UDM Pro, UDR, UCG, Cloud Key Gen2+) or a self-hosted UniFi Network application. It does not talk to a switch's own IP. A switch is identified by its MAC address, and all commands flow through the controller's local API.
Prerequisites
- A UniFi Network controller, reachable from the GEM controller over HTTPS (default 443 on a UniFi OS console, 8443 on a self-hosted standalone controller).
- Credentials, one of:
- An API key (UniFi OS consoles, Network 9.3 or newer). Create it in the console under Settings → Control Plane → Integrations. One key covers WAN status and switch control. This is the preferred option.
- A local admin account on the controller. Ubiquiti SSO / cloud accounts and any account with multi-factor authentication are rejected by the local API. A self-hosted standalone controller has no API keys, so it always needs this.
- For WAN status: a UniFi gateway at the site (UDM, UCG, UXG, USG). A site behind a non-UniFi router has no WAN data to read.
- For switch control: the switch's MAC address, in colon-separated form (
aa:bb:cc:dd:ee:ff). Find it in the UniFi UI under Devices → (the switch) → Overview, or read it back from GEM with theget_devicescommand below.
Setup
- Create the device. Go to System → Devices (Open Devices), add a device, and set Driver to
unifi_network. Set Enabled to Yes. - Fill in the connection fields:
- Controller IP / Host (
ip) — the LAN address of the UniFi controller. Not the switch. - API Key (
api_key) — on a UniFi OS console, paste the key here and leave the username and password empty. Stored encrypted. - Admin Username (
username) and Admin Password (password) — the local admin account, if you aren't using an API key. The password is stored encrypted. - Switch MAC Address (
device_mac) — the MAC of the switch whose ports you want to control, e.g.aa:bb:cc:dd:ee:ff. Leave it blank for WAN status only. - Controller Port (
port) — leave at 443 for a UniFi OS console; set 8443 for a self-hosted standalone controller. - UniFi OS Console (
unifi_os) — leave on for UDM / UDM Pro / UDR / Cloud Key Gen2+. Turn it off only for a standalone self-hosted UniFi Network application. - Site (
site) — leave asdefaultunless your controller manages multiple sites, in which case enter the site's short-name (see troubleshooting).
- Controller IP / Host (
- Save. GEM connects to the controller and starts reading WAN status, and polling the switch if one is set. Confirm the device comes up connected and that
internet_onlineandactive_wanappear in its attributes. - Find the MAC if you don't have it. From System → Commands (Open Commands) or the Script Console, run
get_devicesagainst the device to list every adopted device (name, model, MAC). Copy the switch's MAC into Switch MAC Address if you left it blank. - Map ports to zones (next section) — one zone per port you want to control or monitor.
await gem.command({device_id: <device_id>, command: 'get_device'});
This returns the switch record the driver is tracking, including its port_table. If it comes back with data, the login and MAC are correct.
WAN status
WAN status needs no setup beyond the connection. Once a minute (wan_interval), GEM reads the controller's site health, the gateway's WAN ports and the configured WANs, and writes these device attributes. Each is written only when it changes, so attribute history and triggers see transitions, not a stream of identical values.
| Attribute | Meaning |
|---|---|
internet_online | true while the controller's internet check passes or any WAN is online |
active_wan | Name of the WAN carrying traffic, e.g. Internet 1. Empty when none is |
wan_failover | true while traffic runs on a WAN other than the one with the highest failover priority |
wan_status | The controller's WAN health: ok, warning, error or unknown |
wan_ip | Public IP of the active WAN |
isp_name | The ISP the controller identifies for the active WAN |
wan_latency | Current internet latency, ms |
wan_availability | The active WAN's availability over the last 24 hours, % |
GEM logs one line when the internet drops or comes back, and when the active WAN changes.
A zone per WAN
To put each WAN on a UI or watch it on its own, give it a zone. Open the device's Setup tab and click Discover, which lists the WANs and creates a zone for each one you tick. To add one by hand, create a zone with Address set to the WAN's network group: WAN for the first WAN, WAN2 for the second, and so on. Pick whatever subsystem suits; a Network subsystem is a natural home.
| Zone attribute | Meaning |
|---|---|
state | online, offline, or unknown (nothing reported, e.g. a WAN with nothing plugged in) |
active | true for the WAN carrying traffic |
wan_ip, isp_name | That WAN's public IP and ISP |
latency | That WAN's latency, ms |
availability | That WAN's availability over the last 24 hours, % |
link_speed, link_up | The gateway port's link speed (Mbps) and whether the link is up |
Mapping ports to zones
This driver does not create zones automatically — you add one zone per port you care about. Each zone's Address is the port number printed on the switch faceplate (1-based), and that port number is how every command targets the port.
- Go to System → Zones (Open Zones) and add a zone.
- Pick the UniFi switch as the zone's Device. The Subsystem pre-selects Power (one of the default subsystems); leave it there unless you have a reason to file the port elsewhere.
- Set Address to the faceplate port number — e.g.
4for port 4. - Port Type (
port_type) — an optional zone attribute:poe(default) — the zone's on/off state tracks whether the port is delivering PoE. Use this for PoE cameras, APs, and PoE displays.data— the zone's state tracks whether the port's link is up. Use this for a non-PoE port you only want to enable/disable or monitor.
- Save. On the next poll the zone picks up its live
state,poe_power, andlink_upvalues.
Once a port is a zone, it behaves like any other on/off zone: it can sit on a UI as a toggle, be switched from a macro, or be driven by a trigger. On a control that offers a port picker, the port commands bind to the zone's address automatically.
What on / off actually do
on / off (and their explicit forms port_poe_enable / port_poe_disable) change the port's PoE override in the controller's configuration — exactly as if you toggled PoE for that port in the UniFi UI. The change persists until something sets it back. Turning a zone off cuts PoE and powers down whatever the port feeds; turning it back on restores PoE (auto mode).
To momentarily reboot a stuck powered device without changing its configured PoE state, use port_poe_cycle instead — it issues a one-shot power-cycle and leaves the port's saved settings untouched.
port_enable / port_disable are the separate data-forwarding override — they administratively bring the port up or down (forward = all vs disabled), independent of PoE. reboot_switch restarts the entire switch and briefly drops every port on it, so treat it as a deliberate operator action, not routine automation.
Device attributes
| Attribute | Label | Type | Default | Notes |
|---|---|---|---|---|
ip | Controller IP / Host | string | — | LAN IP/hostname of the UniFi controller (required) |
api_key | API Key | string (secure) | — | UniFi OS API key; when set, username/password are not used |
username | Admin Username | string | — | Local admin account (when not using an API key) |
password | Admin Password | string (secure) | — | Stored encrypted (when not using an API key) |
device_mac | Switch MAC Address | string | — | Switch MAC, aa:bb:cc:dd:ee:ff. Needed only for switch control |
port | Controller Port | int | 443 | 443 for UniFi OS, 8443 for standalone |
unifi_os | UniFi OS Console | bool | true | Off for a self-hosted standalone controller |
site | Site | string | default | Controller site short-name |
status_interval | Status Poll Interval (ms) | int | 30000 | How often port state is refreshed |
wan_monitoring | WAN Monitoring | bool | true | Off stops WAN polling |
wan_interval | WAN Poll Interval (ms) | int | 60000 | How often WAN status is refreshed; minimum 10000 |
Zone attributes
| Attribute | Type | Notes |
|---|---|---|
address | int | Faceplate port number, 1-based (required). WAN zones use the network group instead (see A zone per WAN) |
port_type | string | poe (default) tracks PoE power as state; data tracks link up/down |
state | string | on / off, set by polling — on when the port is delivering PoE (poe zones) or the link is up (data zones) |
poe_power | float | Live PoE draw on the port, in watts |
link_up | bool | Whether the port's link is up |
Commands
| Command | Effect |
|---|---|
on / port_poe_enable | Enable PoE on the port (poe_mode = auto). Persistent override. address = port number |
off / port_poe_disable | Disable PoE on the port (poe_mode = off), cutting power to the device. Persistent override |
port_poe_cycle | One-shot power-cycle of the port's PoE — reboots the powered device without changing its saved settings |
port_enable | Administratively enable the port (data forwarding = all). Persistent override |
port_disable | Administratively disable the port (data forwarding = disabled). Persistent override |
reboot_switch | Reboot the entire switch — drops every port, use deliberately |
get_devices | List every device the controller has adopted (name, model, MAC) — use to find the switch MAC |
get_device | Return the tracked switch record, including its port table |
get_clients | List clients currently connected to the site |
login | Force a fresh login to the controller (does nothing with an API key) |
get_wan | Read WAN status now: the summary plus each WAN's state, IP, ISP, latency and availability |
get_health | The controller's raw site health (stat/health) |
The five port commands take address = the port number; on a control they bind to the zone's address so a port picker is offered. With a username and password, the session cookie and CSRF token are refreshed automatically, and the driver logs in again on its own if the controller expires the session. With an API key there is no session: the key goes on every request.
Controller API reference
Useful when you are matching GEM's behavior to what you see in the UniFi controller. Paths differ between a UniFi OS console and a standalone controller — GEM chooses automatically from the UniFi OS Console toggle:
| Action | UniFi OS console | Standalone controller |
|---|---|---|
| Login | POST /api/auth/login | POST /api/login |
| Site path prefix | /proxy/network/api/s/<site> | /api/s/<site> |
| List devices | <site>/stat/device | same |
| The switch record | <site>/stat/device/<mac> | same |
| PoE / port override | PUT <site>/rest/device/<id> with port_overrides | same |
| Power-cycle a port | POST <site>/cmd/devmgr {cmd: power-cycle, mac, port_idx} | same |
| Reboot the switch | POST <site>/cmd/devmgr {cmd: restart, mac} | same |
| Site health (WAN / internet) | <site>/stat/health | same |
| The gateway (WAN ports) | <site>/stat/device/<gateway mac> | same |
| Configured WANs | /proxy/network/v2/api/site/<site>/wan/enriched-configuration | /v2/api/site/<site>/wan/enriched-configuration |
| API key | X-API-KEY: <key> header on every request | not available |
The controller's TLS certificate is self-signed, so GEM does not verify it — point the device at a controller IP you control on a trusted LAN.
Automation ideas
- Know when the internet drops. A trigger on
internet_onlinebecomingfalsecan send a notification over a path that doesn't need the internet (local display, SMS gateway), or switch the site to a degraded mode. - Know when you've failed over. A trigger on
wan_failoverbecomingtruecan warn that the site is running on its backup line, which may be metered or slower. - Bounce a hung camera or AP. A trigger on a camera going offline, or a scheduled overnight maintenance macro, can run
port_poe_cycleon that port to power-cycle the device without touching its configured PoE state. - Power a display or sign with the room. Wire a PoE display to a switch port, make it a
poezone, and let a room's on/off scene turn the port on and off with everything else. - Load shedding. Turn
offnon-essential PoE ports (signage, secondary APs) from an "away" or energy-saving macro, andonagain when the site is occupied. - Watch PoE draw.
poe_powerrecords each port's wattage over time — history charts show consumption and can flag a device drawing more than expected.
Troubleshooting
| Symptom | Check |
|---|---|
Device won't connect / login fails with 400 or 401 | You're using a Ubiquiti SSO / cloud or MFA account — the local API only accepts a local admin account. Create one on the controller, or use an API key. |
http 401 — the controller refused the API key | The key was deleted or mistyped. Create a new one under Settings → Control Plane → Integrations. A standalone controller has no API keys; use a local admin username and password. |
| No WAN attributes appear | The site needs a UniFi gateway. Run get_wan to see what the controller reports, and check WAN Monitoring is on. |
A WAN zone stays unknown | Nothing is plugged into that WAN, or its Address doesn't match a network group (WAN, WAN2, …). get_wan lists the ids. |
Connects but no port data / device not found | Switch MAC Address must be the switch's MAC, colon-separated (case and surrounding spaces are ignored). Run get_devices to confirm the MAC. |
A command answers controller error: api.err.… | The controller accepted the request but refused it (for example an unknown device or an invalid port setting). The message is the controller's own; nothing was changed. |
get_devices comes back empty | Wrong Site short-name. The default site's short-name is literally default; for multi-site controllers, check the site's short-name in the UniFi UI. |
| Everything times out / wrong page returned | Check the Controller Port and UniFi OS Console toggle match your controller — 443 + on for a UniFi OS console, 8443 + off for a standalone controller. |
| A port override seems to have no effect | Some models ignore a port override until the port has a port profile assigned. Check Devices → (switch) → Ports in the UniFi UI. |
| Zone state doesn't update | Confirm the zone Address is the faceplate port number and that the port appears in the switch's port table (get_device). |
Related documentation
- Devices — adding the UniFi controller as a device and editing its connection settings.
- Zones — creating one zone per port and setting each zone's address and Port Type.
- Subsystems — the Power subsystem port zones file under, and where to add a Network subsystem for WAN zones.
- Commands — running
get_devices,port_poe_cycle, and the rest by hand to verify the link. - Device Health — watching the switch's connection state.
- Macros and Triggers — power-cycling ports and shedding PoE loads on a schedule or in response to events.
- UniFi Protect — the companion driver for Ubiquiti's Protect cameras/NVR.
- UniFi Access and UniFi Presence — the other UniFi drivers.