Tridium Niagara N4 (oBIX)
GEM integrates with Tridium Niagara N4 / AX JACE controllers — and any oBIX-compliant building automation server (Honeywell Vykon, Distech ECx, JCI FX, Lynxspring Onyxx) — through the OASIS oBIX REST contract. Each Niagara station point is exposed as a GEM zone, with bool/level reads and writes flowing through /obix/... endpoints over HTTP(S).
This is the right driver to use when an integrator wants to drag in a BACnet-rich Tridium graphic into a GEM dashboard, expose JACE schedule writes to GEM macros, or surface fan/setpoint overrides on a wall touchscreen.
Prerequisites
- Niagara station running N4.x (AX legacy works but is untested here) with the
obixmodule loaded. - An
ObixServerExt(or the olderObixNetworkserver) under Station → Services, with HTTP Basic authentication enabled. The default oBIX URL ishttp://<jace>/obix. - A station user account with operator-level read + invoke permission on the points you plan to control. Do not use the station admin account.
- Network reachability from the GEM controller to the JACE on the station HTTP port (typically 80 or 443).
If the site fronts Niagara with a reverse proxy or the station uses Niagara Cookie Digest auth, you must either enable Basic auth on ObixServerExt or place GEM behind the proxy on the same auth context — this driver only sends HTTP Basic.
Setup
- Add a device with driver
niagara_obix. - Set
ipto the JACE IP/hostname. Setportto the station HTTP port (default 80) andprotocoltohttporhttps. - Set
usernameandpasswordto the station operator account. - (Optional) Set
obix_rootif the site has remapped oBIX away from/obix. - Save and connect. The connect path issues
GET /obix/to confirm credentials. - Run
get_lobbyfrom the script console to see the top-level oBIX containers exposed by the station. - Walk into the station tree with
get_childrencalls (each child has anhrefpointing at the next level). - For each controllable point, create a zone whose
addressis the oBIX href (absolute/obix/config/Drivers/...or station-relativeconfig/Drivers/...).
Attribute Reference
Device
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
ip | string | yes | — | JACE IP/hostname. |
username | string | yes | — | Station operator account. |
password | string | yes | — | Encrypted at rest. |
port | int | no | 80 | Station HTTP/HTTPS port. |
protocol | string | no | http | http or https. Self-signed certs are accepted. |
obix_root | string | no | /obix | Root path where the oBIX server is mounted. |
status_interval | int | no | 30000 | Per-zone polling cadence (ms). |
Zone
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
address | string | yes | — | oBIX href for the point. |
point_type | string | no | bool | bool, int, real, or str. Controls how on/off/set_level encode the body. |
Zone Address Format
zone.address is the oBIX href of the underlying point. Both shapes are accepted:
- Absolute:
/obix/config/Drivers/BacnetNetwork/AHU1/SupplyFan - Station-relative:
config/Drivers/BacnetNetwork/AHU1/SupplyFan
The driver normalizes the path against obix_root before each request, so either form works.
Commands
| Command | Args | Description |
|---|---|---|
on | address | Set the point to true (bool) or 1 (int/real). |
off | address | Set the point to false / 0. |
set_level | address, level | Write a numeric value using the zone's point_type (defaults to real). |
get_point | address | Read a point and return {value, raw}. raw is the original XML. |
set_point | address, value, contract | Write any contract type (bool, int, real, str). |
invoke | address, body | POST a raw oBIX XML body to an invoke href — escape hatch for BACnet override and station-specific ops. |
get_lobby | — | List children of the oBIX root. |
get_children | address | List children of an oBIX path for discovery. |
Known Limitations
- The driver uses a small regex parser for
val=attributes rather than a full XML parser. Complex objects (lists with mixed children, history queries) come back as raw XML throughget_point; the caller is responsible for parsing them. POST /setenforces oBIX contract matching — writing a<real>body to a<bool>point fails with acontractMismatcherror. Align the zone'spoint_typewith the underlying point.- BACnet override semantics are not auto-generated. The typical override body is
<obj><real name="value" val="..."/><reltime name="duration" val="PT1H"/></obj>against the point'sinvokehref; drop that XML into theinvokecommand for now. - WebSocket / Watch contracts are not implemented. State is reflected via periodic polling.
Troubleshooting
- 401 Unauthorized — the user does not have oBIX permission, or
ObixServerExtis not set to Basic. Verify in Workbench under Services → ObixServerExt → Authentication Scheme. - 404 on
/obix/— the obix module is not loaded, or the station has remapped the root path. Try settingobix_rootto the configured path. contractMismatcherrors — the body type doesn't match the point. Useget_pointfirst to discover the existing contract.- Timeouts on every request — confirm the station HTTP port is reachable (
curl -u user:pass http://<jace>/obix/from the GEM host).