Skip to content

Helpers API - Developer Guide

This guide explains the architecture and usage of the LCARdS helper management system for developers extending or maintaining the codebase.

Architecture Overview

The helper system consists of three main components:

┌─────────────────────────────────────┐
│   Helper Registry (Schema)          │
│   - Authoritative definitions       │
│   - YAML templates                  │
└──────────────┬──────────────────────┘

┌──────────────▼──────────────────────┐
│   Helper Manager (Service)          │
│   - Lifecycle management            │
│   - State monitoring                │
│   - Value access                    │
└──────────────┬──────────────────────┘

┌──────────────▼──────────────────────┐
│   Helper API (WebSocket Wrapper)    │
│   - Create/delete operations        │
│   - Entity registry updates         │
└─────────────────────────────────────┘

Core Components

1. Helper API (lcards-helper-api.js)

Low-level WebSocket API wrapper for Home Assistant helper operations.

Functions:

javascript
// Create a new helper
await createHelper(hass, domain, name, attributes);

// Delete a helper
await deleteHelper(hass, domain, helperId);

// Rename helper entity_id
await updateHelperEntityId(hass, currentEntityId, newEntityId);

// Idempotent creation (check + create if missing)
await ensureHelper(hass, definition);

// Check existence
const exists = helperExists(hass, entityId);

// Get value
const value = getHelperValue(hass, entityId, defaultValue);

// Set value (public API)
await setHelperValue(hass, entityId, value);

WebSocket API Notes:

The HA WebSocket API for helpers is undocumented and may change:

javascript
// Create input_number
await hass.callWS({
  type: 'input_number/create',
  name: 'Helper Name',
  min: 0,
  max: 100,
  step: 1,
  mode: 'slider',
  icon: 'mdi:icon'
});

// Rename entity
await hass.callWS({
  type: 'config/entity_registry/update',
  entity_id: 'input_number.old_id',
  new_entity_id: 'input_number.new_id'
});

Supported Domains:

  • input_number - Sliders and number inputs
  • input_select - Dropdowns
  • input_boolean - Toggles
  • input_text - Free-text storage (e.g. JSON config blobs)

Error Handling:

All functions throw errors with meaningful messages. Always wrap in try/catch:

javascript
try {
  await createHelper(hass, 'input_number', 'My Helper', {
    min: 0,
    max: 100,
    step: 1
  });
} catch (error) {
  console.error('Failed to create helper:', error.message);
}

2. Helper Registry (lcards-helper-registry.js)

Authoritative schema defining all LCARdS helpers.

Registry Structure:

javascript
export const HELPER_REGISTRY = {
  helper_key: {
    entity_id: 'input_select.lcards_helper_name',
    domain: 'input_select',
    name: 'Human Readable Name',
    description: 'Purpose and usage',
    icon: 'mdi:icon-name',
    category: 'category_name',
    ws_create_params: {
      // Domain-specific parameters
      options: ['option1', 'option2']
    },
    default_value: 'option1',
    yaml_config: `input_select:
  lcards_helper_name:
    name: Human Readable Name
    options:
      - option1
      - option2
    icon: mdi:icon-name`
  }
};

Key Fields:

  • entity_id: Desired entity ID in Home Assistant
  • domain: Helper type (input_number, input_select, input_boolean, input_text)
  • ws_create_params: Parameters for WebSocket creation
  • default_value: Fallback value if helper doesn't exist
  • yaml_config: Valid YAML for manual creation

Utility Functions:

javascript
// Get helpers by category
const alertHelpers = getHelpersByCategory('alert_system');

// Get all categories
const categories = getCategories();

// Lookup by key
const definition = getHelperDefinition('alert_mode');

// Get all helpers
const all = getAllHelpers();

// Generate YAML
const yaml = generateHelpersYAML();
const categoryYaml = generateHelpersYAML('alert_system');

// Find by entity_id
const helper = findHelperByEntityId('input_select.lcards_alert_mode');

3. Helper Manager (lcards-helper-manager.js)

Service class managing helper lifecycle and state.

Initialization:

javascript
import { LCARdSHelperManager } from './core/helpers/lcards-helper-manager.js';

const helperManager = new LCARdSHelperManager(hass);

// Integrated in core
window.lcards.core.helperManager

Lifecycle Methods:

javascript
// Get missing helpers
const missing = helperManager.getMissingHelpers();

// Create all missing helpers
const results = await helperManager.ensureAllHelpers();
// Returns: { total, existing, created, failed, errors }

// Create single helper
await helperManager.ensureHelper('alert_mode');

State Access:

javascript
// Get current value (or default)
const mode = helperManager.getHelperValue('alert_mode');

// Set value (calls HA service)
await helperManager.setHelperValue('alert_mode', 'red_alert');

// Check existence
if (helperManager.helperExists('alert_mode')) {
  // Helper exists
}

Reactivity:

javascript
// Subscribe to changes
const unsubscribe = helperManager.subscribeToHelper(
  'alert_mode',
  (newValue, oldValue) => {
    console.log(`Alert mode changed: ${oldValue} → ${newValue}`);
  }
);

// Cleanup
unsubscribe();

// Or unsubscribe by key
helperManager.unsubscribeFromHelper('alert_mode');

Helper Bindings (Future):

javascript
// Resolve helper bindings in card config
const config = {
  alertMode: null,
  threshold: null
};

const bindings = {
  alertMode: 'alert_mode',
  threshold: 'alert_threshold'
};

const resolved = helperManager.resolveHelperBindings(config, bindings);
// Returns config with values from helpers

Export:

javascript
// Generate YAML
const yaml = helperManager.generateYAML();
const alertYaml = helperManager.generateYAML('alert_system');

// Get helpers by category
const helpers = helperManager.getHelpersByCategory('alert_system');

Adding New Helpers

Step 1: Define in Registry

Add to HELPER_REGISTRY in lcards-helper-registry.js:

javascript
export const HELPER_REGISTRY = {
  // ... existing helpers

  my_new_helper: {
    entity_id: 'input_boolean.lcards_my_feature_enabled',
    domain: 'input_boolean',
    name: 'My Feature Enabled',
    description: 'Enable or disable my cool feature',
    icon: 'mdi:feature-search',
    category: 'features',
    ws_create_params: {}, // input_boolean has no extra params
    default_value: false,
    yaml_config: `input_boolean:
  lcards_my_feature_enabled:
    name: My Feature Enabled
    icon: mdi:feature-search`
  }
};

Step 2: Use in Code

Access via Helper Manager:

javascript
// Check if feature is enabled
const isEnabled = window.lcards.core.helperManager.getHelperValue('my_new_helper');

if (isEnabled) {
  // Feature logic
}

// Subscribe to changes
window.lcards.core.helperManager.subscribeToHelper(
  'my_new_helper',
  (enabled) => {
    // React to changes
    this.featureEnabled = enabled;
    this.requestUpdate();
  }
);

Step 3: Document

Update user documentation with:

  • Purpose of the helper
  • Expected values
  • Usage examples
  • Automation integration

Integration Points

Core System

The Helper Manager is initialized in lcards-core.js:

javascript
// Initialize HelperManager (Phase 2f)
this.helperManager = new LCARdSHelperManager(hass);

// Update HASS
if (this.helperManager) {
  this.helperManager.updateHass(hass);
}

Access globally:

javascript
window.lcards.core.helperManager

Alert Lab & Configuration Panel

Both consumers use the same Helper Manager API already documented above — no new methods. The Alert Lab reads/writes alert_lab_{mode}_{hue,saturation,lightness} keys via getHelperValue()/setHelperValue() on open/save; the Config Panel lists helper status via getAllHelpers() + helperExists() + getHelperValue(), and bulk-creates missing ones via ensureAllHelpers().

Best Practices

  • Naming: prefix all helpers with lcards_, snake_case entity IDs, group by category in the registry.
  • Error handling: wrap createHelper()/setHelperValue() calls in try/catch — see the Error Handling notes under Helper API above.
  • State: subscribe to changes for reactive updates instead of polling, and unsubscribe on component cleanup (unsubscribeFromHelper() or the function returned by subscribeToHelper()).
  • Performance: batch helper creation via ensureAllHelpers() rather than looping ensureHelper() calls; avoid excessive subscriptions.

There is no automated test suite for this project — validate helper changes manually: create via the Config Panel, confirm the entity appears in HA, exercise Alert Lab save/reload, and trigger a value change from an automation.