Skip to main content

UI Controls

UI Controls are navigation buttons and pages that appear in the main navigation of each UI. They determine which control pages (Lighting, AV, HVAC, etc.) are accessible from each user interface.

Overview

UI Controls allow you to:

  • Customize which control pages appear in each UI
  • Create UI-specific controls (hide irrelevant controls)
  • Configure control icons and labels
  • Reorder navigation buttons
  • Set PIN protection for specific controls

Viewing UI Controls

The page has two tabs: List and Select.

List Tab

The main grid displays all UI controls with the following columns:

  • ID - Unique identifier
  • Label - Display text on navigation button
  • Component - Svelte component path
  • UI - UI this control belongs to (null = global)
  • Icon - Icon filename
  • PIN - Whether PIN is required to access
  • Enabled - Whether the control is active
  • Sort Index - Display order

Grid Actions

  • Add - Create a new UI control
  • Delete - Remove a UI control
  • Sort - Reorder controls by dragging rows

Quick Actions

  • Duplicate Icon - Copy an existing control

Understanding Global vs. UI-Specific Controls

Global Controls (UI = null)

  • Appear in ALL UIs by default
  • Cannot be removed from a specific UI
  • Include standard controls: Lighting, Audio, Video, Climate

UI-Specific Controls (UI = specific ID)

  • Appear only in the assigned UI
  • Override global controls when present
  • Allow per-UI customization

Hiding Global Controls

To hide a global control from a specific UI:

  1. Click Duplicate icon on the global control
  2. Set UI to the target UI ID
  3. Set Enabled = No
  4. Save

Result: The disabled UI-specific control overrides the global control, effectively hiding it from that UI.

Tip: A tooltip on the List tab explains this: "To hide a global control, copy it, add it to a specific UI, then disable it"

Space-Linked UIs

When a UI has site_space_id set, its control list is auto-derived from the subsystems present in the linked Site Space (and descendants if include_child_spaces is on). ui_control rows on a space-linked UI are still honored as overlays:

  • A row with a new component adds a control on top of the inherited set.
  • A row with the same component as an inherited control and enabled = false suppresses that inherited control.

The Select tab shows a banner reminding you of this when a space-linked UI is selected.

Select Tab

The Select tab provides a quick way to add standard controls to a UI:

Workflow

Left Side - Available Controls:

  • Lists all subsystem-based controls
  • Includes: Lighting, Shades, Security, HVAC, etc.
  • Plus special controls: Audio, Video

Center - Action Buttons:

  • Add ▶ - Add selected controls to UI
  • ◀ Remove - Remove selected controls from UI

Right Side - Current UI Controls:

  • Shows controls already assigned to selected UI
  • Sorted by sort_index

Using the Select Tab

  1. Select a UI from the dropdown at the top
  2. Choose controls from the left list (multi-select)
  3. Click Add ▶ to add them to the UI
  4. Or select existing controls on the right and click ◀ Remove

Component Path: Controls are automatically mapped to /controls/{subsystem_lowercase}

Example:

Lighting → /controls/lighting
Audio → /controls/audio
Shades → /controls/shades

Control Configuration

Basic Properties

Label

  • Text shown on navigation button
  • Examples: "Lighting", "Audio", "Climate", "Cameras"
  • Can be customized per UI

Component

  • Svelte component path
  • Must start with /
  • Standard format: /controls/{name}
  • Custom components: /controls/custom_control

UI

  • Leave blank for global control (all UIs)
  • Select specific UI for UI-only control
  • Use for UI customization

Icon

  • Icon filename (without extension)
  • Located in theme's /icons/ directory
  • Examples: lighting, audio, shades, security
  • If not set, defaults based on component name

PIN

  • Require PIN entry before accessing control
  • Useful for:
    • Parental controls
    • Secure controls (security system)
    • Administrative functions

Enabled

  • Toggle to show/hide control
  • Disabled controls don't appear in navigation
  • Configuration preserved

Sort Index

  • Display order in navigation
  • Lower numbers appear first
  • Drag rows in the grid, then click the Save Sort Order button (swap-sort icon) in the toolbar to renumber

Common Use Cases

Adding Standard Controls to a UI

Using Select tab:

  1. Select UI: kitchen_panel
  2. Select controls: Lighting, Shades, Climate
  3. Click Add ▶
  4. Controls appear in kitchen panel navigation

Creating Custom Control

  1. Switch to List tab
  2. Click Add
  3. Configure:
    Label: Security
    Component: /controls/security
    UI: master_bedroom_panel
    Icon: shield
    PIN: Yes (require PIN)
    Enabled: Yes
  4. Save

Hiding Global Control from Specific UI

To hide "Video" from guest panel:

  1. Find "Video" global control in list
  2. Click Duplicate icon
  3. In the copy, set:
    UI: guest_panel
    Enabled: No
  4. Save
  5. Video control no longer appears in guest_panel

Reordering Controls

Using List tab:

  1. Enable Sort action
  2. Drag controls to desired order
  3. Sort index updates automatically
  4. Changes take effect immediately in UIs

Or using Select tab (right side):

  1. Select a control from the right list
  2. Use ▲ ▼ buttons to move up/down
  3. Sort index updates automatically

PIN-Protected Controls

For secure access to certain controls:

  1. Edit the control (e.g., "Security")
  2. Set PIN: Yes
  3. Save
  4. When users click the control:
    • PIN prompt appears
    • Must enter valid PIN (from user account)
    • On success, control opens
    • On failure, access denied

Control Components

Standard Control Components

GEM includes built-in control components:

/controls/lighting

  • Zone grid for lighting control
  • Supports on/off, dimming, color
  • Scene buttons if configured

/controls/audio

  • Audio zone control
  • Volume, input selection, transport
  • Multi-room audio grouping

/controls/video

  • Video zone control
  • Source selection, display control
  • AV matrix routing

/controls/shades

  • Shade position control
  • Open, close, stop, presets
  • Group control

/controls/climate

  • Thermostat control
  • Temperature, mode, fan
  • Multi-zone HVAC

/controls/security

  • Alarm panel interface
  • Arm, disarm, status
  • Zone bypass

/controls/cameras

  • Camera feeds
  • PTZ control
  • Recording playback

/controls/garage

  • Garage door control for the garage subsystem — All / None selection, then raise or close the selected doors
  • Handles two opener styles automatically per zone:
    • Pulse-relay doors (a single momentary contact that toggles the door) — raise/close only fire when the door isn't already where you want it, and press-and-hold the raise/close button forces a pulse regardless of the sensed state (escape hatch for a wrong door sensor)
    • Discrete openers (separate open/close/stop, e.g. Konnected) — raise/close send the verb directly and idempotently (no toggle guard); a Stop button appears whenever any door in the fleet supports a real mid-travel stop
  • Opener style is detected from the zone's open_action / close_action / stop_action attributes — discrete openers carry these (stamped by their driver), pulse-relay doors do not and fall back to pulse. See Command Overrides
  • Renders an interactive zone map when garage zones are placed on a map (see UI Themes → Zone Maps); otherwise falls back to an inline camera feed alongside a row of labeled zone-select buttons, one per door
  • Each zone-select button shows the door's live status as a colored badge below its label — opening / closing in blue while the door is travelling (from the zone's operation attribute), open in amber (worth noticing), and closed in green (secured). Relay-only doors that don't report an operation show just open/closed
  • The inline camera feed is sourced from the camera_zone attribute on the garage subsystem
  • The camera-feed fallback is orientation-aware — the camera occupies half the width in landscape and the full width in portrait

/controls/doors

  • Door and lock control for the door subsystem — a grid of zone-select tiles (one per door or lock) alongside the selected zone's full control panel
  • Each tile shows the door's live state and battery level as a colored badge below its label, updated in real time via zone subscriptions:
    • closed / locked in green (secured)
    • open / unlocked / ajar in amber (worth noticing)
    • opening / closing / moving in blue (in motion)
    • fault / alarm / error / offline in red
    • any other state falls back to the generic status colors
  • When a zone reports a battery level it is appended to the badge as a percentage (e.g. closed - 87%)
  • This live badge now renders for every subsystem that uses the generic zone-grid control (doors, gates, covers, power, water, fire, lift, fans, …), driven by each zone's state and battery (battery_level / battery) attributes via live subscriptions. A zone that reports neither simply shows a plain label, so subsystems whose zones don't publish state are unaffected

/controls/water

  • Water management control
  • Leak sensors, shut-off valves
  • Flow monitoring

/controls/weather

  • Weather station data
  • Temperature, humidity, wind
  • Forecast display

/controls/pool

  • Pool equipment control
  • Temperature, pumps, lights
  • Spa control

/controls/spaces

  • Drill-down tile grid for child site spaces
  • Auto-included in space-linked UI menus when the bound space has children with their own UIs (or descendants further down that do)
  • Tile behavior:
    • Leaf tile — child has its own UI. Tapping navigates to that UI.
    • Drill-down tile (label ends with ) — child has no UI of its own but a descendant does. Tapping descends into that child and re-loads the tile grid from its children.
  • A breadcrumb with a ‹ Back button appears once you've drilled in, popping one level at a time back to the original UI's space

Custom Control Components

Create custom control components:

  1. Develop Svelte component in src/components/controls/
  2. Add route in src/routes/controls/
  3. Create UI control pointing to the component
  4. Assign to UI

Example Custom Control:

<!-- src/routes/controls/outdoor_audio.svelte -->
<script>
import GemApp from '../../gem/app';
// Custom outdoor audio control logic
</script>

<div class="outdoor-audio-control">
<!-- Custom UI for outdoor audio zones -->
</div>

Then create UI control:

Label: Outdoor Audio
Component: /controls/outdoor_audio
Icon: speaker_outdoor

Icons

Icons are stored in the theme's /icons/ directory:

Standard Icons

  • lighting - Light bulb
  • audio - Speaker
  • video - TV/display
  • shades - Window blinds
  • climate - Thermometer
  • security - Shield
  • camera - Camera
  • pool - Pool
  • irrigation - Sprinkler
  • lock - Padlock

Custom Icons

Upload custom icons via UI > UI Themes page:

  1. Navigate to UI > UI Themes
  2. Select theme
  3. Go to Icons tab
  4. Upload PNG or SVG files
  5. Reference by filename in UI Control

Icon Requirements:

  • Format: PNG or SVG
  • Size: 64x64 to 128x128 pixels
  • Style: Should match theme aesthetic
  • Filename: lowercase_with_underscores.png

Best Practices

  1. Consistent Labeling: Use clear, recognizable names for controls

  2. Logical Ordering: Arrange controls by frequency of use:

    • Most used first (Lighting, Audio)
    • Moderate use middle (Climate, Shades)
    • Least used last (Pool, Irrigation)
  3. Icon Selection: Choose icons that clearly represent the control function

  4. Global Defaults: Use global controls for controls that should appear everywhere

  5. UI Overrides: Use UI-specific controls sparingly, only when truly needed

  6. PIN Protection: Only PIN-protect controls that need security:

    • Security system
    • Administrative functions
    • Potentially dangerous controls (gates with traffic)
  7. Testing: Test controls after adding to verify component exists and loads

  8. Enabled State: Disable rather than delete during troubleshooting

Troubleshooting

Control Not Appearing

Check:

  1. Enabled: Control must be enabled
  2. UI Assignment: Control is global OR assigned to this UI
  3. Component Exists: Svelte component file exists at path
  4. UI Enabled: Parent UI must be enabled
  5. Role Permission: User's role allows access to this UI

Control Shows Error

Check:

  1. Component Path: Must start with /
  2. Component Exists: File exists at src/routes/controls/{name}.svelte
  3. Syntax Errors: Component has valid Svelte syntax
  4. Console Errors: Check browser console for runtime errors

Wrong Icon Displays

Check:

  1. Icon Name: Matches file in theme's /icons/ directory
  2. Theme: Correct theme assigned to UI
  3. File Extension: Don't include .png or .svg in icon name
  4. Browser Cache: Clear cache and reload

PIN Not Working

Check:

  1. User PIN: User has PIN set in user account
  2. PIN Match: Entered PIN matches user PIN
  3. Case Sensitivity: PINs are typically numeric (no case)

Duplicate Not Working

Cause: Duplicate creates a copy but doesn't auto-save

Solution: After clicking duplicate, configure the new control and save explicitly

Advanced Topics

Conditional Controls

Show/hide controls based on system state:

Not directly supported in UI Controls page. Implement via:

  1. Custom control component with conditional display
  2. JavaScript in theme
  3. Macro that enables/disables controls

Dynamic Control Counts

Display count badges on controls:

Example: Show number of lights that are on

Implement in control component:

let onCount = zones.filter(z => z.power === 'on').length;

Control Templates

For installations with many similar UIs:

  1. Create template UI with all desired controls
  2. Duplicate UI
  3. Modify specific controls as needed
  4. Saves time vs. configuring from scratch
  • UIs - Managing user interfaces
  • UI Zones - Assigning zones to controls
  • UI Themes - Icon management
  • Roles - Controlling access to controls