Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/korapp/plasma-homeassistant/llms.txt

Use this file to discover all available pages before exploring further.

The entity model provides JavaScript classes for representing Home Assistant entities in the plasmoid. It includes runtime entity data (Entity) and configuration entity data (ConfigEntity).

Overview

The model is implemented as an ES6 JavaScript module that exports entity classes and utility functions. Location: package/contents/code/model.mjs Type: JavaScript ES Module Exports:
  • Entity - Runtime entity with live state data
  • ConfigEntity - Configuration entity with action definitions

Entity Class

Represents a Home Assistant entity with its current state and computed properties.

Constructor

function Entity(
    {entity_id, name, icon, state, attribute, attributes, unit, default_action, scroll_action},
    data
)
entity_id
string
default:"''"
Home Assistant entity ID (e.g., "light.bedroom", "sensor.temperature")
name
string
Custom display nameFalls back to attributes.friendly_name if not provided
icon
string
Custom icon nameFalls back to attributes.icon if not provided. Supports Material Design Icons (mdi:) and Plasma icons
state
string
Initial/default state valueOverridden by data.s if provided
attribute
string
default:"''"
Attribute name to display instead of stateWhen set, displays the value of attributes[attribute] instead of the state value
attributes
object
Initial attributes objectMerged with data.a to create final attributes. Common attributes:
  • friendly_name: Display name
  • icon: Icon identifier
  • unit_of_measurement: Unit string
  • Domain-specific attributes (brightness, temperature, etc.)
unit
string
Custom unit stringFalls back to attributes.unit_of_measurement if not provided
default_action
object
default:"{}"
Service call configuration for click actionStructure:
{
  domain: "light",
  service: "toggle",
  target: {entity_id: "light.bedroom"},
  data_field: "brightness"  // optional
}
scroll_action
object
default:"{}"
Service call configuration for scroll action (number fields)Same structure as default_action
data
object
default:"{}"
Live state update from Home AssistantProperties:
  • s: New state value
  • a: Updated attributes object
This parameter is used when updating an existing entity with new state data

Properties

All Entity instances have the following properties:
entity_id
string
The entity’s unique identifier
state
string
Current state value (merged from initial state and data.s)
attributes
object
Merged attributes from configuration and live data
name
string
Display name, resolved from custom name or attributes.friendly_name
icon
string
Icon identifier, resolved from custom icon or attributes.icon
unit
string
Unit string, resolved from custom unit or attributes.unit_of_measurement
attribute
string
Attribute name to display (if any)
default_action
object
Click action configuration
scroll_action
object
Scroll action configuration
active
boolean
Whether the entity is in an “active” stateTrue if state is "on", "open", or "idle"
domain
string
Entity domain extracted from entity_idExamples: "light", "sensor", "switch", "climate"
value
string
Computed display value using getDisplayValue()Shows attribute value or formatted state with unit

Implementation

From model.mjs:9-22:
export function Entity({
    entity_id = '',
    name,
    icon,
    state,
    attribute = '',
    attributes,
    unit,
    default_action = {},
    scroll_action = {}
} = {}, data = {}) {
    this.entity_id = entity_id
    this.attributes = Object.assign({}, attributes, data.a)
    this.state = data.s || state || ''
    this.name = name || this.attributes.friendly_name || ''
    this.icon = icon || this.attributes.icon || ''
    this.unit = unit || this.attributes.unit_of_measurement || ''
    this.attribute = attribute
    this.default_action = default_action
    this.scroll_action = scroll_action
    this.active = activeStates.includes(this.state)
    this.domain = entity_id.substring(0, entity_id.indexOf('.'))
    this.value = getDisplayValue(this)
}

Usage Example

From main.qml:96-102:
function initState(state) {
    itemModel.clear()
    items.forEach((i, idx) => {
        const entityData = state[i.entity_id]
        // Create Entity from config item and live data
        itemModel.insert(idx, new Model.Entity(i, entityData))
    })
    initialized = true
}
Updating with new state (main.qml:82-94):
function updateState(state) {
    for(let id in state) {
        const itemIdx = items.findIndex(i => i.entity_id === id)
        const change = state[id]['+']  // {s: "new_state", a: {...}}
        const item = itemModel.get(itemIdx)
        // Create new Entity merging old config with new data
        const newItem = new Model.Entity(item, change)
        const oldValue = item.value
        itemModel.set(itemIdx, newItem)
        if (items[itemIdx].notify && oldValue !== newItem.value) {
            notifications.createNotification(newItem.name + " " + newItem.value)
        }
    }
}

ConfigEntity Class

Represents an entity in the configuration UI with reactive action properties.

Constructor

function ConfigEntity(
    {entity_id, name, icon, attribute, default_action, scroll_action, notify}
)
entity_id
string
default:"''"
Entity ID to configure
name
string
Custom display name
icon
string
Custom icon identifier
attribute
string
Attribute name to display
default_action
object
Click action configuration
scroll_action
object
Scroll action configuration
notify
boolean
Whether to show notifications when entity value changes

Properties

ConfigEntity uses property descriptors for reactive behavior:
entity_id
string
Reactive entity ID propertyWhen set, automatically:
  • Updates internal domain property
  • Updates action targets to match new entity_id
  • Validates actions against new domain
domain
string
Entity domain extracted from entity_id
default_action
object
Reactive default action propertyWhen set, automatically:
  • Validates service exists
  • Sets domain from entity domain if not provided
  • Sets target to current entity_id if not provided
  • Returns null if service is empty
scroll_action
object
Reactive scroll action property (same behavior as default_action)

Implementation

From model.mjs:24-52:
export function ConfigEntity({
    entity_id = '',
    name,
    icon,
    attribute,
    default_action,
    scroll_action,
    notify
} = {}) {
    // Reactive entity_id property
    Object.defineProperties(this, {
        entity_id: {
            enumerable: true,
            get: function() { return this[Symbol.for('entity_id')] },
            set: function(id) {
                this[Symbol.for('entity_id')] = id
                this[Symbol.for('domain')] = id.substring(0, id.indexOf('.'))
                updateAction(this, 'default_action')
                updateAction(this, 'scroll_action')
            }
        },
        domain: {
            enumerable: true,
            get: function() { return this[Symbol.for('domain')] }
        }
    });

    // Add reactive action properties
    addActionProperty(this, 'default_action')
    addActionProperty(this, 'scroll_action')

    // Set initial values (triggers setters)
    this.entity_id = entity_id
    this.name = name
    this.icon = icon
    this.attribute = attribute
    this.default_action = default_action
    this.scroll_action = scroll_action
    this.notify = notify
}

Action Property Logic

From model.mjs:54-73:
function addActionProperty(o, name) {
    Object.defineProperty(o, name, {
        enumerable: true,
        get: function() { return o[Symbol.for(name)] },
        set: function(action) {
            // Return null if no service specified
            o[Symbol.for(name)] = !action?.service ? null : { 
                service: action.service,
                domain: action.domain || o.domain,  // Default to entity domain
                target: action.target || { entity_id: o.entity_id },  // Default to this entity
                data_field: action.data_field
            }
        }
    })
}

function updateAction(o, name) {
    if (!o[name]) return
    // Clear action if domain changed and doesn't match
    if (o.domain !== o[name].domain) return o[name] = null
    // Update target to new entity_id
    o[name].target.entity_id = o.entity_id    
}

Usage Example

From ConfigItems.qml:34 and ConfigItem.qml:
// Creating new config entity
Button {
    text: i18n("Add")
    onClicked: openDialog(new Model.ConfigEntity())
}

// Loading existing config entity
ToolButton {
    icon.name: 'edit-entry'
    onClicked: openDialog(new Model.ConfigEntity(model), index)
}

// In ConfigItem.qml - reactive updates
TextField {
    text: item.entity_id
    onEditingFinished: {
        item.entity_id = text  // Triggers domain update and action validation
        itemChanged()
    }
}

getDisplayValue Function

Utility function that formats entity display values.

Signature

function getDisplayValue({state, attribute, attributes, unit})
state
string
Entity state value
attribute
string
Attribute name to display (if any)
attributes
object
Entity attributes object
unit
string
Unit string
return
string
Formatted display string

Logic

From model.mjs:3-7:
function getDisplayValue({state, attribute, attributes, unit}) {
    // Priority 1: Display attribute value if specified and exists
    if (attribute && attributes[attribute]) 
        return attributes[attribute].toString()
    
    // Priority 2: Display state with unit (if not unknown)
    if (state && state !== 'unknown') 
        return state + (unit === '%' ? unit : ' ' + unit)
    
    // Priority 3: Return empty string
    return ''
}

Behavior

  1. Attribute mode: If attribute is set and exists in attributes, return that value
  2. State mode: If state exists and is not "unknown", return formatted state:
    • Percentage: Append % directly (e.g., "75%")
    • Other units: Add space before unit (e.g., "22 °C")
  3. Fallback: Return empty string if no valid value

Examples

// Attribute display
getDisplayValue({
    attribute: 'brightness',
    attributes: {brightness: 200},
    state: 'on',
    unit: ''
})
// Returns: "200"

// State with percentage
getDisplayValue({
    state: '75',
    unit: '%'
})
// Returns: "75%"

// State with temperature
getDisplayValue({
    state: '22.5',
    unit: '°C'
})
// Returns: "22.5 °C"

// Unknown state
getDisplayValue({
    state: 'unknown',
    unit: '°C'
})
// Returns: ""

// No attribute value
getDisplayValue({
    attribute: 'missing',
    attributes: {},
    state: 'on'
})
// Returns: "on "

Active States

The model defines which states are considered “active”:
const activeStates = ['on', 'open', 'idle'];
Entities with these states have active === true, which can be used for:
  • Visual highlighting
  • Icon selection
  • Color themes
  • Filtering

Data Flow

Configuration to Runtime

  1. User configures entity in ConfigItems using ConfigEntity
  2. Configuration saved to plasmoid.configuration.items as JSON
  3. Main plasmoid reads configuration and parses JSON to array
  4. Array items used as templates to create Entity instances
  5. Live state data merged into Entity instances
  6. Entity instances stored in itemModel for UI display

State Updates

  1. Home Assistant sends state change event via WebSocket
  2. Event contains entity_id and change data: {entity_id: {"+": {s: "new_state", a: {...}}}}
  3. Find corresponding item in model by entity_id
  4. Create new Entity merging existing config with new state
  5. Replace old Entity in model with new one
  6. QML UI automatically updates via model binding

Best Practices

  1. Immutable updates: Always create new Entity instances for updates (don’t modify existing)
  2. Merge carefully: Use Object.assign({}, old, new) to merge attributes safely
  3. Check attribute existence: Always check if (attribute && attributes[attribute]) before accessing
  4. Validate entity_id: Ensure entity_id contains a dot before extracting domain
  5. Handle undefined: Use default parameters and fallback chains for safety
  6. Use ConfigEntity reactivity: Let property setters handle domain/action updates automatically

Type Reference

Entity Type

interface Entity {
    entity_id: string
    state: string
    attributes: Record<string, any>
    name: string
    icon: string
    unit: string
    attribute: string
    default_action: Action
    scroll_action: Action
    active: boolean
    domain: string
    value: string
}

ConfigEntity Type

interface ConfigEntity {
    entity_id: string  // reactive
    domain: string  // readonly, reactive
    name?: string
    icon?: string
    attribute?: string
    default_action?: Action  // reactive
    scroll_action?: Action  // reactive
    notify?: boolean
}

Action Type

interface Action {
    domain: string
    service: string
    target?: {
        entity_id: string | string[]
        area_id?: string
        device_id?: string
    }
    data_field?: string
}

Build docs developers (and LLMs) love