A Home Assistant custom component for LightStack - a priority-based alert management system for Inovelli LED switches.
LightStack is a priority-based alert management system designed specifically for Inovelli smart switches with LED notification bars. It solves a common problem: when multiple alerts are active, only one LED state can be displayed at a time.
The Problem:
Without LightStack:
alert 1 fires -> switch displays alert 1
alert 2 fires -> switch displays alert 2
alert 2 clears -> switch shows "all clear" (WRONG! alert 1 is still active)
The Solution:
With LightStack:
alert 1 fires -> switch displays alert 1
alert 2 fires -> switch displays alert 2 (if higher priority)
alert 2 clears -> switch displays alert 1 (correctly shows remaining alert)
LightStack provides:
- Centralized alert state tracking across all your automations
- Priority-based display (5 levels: Critical, High, Medium, Low, Info)
- Full LED customization per alert (color, effect, brightness, duration)
- Real-time updates via WebSocket
- Web UI for managing alerts and viewing history
For more information about LightStack, including installation and configuration, visit the LightStack repository.
- Real-time Updates: Uses WebSocket for instant push notifications - no polling required
- LED Plan Sensor: What the switch is showing across all seven LEDs, plus the exact Zigbee2MQTT payloads to reproduce it
- Per-LED Alerts: Several alerts can share the switch at once, each holding its own LEDs
- Current Alert Sensor: The highest priority active alert, with its LED settings
- Alert Status Binary Sensor: Simple on/off indicator when any alert is active
- Clear All Button: One-click button to clear all active alerts
- Services: Full control via Home Assistant services for automations
The Inovelli Blue Series LED bar has seven LEDs (LED 1 at the bottom, LED 7 at the top). Each LED holds its own effect in firmware, so several alerts can show at the same time on different LEDs. Each alert in LightStack either takes the whole bar or lights specific LEDs.
LightStack decides what the switch shows:
- A whole-bar alert outranks every per-LED alert. While one is active it is shown and per-LED alerts are hidden. This is also what the hardware does: a whole-bar effect masks the individual LEDs underneath it.
- Among competing bar alerts, the highest priority one wins.
- With no bar alert active, every per-LED alert shows at once. Where two alerts claim the same LED, the higher priority one wins that LED.
- Equal priorities are broken alphabetically, so the display is stable.
Effects are never blended: each LED shows exactly one alert.
The result is published as the LED Plan sensor, which carries a ready-to-publish
list of Zigbee2MQTT payloads. Use lightstack.apply_led_plan to send them.
| Platform | Description |
|---|---|
sensor |
current_alert (highest priority alert) and led_plan (the whole LED bar) |
binary_sensor |
Indicates if any alert is currently active (on) or all clear (off) |
button |
Clear all active alerts with a single press |
| Service | Description |
|---|---|
lightstack.trigger_alert |
Trigger an alert by key, with optional priority override |
lightstack.clear_alert |
Clear a specific alert by key |
lightstack.clear_all_alerts |
Clear all active alerts |
lightstack.apply_led_plan |
Publish the current LED plan to a Zigbee2MQTT switch |
- Open HACS in Home Assistant
- Go to "Integrations"
- Click the three dots in the top right corner
- Select "Custom repositories"
- Add
https://github.com/sjafferali/lightstack-homeassistantas an Integration - Click "Install"
- Restart Home Assistant
- Copy the
custom_components/lightstackdirectory to your Home Assistant'scustom_componentsdirectory - Restart Home Assistant
After installation:
- Go to Settings -> Devices & Services
- Click "+ Add Integration"
- Search for "LightStack"
- Enter your LightStack server host and port
The integration is configured through the UI:
| Field | Description | Default |
|---|---|---|
| Host | Hostname or IP of your LightStack server | localhost |
| Port | WebSocket API port | 8080 |
The Current Alert sensor provides these attributes for use in automations:
| Attribute | Description |
|---|---|
is_all_clear |
Boolean indicating if all alerts are cleared |
active_count |
Number of currently active alerts |
alert_key |
Unique identifier of the current alert |
effective_priority |
Priority level (1-5) of the current alert |
priority_name |
Human-readable priority (Critical, High, Medium, Low, Info) |
led_color |
Inovelli LED color value (0-255) |
led_color_name |
Human-readable color name (Red, Blue, Green, etc.) |
led_effect |
LED effect code (solid, pulse, chase, aurora, etc.) |
led_effect_name |
Human-readable effect name (Solid, Pulse, Chase, etc.) |
led_brightness |
LED brightness level (0-100) |
led_duration |
LED duration value (encoded, see below) |
led_duration_name |
Human-readable duration (e.g., "5 Minutes", "Indefinitely") |
led_scope |
bar (whole strip) or individual (specific LEDs) |
led_positions |
The LEDs (1-7) this alert lights, when scope is individual |
last_triggered |
Timestamp when the alert was last triggered |
description |
Alert description if configured |
sensor.lightstack_led_plan describes the whole switch, not a single alert. Its state
is how the bar is being driven: idle, bar, or individual.
| Attribute | Description |
|---|---|
mode |
idle, bar, or individual |
is_all_clear |
True when nothing is lit |
bar_alert_key |
The alert owning the whole bar, in bar mode |
lit_count |
How many of the seven LEDs are lit |
showing |
The alerts currently on the switch, bottom LED first |
suppressed |
Active alerts that are not on the switch (outranked or masked) |
leds |
All seven LEDs: which alert owns each, and its effect, color and level |
commands |
The Zigbee2MQTT payloads to publish, in order |
The commands list always specifies the bar and all seven LEDs, so it can be
applied without knowing what the switch was showing beforehand. There is no bitmask on
the hardware: one publish per LED.
A single LED accepts fewer effects than the whole bar. Zigbee2MQTT discards an unsupported effect without reporting an error, so the LED simply stays dark. LightStack rejects the combination when the alert is saved, but it is worth knowing which is which:
| Effect | Whole bar | Single LED |
|---|---|---|
solid |
yes | yes |
fast_blink, slow_blink |
yes | yes |
medium_blink |
yes | — |
pulse |
yes | yes |
chase |
yes | yes |
slow_chase, fast_chase |
yes | — |
aurora |
yes | yes |
falling, rising |
— | yes |
slow/medium/fast_falling |
yes | — |
slow/medium/fast_rising |
yes | — |
fast_siren, slow_siren |
yes | — |
open_close |
yes | — |
small_to_big |
yes | — |
off, clear_effect |
yes | yes |
Note that falling and rising are per-LED names; the bar uses the speed variants
instead.
Duration values are encoded as follows:
| Value Range | Unit | Example |
|---|---|---|
| 1-60 | Seconds | 30 = 30 seconds |
| 61-120 | Minutes | 65 = 5 minutes |
| 121-254 | Hours | 132 = 12 hours |
| 255 | Indefinite | Runs until cleared |
automation:
- alias: "Alert on Garage Door Open"
trigger:
- platform: state
entity_id: cover.garage_door
to: "open"
action:
- service: lightstack.trigger_alert
data:
alert_key: "garage_door_open"
priority: 2
note: "Garage door opened"automation:
- alias: "Clear Garage Door Alert"
trigger:
- platform: state
entity_id: cover.garage_door
to: "closed"
action:
- service: lightstack.clear_alert
data:
alert_key: "garage_door_open"For Inovelli Blue series switches with Zigbee2MQTT. This is all you need: whenever the LED plan changes, hand it to the switch.
automation:
- alias: "Update Inovelli LEDs from LightStack"
trigger:
- platform: state
entity_id: sensor.lightstack_led_plan
action:
- service: lightstack.apply_led_plan
data:
topic: "zigbee2mqtt/Office Switch/set"The service publishes each of the plan's commands in order, spaced 100 ms apart, which
is how Inovelli's own driver addresses the LEDs one at a time. Raise delay_ms if a
busy Zigbee network drops commands.
Driving more than one switch is the same service, once per topic:
action:
- service: lightstack.apply_led_plan
data:
topic: "zigbee2mqtt/Office Switch/set"
- service: lightstack.apply_led_plan
data:
topic: "zigbee2mqtt/Hallway Switch/set"If you would rather publish the payloads yourself, loop over the commands attribute:
action:
- repeat:
for_each: "{{ state_attr('sensor.lightstack_led_plan', 'commands') }}"
sequence:
- service: mqtt.publish
data:
topic: "zigbee2mqtt/Office Switch/set"
payload: "{{ repeat.item | to_json }}"
- delay:
milliseconds: 100Notify when an alert is hidden
Because a whole-bar alert masks every per-LED alert, a P1 can be active but not
visible. suppressed makes that explicit:
automation:
- alias: "Warn when a critical alert is hidden"
trigger:
- platform: state
entity_id: sensor.lightstack_led_plan
condition:
- condition: template
value_template: >
{{ state_attr('sensor.lightstack_led_plan', 'suppressed') | length > 0 }}
action:
- service: notify.mobile_app
data:
message: >
Hidden on the switch:
{{ state_attr('sensor.lightstack_led_plan', 'suppressed') | join(', ') }}For Z-Wave Inovelli switches:
automation:
- alias: "Update Inovelli LED from LightStack"
trigger:
- platform: state
entity_id: sensor.lightstack_current_alert
action:
- choose:
- conditions:
- condition: state
entity_id: sensor.lightstack_current_alert
state: "All Clear"
sequence:
- service: zwave_js.set_config_parameter
target:
entity_id: light.inovelli_switch
data:
parameter: 16
value: 0 # Clear notification
- conditions:
- condition: template
value_template: "{{ state_attr('sensor.lightstack_current_alert', 'led_color') is not none }}"
sequence:
- service: zwave_js.set_config_parameter
target:
entity_id: light.inovelli_switch
data:
parameter: 16
value: >
{% set color = state_attr('sensor.lightstack_current_alert', 'led_color') | default(0) %}
{% set effect = state_attr('sensor.lightstack_current_alert', 'led_effect') %}
{% set effect_num = {'solid': 1, 'fast_blink': 2, 'slow_blink': 3, 'pulse': 4}.get(effect, 1) %}
{{ (color * 65536) + (effect_num * 256) + 255 }}- Home Assistant 2023.1.0 or newer
- LightStack server running and accessible
- The MQTT integration, if you use
lightstack.apply_led_planto drive a Zigbee2MQTT switch
- Verify LightStack server is running
- Check the host and port are correct
- Ensure there are no firewalls blocking the WebSocket connection
- Check Home Assistant logs for detailed error messages
The integration uses WebSocket push notifications. If entities stop updating:
- Check if LightStack server is still running
- Reload the integration from Settings -> Devices & Services
- Check logs for reconnection messages
- LightStack - The priority-based alert management server this integration connects to
Contributions are welcome! Please read the Contribution guidelines.
This project was generated from @oncleben31's Home Assistant Custom Component Cookiecutter template.
