Skip to main content

Site Modes

Site Modes define operational states that can be applied to the site or to individual site spaces. Modes enable different automation behaviors based on the current state of a space, such as "Occupied", "Away", "Night", "Party", or "Business Hours".

The mental model is four short sentences:

  1. A mode is a named state you set on the site or any space; spaces without their own mode inherit from above.
  2. Hold pins an assignment — a held space keeps its mode until the hold is released.
  3. Modes carry enter/exit actions — simple subsystem-wide commands (or a macro when you need more) applied wherever the mode just took effect.
  4. Broader mode changes prune around spaces that have their own direct mode — you never have to opt rooms out one by one.

Overview​

Modes are system-wide definitions assignable to the site (site-wide) or to any site space. When the effective mode of a scope changes, the outgoing mode's exit actions and the incoming mode's enter actions run automatically against the spaces that actually transitioned — no hand-built macros or triggers required for the common case.

Viewing Modes​

The main grid displays all configured modes with the following columns:

  • ID - Unique identifier
  • Name - Internal mode name
  • Label - Display name
  • Description - Purpose description
  • Space - The space this mode belongs to; blank is a site-wide mode
  • Default - Whether this is the fallback mode
  • Elevated - Whether changing into this mode requires an elevated role
  • Exit Elevated - Whether changing away from this mode requires an elevated role
  • Enter / Exit - Number of configured transition actions
  • Sort - Display order
  • Enabled - Whether the mode is active

Grid Actions​

  • Add - Create a new mode
  • Edit - Modify an existing mode
  • Sort - Drag to reorder modes
  • Delete - Remove a mode

A row's toolbox shows a package icon (apps icon) only on a mode an application package installed. Hovering names the package and its version; clicking opens it in Applications. Editing or deleting a mode a package installed changes what uninstalling that package removes — including the elevation flags that decide who may enter or leave it — so the icon is the warning as much as the link. A mode you created by hand shows no icon.

Creating a Mode​

  1. Click Add in the grid toolbar
  2. Configure the mode properties (see below)
  3. Click Save

Mode Information​

Name

  • Internal identifier (lowercase_with_underscores)
  • Auto-formatted on blur
  • Examples: occupied, away, night_mode, business_hours

Label

  • Human-readable display name
  • Examples: "Occupied", "Away", "Night Mode", "Business Hours"

Description

  • Optional text explaining the mode's purpose

Sort Index

  • Numeric value controlling display order in selectors and lists

Space

  • Blank means a site-wide mode — a state of the whole building, like Away or Night. Site-level panels offer it, and setting it transitions the site.
  • Pick a space to scope the mode to one room or area: Movie in the theater, Guest Privacy in the guest suite.
  • A scoped mode is offered only by panels standing in that space, or above it with child spaces included — and setting it transitions that space, not the site.
  • This is the same shape zones use: zone.site_space_id decides which panels show a zone, and a UI Zone row adds one from elsewhere.
  • Deleting the space does not promote the mode back to site-wide. It keeps the narrowing it was given, which leaves it offered on no panel until you re-scope it or clear the field — deliberate, because losing a room is not a decision to let its mode move the whole building.

Settings​

Default

  • Toggle to mark this as the fallback mode
  • The default mode is used when no mode is explicitly set anywhere
  • Only one mode should be marked as default

Requires an elevated role

  • On by default, and on for every mode that existed before this setting did
  • While on, only an elevated role may change into this mode, from anywhere
  • Turn it off to open a mode to ordinary roles — see Who may change a mode
  • Keep it on for anything that disarms security or unlocks doors

Leaving requires an elevated role

  • Off by default, so nothing changes until you turn it on
  • The setting above guards the way in; this guards the way out — while this mode is in effect, only an elevated role may change to another one
  • Turn it on for a mode that must survive a stray tap. Vacation is the case: however guarded entering it was, any mode you have opened to ordinary roles is a way back out, because a flag on the destination cannot protect the source
  • It reads the mode in effect at the scope, not the assignment, so carving a single space out of Vacation is as gated as changing it at the top
  • Re-setting the mode that is already in effect is not "leaving" and is always allowed
  • The switcher hides every other mode while such a mode is in effect, so no panel offers a tap that would be refused

Enabled

  • Toggle to enable/disable the mode
  • Disabled modes are hidden from selectors but their configuration is preserved
  • Disabling also takes the mode out of reach: every role but an elevated one is refused when setting it, including one holding an explicit set_site_mode grant. A macro or schedule can still set it — a scheduled arm must not break because someone hid its mode from the panels — and the server logs a warning when that happens

Panels​

Which UIs offer this mode in their sidebar switcher. Every UI is listed with a checkbox, and ticking one assigns the mode to that panel; the optional field beside a ticked panel renames the mode on that panel only, leaving its site-wide label alone.

These are the same UI Site Modes rows, seen from the mode's side instead of the panel's. That page answers what does this panel offer and owns the order modes appear in; this section answers who offers this mode. Either one writes the same rows, so a change made here shows up there immediately.

The Space field above already decides which panels offer the mode. Beside each panel the editor says where it stands — the space it is linked to, or site-level panel — and marks the ones that already offer this mode via their space. Those need nothing here.

Tick a panel to offer the mode somewhere it would not otherwise appear: the theater's Movie mode on the hall panel, say. It is the same job a UI Zone row does when it puts another room's zone on a panel, and it is the only way to cross space boundaries.

Assignments are written when the mode is saved, not when a box is ticked — on a new mode there is no id for a panel row to point at until it exists. A panel that is already open keeps the list it loaded until it reloads or switches UI.

Actions​

Each mode carries two action lists — On Enter and On Exit — that run automatically whenever the mode takes effect at (or leaves) a scope. Actions always apply to the transitioned spaces: the site or space the mode was set on, plus every descendant space that inherits it. Spaces with their own direct mode are untouched.

An action row is one of two shapes. Every row also has an Enabled checkbox: untick it to keep an action on the mode without running it (it is stored as "enabled": false and skipped at transition time).

Command action — a subsystem-wide command:

  • Subsystem — the zones to target (e.g. Lights, Climate, Shades)
  • Command — the verb (level, on, off, setpoint, open, close, ...)
  • Level — optional numeric value (dimmer %, setpoint, shade position)
  • Args — optional JSON for command-specific arguments (e.g. {"mode": "cool"} on a setpoint)

Macro action — a reference to an existing macro. Use this the moment you need delays, conditions, notifications, or ordering — the action list itself stays flat and immediate by design. The macro receives transition context (site_mode, site_mode_id, site_mode_direction, site_mode_scope_space_id).

If the macro you want doesn't exist yet, click the + button beside the macro picker to build it in a modal without leaving this page — the action rows you have already typed are unsaved form state and would be lost by navigating to the Macros page. The new macro is selected into the row as soon as you save it. Picking an existing macro and then clicking its name opens it in a reference modal over this page, for the same reason.

Stop when mode is left​

An On Enter macro row has a Stop when mode is left checkbox. Tick it on a long whole-house macro — a Party scene that walks every room over a couple of minutes, say — so that when someone changes their mind and picks another mode, the Party macro stops instead of running on underneath the new mode's macro and undoing its work.

When the mode is left at the site or space where it was set:

  • a run of that macro this mode started is stopped at its current step
  • a run still waiting to start (queued behind another run of the same macro) never starts
  • flagged macros further down the list that the transition hadn't reached yet are skipped
  • the new mode's actions wait (up to 10 seconds) for the stopped run to finish unwinding, so they never race a command it still had in flight

What it does not touch:

  • the same macro started any other way — a trigger, a keypad button, a schedule, another mode
  • runs started by the mode at a different scope — leaving Party in the Guest House leaves the Main House's Party alone
  • unticked actions, which behave exactly as before and run to completion
  • On Exit actions — the checkbox is only offered on enter actions

The stop is recorded on the macro's run history (reason stopped, or cancelled for a run that never started) and on the mode's Automation History entry (stopped_on_exit).

Example — "Unoccupied" setback​

On Enter:

SubsystemCommandLevelArgs
Lightslevel50
Climatesetpoint78{"mode": "cool"}
Climatesetpoint62{"mode": "heat"}

Set the site to Unoccupied and every inheriting space dims to 50% and sets back. Later, when a single space (say the guard house) leaves its own mode and falls back to Unoccupied, the same actions run again — scoped to just that space. Actions never enumerate zones, so they stay correct as zones are added.

Mode Inheritance​

Modes follow a parent-child inheritance model through the site space hierarchy:

  1. If a space has a mode directly assigned, that mode is used
  2. If no mode is assigned, the space inherits its effective mode from its parent
  3. Inheritance walks up the hierarchy until a direct assignment is found (then the site, then the default mode)
  4. A mode change at a scope only affects the spaces that resolve through it — descendants with their own direct assignment are pruned, along with their subtrees

Example​

Building (mode: business_hours)
Floor 1 (no mode → inherits business_hours)
Lobby (no mode → inherits business_hours)
Server Room (mode: always_on) ← pruned from Building-level transitions
Floor 2 (mode: quiet_hours) ← pruned from Building-level transitions
Office 201 (no mode → inherits quiet_hours)

Transitions fire on effective mode changes. Clearing a space's direct mode is a real transition too: the space falls back to its inherited (or default) mode, and that mode's enter actions run scoped to the space. Re-asserting a mode that is already in effect fires nothing.

Hold — pinning an assignment​

Hold is set per assignment (on the site or on a space), not on the mode itself — from the Mode panel in Site Spaces. A held assignment rejects mode changes and clears at that scope until the hold is released. Holding a space with no direct mode pins it to inheritance (direct assignments are rejected).

Broader transitions already skip spaces with their own direct mode, so a held space is doubly protected: the site can change modes freely around it, and nothing can change the space itself until the hold is released.

The bypass pattern​

To take a space "out of automation" (guest privacy, maintenance, commissioning):

  1. Create a mode with no enter or exit actions (e.g. bypass, guest_privacy, maintenance)
  2. Set it directly on the space
  3. Hold the assignment

The space is now pruned out of every broader mode transition, its own mode does nothing, and it can't be changed until the hold is released. For triggers that should also respect it (e.g. motion lighting), gate the trigger on the space's effective_mode attribute.

Switching from a panel​

Every end-user panel carries the mode switcher in its sidebar (menu button, top right). A Site Modes button in the sidebar footer, beside AV Scenes, opens it as a sheet that slides up over the footer; on a panel linked to a space the button is named for it (Theater Modes). The current mode is named in the sheet's header, and the modes that panel offers are rows below it, the active one marked. Tap the button again, or the sheet's close button, to put it away. The sheet and AV Scenes share the space above the footer, so opening one closes the other. The button is hidden when the panel has no mode to show.

Which modes a panel offers follows the same rule its zone list follows: what its space contributes, plus anything explicitly assigned to it. A panel linked to the theater offers the theater's modes; a panel at the site — one with no space link, or linked to the site's root space — offers the site-wide ones. UI Site Modes adds the exceptions and sets the order, and can give a mode a different label on one panel than it has site-wide.

The header names the mode in effect at that panel's scope, so a room panel reports the room's mode rather than the building's, and says which room it is naming. It renders whenever a mode resolves, even for someone who may change none of them — what is in effect is a display question, what can be changed is a permission one.

Picking a mode does not change it. The list is replaced by a confirm row — Switch to Away?, the mode's description underneath it, and Cancel / Switch — and only Switch calls the change. A mode transition runs the mode's whole enter/exit action set, which on a typical site arms or disarms security and locks or unlocks entry doors, so it is never one tap away. Closing the sheet or the sidebar drops an unconfirmed pick.

A mode's own scope decides what a transition changes, not the panel it was tapped on. An unscoped mode sets the site from anywhere; a mode scoped to the guest suite sets that space, whether it was tapped on the guest panel or on the main one. The two cannot drift: the same field decides where a mode is offered and what it moves, so a mode that appears on one room's panel can never quietly transition the building. Spaces with their own direct assignment are pruned from the transition as always (see Mode Inheritance), and a held assignment rejects the change; the panel reports the failure in a toast and the displayed mode stays where it was.

The list is filtered to what the person signed in can actually set, so a row that would refuse on tap is never offered — see below. The list disappears when nothing is left, which on a site with no enabled modes, or for a user who may set none of them, leaves only the header naming the mode in effect; with no mode in effect either, the footer button is not shown at all. The mode shown is re-read whenever the sidebar opens, so a change made by a schedule, a macro or another panel is picked up there.

Who may change a mode​

Four tiers, checked in order. The first that applies decides.

1. An elevated role sets anything. Any mode, at any scope. This is the role's is_elevated flag, not the session's — a wall panel signed in with a PIN keeps the authority its role carries, the same trade the physical surface makes everywhere else. Mode changes are what wall panels are for. This is the only tier that skips everything below.

2. Two rules about the modes themselves bind everyone else — the explicit grant in tier 3 included, because a kiosk is exactly who they exist to stop:

  • A disabled mode is refused. It is invisible in every switcher, so reaching it at all means a request built by hand.
  • A mode flagged Leaving requires an elevated role refuses every change away from it. This is the exit half of the question: Requires an elevated role decides who may enter the mode being set, this decides who may leave the one already in effect, and only the second can keep a kiosk from dropping the site out of Vacation. It reads the mode in effect at the scope being set, so an inheriting space is as guarded as the one that supplied the mode.

3. A role explicitly granted set_site_mode sets anything else. Naming the event in a role's allow list (rather than reaching it through allow api *) is a per-event decision an administrator made, and it is what kiosk roles run on. It predates the per-mode rules and is otherwise carried forward unchanged.

4. Everyone else must satisfy all three:

  • the mode is not marked Requires an elevated role, and
  • the change is aimed at the mode's own scope — its space, or the site for a site-wide mode, and
  • the mode is offered by a UI that role can reach — its space, or a UI Site Modes assignment.

Because is_elevated defaults true, an upgrade changes nothing: every mode that already existed still requires an elevated role, which is exactly who could set one before. Opening a mode to ordinary roles is two deliberate steps — turn the flag off, then make sure a panel those roles can reach offers it, through the mode's Space or an explicit assignment.

The UI check is the union across every UI the role allows, not the panel the request came from: a person who can reach the theater panel and the hall panel may set either one's modes from either one.

Unlike command scope, this half does not fail open on a UI that expresses nothing — it does not need to. A mode already carries its own scope, so a panel with no assignments is not an unanswered question: it offers what its space gives it, which for a site-level panel is every site-wide mode. A non-elevated role is also held to the mode's own scope when setting it, so a room's mode cannot be aimed at the site.

A mode scoped to a space nobody's panel stands in is therefore reachable only by an elevated role, or by a macro or schedule. That is a useful shape for a mode that should only ever run unattended.

Only set_site_mode works this way. Clearing a mode and holding an assignment stay elevated-role-only for everyone: clearing drops the scope to its inherited-or-default mode, so the mode it lands on is not the one named in the request, and a hold blocks every future transition including the scheduled arm.

Macros, schedules and triggers run server-side with no invoker, so none of this applies to them — that is the escape hatch for giving a restricted role one specific transition. Gate the macro itself if that matters.

Attributes​

Mode state is mirrored onto attributes so triggers, widgets, and the AI can react to it:

AttributeTargetMeaning
modesite / site_spaceThe direct assignment (empty when inheriting)
effective_modesite / site_spaceThe resolved mode — direct, inherited, or default. Use this in triggers that should react to inherited changes.

Database Schema​

ColumnTypeDescription
idINTEGERPrimary key
nameSTRINGInternal name (required)
labelSTRINGDisplay name
descriptionSTRINGOptional description
is_defaultBOOLEANFallback mode flag (default: false)
is_elevatedBOOLEANChanging into this mode requires an elevated role (default: true)
exit_is_elevatedBOOLEANChanging away from this mode requires an elevated role (default: false)
enter_actionsJSONAction entries run when the mode takes effect
exit_actionsJSONAction entries run when the mode is left
site_space_idINTEGERSpace this mode belongs to; NULL is a site-wide mode
sort_indexINTEGERDisplay order
enabledBOOLEANActive state (default: true)

Hold lives on the assignment: site.mode_hold and site_space.mode_hold. Panel assignments live in ui_site_mode (one row per UI × mode, with the optional per-panel name override) — see UI Site Modes.

Action entries are JSON objects in one of two shapes:

{ "subsystems": ["lights"], "command": "level", "level": 50, "args": {} }
{ "macro_id": 42 }
{ "macro_id": 43, "stop_on_exit": true }

stop_on_exit is optional on an enter-action macro entry; absent means the macro runs to completion as it always has. See Stop when mode is left.

Integration with Automation​

Enter/exit actions cover the common case. For everything else:

Triggers​

Create triggers on the mode or effective_mode attributes (site or site_space) — e.g. fire when a space's effective_mode becomes away. Prefer effective_mode so inherited changes are seen.

Macros​

  • The Set Site Mode macro step sets or clears a mode on the site or a space
  • A macro referenced from an action list receives the transition context and can branch on it

Observability​

Every transition is logged to site_mode_history — including hold, release, and clear events at a scope with no direct mode assigned (those rows record an empty mode) — and every action run is logged to Automation History (artifact type site_mode), including the zone counts dispatched and any errors.

Best Practices​

  1. Keep it Simple: Start with a small set of modes (occupied, away, night) and add more as needed
  2. Prefer actions over hand-built macros: Use the action lists for subsystem-wide changes; reach for a macro action only when you need delays or conditions
  3. Use Hold deliberately: Hold pins one assignment — release it when the exception is over
  4. One Default: Ensure exactly one mode is marked as default
  5. Clear Labels: Use descriptive labels that are obvious to end users
  6. Trigger on effective_mode: The mode attribute is empty on inheriting spaces — effective_mode is the one that always resolves
  • Site Spaces - Assigning modes to spaces, holds, inheritance chain
  • UI Site Modes - The same panel assignments, edited from the panel's side
  • Triggers - Automating responses to mode changes
  • Macros - Automation sequences