Skip to main content

Attributes

Attributes are key-value pairs that store configuration, state, and metadata for all entities in GEM. They provide a flexible, extensible way to add custom properties to subsystems, devices, zones, and other system objects.

Overview

The Attributes page provides a unified interface for viewing and managing attributes across all system targets. Attributes can store configuration values, runtime state, device settings, and custom metadata.

Attribute Registry

GEM maintains an Attribute Registry — a catalog of known attributes for each system target and driver. When editing attributes on a device or zone, the registry provides:

  • Auto-complete — the attribute name field suggests registered attributes relevant to the entity's driver.
  • Auto-fill — selecting a registered attribute auto-fills the value type, history, secure, and readonly flags.
  • Descriptions — registered attributes show a description hint and unit below the name.
  • Driver context — attributes are filtered by the entity's driver inheritance chain (e.g., a lutron_qsx device sees attributes from lutron_qsx, lutron_base, and core). Cross-cutting targets without a driver (e.g., ui, site, site_space) accept attributes from any integration and are shown the full registry for that target.

The registry is auto-generated from a codebase scan (scripts/register_attributes.js) and seeded into the database on startup. Manual edits to descriptions, history flags, and secure flags in the seed file are preserved across re-scans.

Viewing Attributes

The main grid displays attributes filtered by system target with the following columns:

  • ID - Unique identifier
  • Target - System target type (zone, device, subsystem, etc.)
  • Target ID - ID of the specific entity
  • Target - Human-readable name of the target entity (computed)
  • Name - Attribute name
  • Value - Current value
  • Previous Value - Last value before most recent change
  • Value Type - Data type (string, bool, int, float, date, json)
  • Read Only - Whether the attribute can be modified
  • History - Whether value changes are logged

Filtering by System Target

Before viewing attributes, select a System Target from the dropdown:

  • subsystem - Subsystem attributes
  • device - Device attributes
  • zone - Zone attributes
  • macro - Macro attributes
  • ui - UI attributes
  • user - User attributes
  • system - System-wide settings
  • variable - Virtual variables
  • And many more...

The grid automatically loads attributes for the selected target type.

Grid Actions

  • Add - Create a new attribute
  • Edit - Modify an existing attribute
  • Delete - Remove an attribute (warning: may affect functionality)

Note: Some system attributes are read-only and cannot be modified or deleted.

Attribute Editor

The inline attribute editor (used on device, zone, and other detail pages) uses a click-to-edit pattern:

  • Attributes display in a compact read-only table with name, truncated value, type badge, and toggle switches for Read Only, History, and Secure.
  • Double-click any row (or click the edit icon) to enter edit mode for that row. The row highlights and expands with full input fields.
  • Click Save (checkmark) to save that single row, or Cancel to discard changes.
  • The Read Only, History, and Secure toggles auto-save immediately when clicked — no need to enter edit mode.
  • Click Add to add a new attribute (opens in edit mode with the registry-aware name selector).
  • Click Save All to batch-save all pending changes across rows.
note

When Live Values polling is active, all rows are locked to read-only mode. Disable live values to edit attributes.

Creating an Attribute

To create a new attribute:

  1. Select the System Target (e.g., zone)
  2. Click Add in the grid toolbar
  3. Configure the attribute:
    • System Target - Auto-filled from selection
    • Target ID - Select the specific entity
    • Name - Attribute name (lowercase_with_underscores). The dropdown suggests registered attributes for the entity's driver.
    • Value - Initial value (auto-filled from registry default if available)
    • Value Type - Data type (auto-filled from registry)
    • Read Only - Check to prevent modifications
    • History - Check to log all value changes
  4. Click Save

Attribute Properties

Name

Attribute names follow the GEM naming convention:

  • Lowercase letters, numbers, and underscores only
  • Descriptive and clear
  • Examples: ip_address, default_level, color_temp

Value Types

GEM supports six data types:

string

  • Text values
  • Examples: "Living Room", "192.168.1.100", "HDMI 1"
  • No type conversion

bool

  • Boolean values
  • Stored as: true/false, 1/0, on/off
  • Normalized to true or false

int

  • Integer numbers
  • Examples: 100, -50, 0
  • No decimal places

float

  • Decimal numbers
  • Examples: 72.5, -10.25, 3.14159
  • Supports scientific notation

date

  • Timestamps
  • Stored in ISO 8601 format
  • Examples: "2024-01-15T14:30:00Z"
  • Automatically converted to local timezone

json

  • Complex structured data
  • Stored as JSON objects or arrays
  • Examples:
    {"red": 255, "green": 128, "blue": 0}
    ["HDMI1", "HDMI2", "Component"]

Read Only

Read-only attributes cannot be modified through the admin interface:

  • System-calculated values
  • Device-reported states
  • Protected configuration

Examples:

  • firmware_version
  • connection_state
  • last_seen

Value Options

Define a fixed set of allowed values for an attribute. When value options are set, the attribute editor and trigger condition builder show a dropdown instead of a free-text input.

  • Available for all types except bool (which already has true/false)
  • Add options one at a time in the attribute creator
  • Each option appears as a removable tag
  • Users can still enter custom values (fill-in allowed)

Use cases:

  • Restrict a mode attribute to home, away, vacation
  • Limit an input attribute to known source names
  • Constrain a color_temp attribute to preset values

Dynamic Option Source

Some registered attributes pull their dropdown choices live from elsewhere in the system instead of from a static value_options list. When a registry entry declares an option_source, the attribute editor replaces the free-text input with a SelectSearch picker whose items are resolved on demand and the read-only display shows the matching label instead of the raw stored id.

Sources are one of:

  • command — runs a command on a device (located by device_id, by a sibling attribute, or by a device_filter like {driver: 'lutron_qsx'}) and maps the response into picker items.
  • query — queries a model (zone, device, macro, ui_page, …) with optional filters.
  • settings — reads a list/object from the global settings tree.
  • static — a fixed array embedded in the registry entry.

Option sources are resolved client-side, cached for the session, and shared between the AttributeEditor and the widget configuration form so the same descriptor works in both places. They're defined in lib/attribute_registry_seed.js and survive re-scans.

Metric Role

Power and energy attributes can carry a metric_role tag (e.g. power.solar, power.grid, power.battery, power.load, battery.soc) that maps a driver's vendor-specific attribute name onto a shared, canonical concept. This lets a single generic dashboard read heterogeneous drivers — production_now_w (Enphase), pv_power (SolarEdge) and solar_power_w (Tesla) all resolve to power.solar — without per-driver code. A companion metric_sign: 'inverted' flag flips the value when a driver's native sign is the opposite of the canonical convention.

These tags are set in the seed file (not the attribute editor) and are consumed by the Power Flow widget. See Power Management for the full role list, sign conventions, and how to tag a new driver.

History

Enable history to log all value changes:

  • Use cases:

    • Security and compliance
    • Troubleshooting
    • Analytics and reporting
    • Behavior analysis
  • Performance impact:

    • Minimal for infrequent changes
    • Moderate for frequent changes (e.g., temperature sensors)
    • High for very frequent changes (e.g., motion sensors)

Enable history only for attributes where historical data is valuable.

View attribute history at Insights > Attribute History.

Common Attribute Categories

Device Attributes

Network Configuration:

  • ip_address - Device IP address (string)
  • port - Network port (int)
  • mac_address - Physical MAC address (string)
  • hostname - DNS hostname (string)

Authentication:

  • username - Login username (string)
  • password - Login password (string, auto-encrypted)
  • api_key - API authentication key (string, auto-encrypted)
  • token - Access token (string, auto-encrypted)

Serial Configuration:

  • baud_rate - Serial baud rate (int)
  • parity - Parity setting (string: none/even/odd)
  • data_bits - Data bits (int: 7 or 8)
  • stop_bits - Stop bits (int: 1 or 2)
  • delimiter - Message delimiter (string)

Runtime State:

  • power_state - Current power status (string: on/off)
  • connection_state - Connection status (string: connected/disconnected)
  • firmware_version - Device firmware version (string, read-only)
  • uptime - Device uptime in seconds (int, read-only)

Zone Attributes

State:

  • power - Power state (string: on/off)
  • level - Brightness/volume/position (int: 0-100)
  • input - Selected input source (string)
  • mute - Mute state (bool)
  • temperature - Current temperature (float)
  • setpoint - Target temperature (float)

Color (RGB/RGBW):

  • color - RGB hex color (string: #RRGGBB)
  • hue - Hue (int: 0-360)
  • saturation - Saturation (int: 0-100)
  • brightness - Brightness (int: 0-100)
  • color_temp - Color temperature in Kelvin (int: 2000-6500)

Limits:

  • min_level - Minimum level (int: 0-100)
  • max_level - Maximum level (int: 0-100)
  • default_level - Default on level (int: 0-100)

Behavior:

  • ramp_rate - Fade/transition time in seconds (float)
  • on_delay - Delay before turning on (int, milliseconds)
  • off_delay - Delay before turning off (int, milliseconds)

Relay Control:

  • normally_closed - Invert relay logic (bool)
  • relay_states - Custom state mapping (json)

Subsystem Attributes

UI Configuration:

  • icon - Icon name for UI display (string)
  • color - Theme color (string: #RRGGBB)
  • sort_index - Display order (int)

Behavior:

  • enabled - Subsystem active state (bool)
  • default_level - Default level for all zones (int)

System Attributes

System-wide settings stored on the system target:

  • system_name - Installation name (string)
  • timezone - System timezone (string)
  • geo_latitude - Latitude for astronomical calculations (float)
  • geo_longitude - Longitude for astronomical calculations (float)
  • db_maintenance_enabled - Enable automatic database cleanup (bool)
  • db_retention_days - Days to retain historical data (int)

UI Attributes

User interface configuration:

  • theme - UI theme name (string)
  • layout - Layout configuration (json)
  • widgets - Widget configuration (json)

User Attributes

User preferences and settings:

  • email - Email address (string)
  • phone - Phone number (string)
  • notification_preferences - Notification settings (json)
  • language - Preferred language (string)

Secure Attributes

Certain attributes are automatically encrypted for security:

Auto-Detected Names

Attributes with these names are encrypted:

  • password
  • api_key
  • private_key
  • secret
  • token
  • passphrase

Encryption Details

  • Algorithm: AES-256-GCM
  • Key Storage: .encryption_key file (not in version control)
  • Format: gem-crypt:iv:authTag:encrypted
  • Transparency: Automatic encryption/decryption via Sequelize hooks

Manual Encryption

Force encryption for custom sensitive attributes:

await gem.setAttribute('device', deviceId, 'my_secret', 'sensitive_value', 'string', {secure: true});

Key Management

Encryption Key Backup:

  1. Navigate to System > Backup & Restore
  2. Download encryption keys
  3. Store securely (password manager, encrypted cloud storage)

Key Restoration: Required when restoring backups to new hardware. Upload encryption keys file in the Backup & Restore page.

Accessing Attributes Programmatically

JavaScript (Macros, Drivers)

// Get attribute value
let value = await gem.getAttribute('zone', zoneId, 'brightness');

// Set attribute value
await gem.setAttribute('zone', zoneId, 'brightness', 75, 'int');

// Get multiple attributes
let attrs = await gem.getAttributes('device', deviceId);
console.log(attrs.ip_address, attrs.port);

// Delete attribute
await gem.deleteAttribute('zone', zoneId, 'old_attribute');

REST API

# Get attribute
GET /api/data/attribute?system_target=zone&target_id=123&name=brightness

# Set attribute
POST /api/data/attribute
{
"system_target": "zone",
"target_id": 123,
"name": "brightness",
"value": 75,
"value_type": "int"
}

# Delete attribute
DELETE /api/data/attribute/{id}

WebSocket

// Get attribute
socket.emit('get_attribute', {
system_target: 'zone',
target_id: 123,
name: 'brightness'
}, (result) => {
console.log('Brightness:', result.value);
});

// Set attribute
socket.emit('set_attribute', {
system_target: 'zone',
target_id: 123,
name: 'brightness',
value: 75,
value_type: 'int'
}, (result) => {
if (result.error) {
console.error('Error:', result.error);
}
});

Attribute Triggers

Attributes can trigger automation when their values change. See Triggers for details.

Example use cases:

  • Turn on lights when motion sensor goes high
  • Send alert when temperature exceeds threshold
  • Activate scene when security system arms
  • Sync attributes across multiple devices

Best Practices

  1. Naming: Use clear, descriptive names that indicate purpose

  2. Type Selection: Choose the most specific type:

    • Use int for whole numbers
    • Use float for decimals
    • Use bool for true/false
    • Use json for structured data
  3. History: Enable only when needed:

    • Enable for security-critical attributes
    • Enable for troubleshooting key values
    • Disable for high-frequency updates
  4. Read-Only: Mark calculated or device-reported attributes as read-only

  5. Documentation: Use descriptive names instead of needing separate documentation

  6. Defaults: Store default values as attributes rather than hardcoding

  7. Organization: Group related attributes with common prefixes:

    • color_* for color properties
    • limit_* for constraints
    • state_* for runtime state
  8. Validation: Validate values before setting:

    if (level >= 0 && level <= 100) {
    await gem.setAttribute('zone', zoneId, 'level', level, 'int');
    }
  9. Security: Never log or expose secure attributes

  10. Cleanup: Delete unused attributes periodically

Dynamic Attribute Values

Dynamic attribute values use bracket expressions to reference other attributes, variables, or cross-entity values at runtime. They are resolved in macro steps, trigger conditions, and scheduled macros.

Syntax

All dynamic values start with [ and end with ], optionally followed by arithmetic and clamping.

Local Attribute Reference

[level] → value of 'level' on the current entity
[brightness]+20 → brightness + 20

Variable Reference

[$sunrise] → value of the 'sunrise' system variable
[$brightness]+10 → brightness variable + 10

Cross-Entity Reference

[zone.5.level] → level attribute of zone 5
[device.12.temperature] → temperature attribute of device 12

Arithmetic Operators

Append an operator and operand after the closing bracket:

OperatorExampleResult
+[level]+20level + 20
-[level]-10level - 10
*[level]*2level × 2
/[level]/3level ÷ 3

Clamping

Constrain the result to a range with :min:max:

[level]+50:0:100 → add 50, clamp between 0 and 100
[level]*3:0:200 → multiply by 3, clamp between 0 and 200
[level]:0:50 → clamp raw value between 0 and 50 (no operator)

Date Arithmetic

For date type values, the offset is in minutes:

[$sunrise]+30 → 30 minutes after sunrise
[$sunset]-15 → 15 minutes before sunset

Dynamic Value Builder

The macro step editor includes a Dynamic Value Builder dialog for constructing dynamic expressions visually. Click the settings icon next to a dynamic parameter to open it. The builder supports:

  • Static — plain literal value
  • Local Attribute — reference an attribute on the current entity
  • Cross-Entity — pick a zone or device and its attribute
  • Variable — select a system variable

Configure optional arithmetic operator, operand, and clamping, then click Apply to insert the expression.

Advanced Topics

Computed Attributes

Create virtual attributes calculated from other values:

// In a driver or macro
let totalPower = zone1.power + zone2.power + zone3.power;
await gem.setAttribute('variable', 0, 'total_power', totalPower, 'float');

Attribute Synchronization

Keep attributes in sync across entities:

// Trigger when master zone level changes
socket.on('attribute_change', async (data) => {
if (data.name === 'level' && data.target_id === masterZoneId) {
// Sync to slave zones
for (let slaveId of slaveZones) {
await gem.setAttribute('zone', slaveId, 'level', data.value, 'int');
}
}
});

JSON Attribute Schemas

Structure complex JSON attributes:

{
"scenes": {
"movie": {"brightness": 20, "color_temp": 2700},
"reading": {"brightness": 80, "color_temp": 4000},
"party": {"brightness": 100, "color": "#FF00FF"}
}
}

Access with:

let attrs = await gem.getAttributes('zone', zoneId);
let scenes = JSON.parse(attrs.scenes || '{}');
let movieScene = scenes.movie;

Attribute Migrations

When restructuring attributes:

  1. Create new attributes with new naming
  2. Copy values from old to new
  3. Update all references
  4. Delete old attributes
  5. Document the change

Troubleshooting

Attribute Not Saving

  1. Check Type: Verify value matches the value_type
  2. Check Read-Only: Read-only attributes cannot be modified
  3. Check Permissions: Verify user has attribute write permission
  4. Review Logs: Check for validation errors

Attribute Not Updating

  1. Check Subscriptions: Ensure clients are subscribed to updates
  2. Review Triggers: Conflicting triggers may override values
  3. Check Device: Device may not be sending feedback
  4. Verify Response Set: Response parsing may be incorrect

History Not Saving

  1. Check History Flag: Verify history is enabled for the attribute
  2. Check Retention: Old history may be pruned based on retention settings
  3. Review Performance: High-frequency updates may be throttled

Encryption Issues

  1. Missing Key: Encryption key file must exist
  2. Wrong Key: Restoring backups requires original encryption key
  3. Key Permissions: Verify file permissions on .encryption_key