Skip to content

v0.2.0 — multi-target, glob, per-target source, admin-gating

Choose a tag to compare

@jpettitt jpettitt released this 21 May 20:28

First general-availability release of the v0.2 line. Rolls up everything from v0.2.0b1 and v0.2.0b2 and adds the admin-gating work that landed after b2.

This is a drop-in upgrade from v0.1.x. Existing rules keep working — the singular target: <entity_id> form is auto-migrated to the new targets: [<entity_id>] list on load. No manual migration, no YAML changes.

Highlights

Multi-target rules and glob target patterns

One rule can now apply to many entities at once. Pick them in the panel via HA's native multi-entity selector, or list them in YAML / JSON:

```jsonc
{ "targets": ["light.kitchen", "light.dining_room"] }
```

Targets can also include shell-style globs — `*`, `?`, `[set]`:

```jsonc
{ "targets": ["light.kitchen_*", "sensor.temp_?"] }
```

Patterns are resolved against `hass.states` at apply time. The panel shows a live "Matches N entities" preview as you type. Newly-added entities that match an existing glob pick up the rule automatically.

Per-target source semantics

For a multi-target or glob rule with no explicit `source`, each matched target reacts to its own state and `source_attribute`. One rule, every kitchen light colored by its own brightness:

```jsonc
{
"targets": ["light.kitchen_*"],
"source_attribute": "brightness",
"mode": "thresholds",
"thresholds": [
{ "lt": 64, "color": "#552200" },
{ "lt": 192, "color": "#ffaa00" },
{ "color": "#ffffaa" }
]
}
```

(No `source` field — that's per-target semantics: each matched light reads its own `brightness`.)

Single-literal-target rules still default `source` to the target, as before.

Mapping-state autocomplete

Each mapping-key cell in the editor offers a `` of states the resolved source entity has actually been observed in — the last seven days of recorder history plus its current state. Cached per-entity. Falls back to just the current state when the recorder is disabled.

Speeds up authoring mapping rules for entities with non-obvious state vocabularies (`lock`'s `locking` / `unlocking`, `alarm_control_panel`'s mode names, etc.).

Admin-only management

Both the WebSocket API and the sidebar panel are admin-gated. Non-admin users:

  • Don't see the Smart Icons sidebar entry
  • Get `unauthorized` from every `smart_icons/*` WS command
  • Still see correctly painted icons on their dashboards — the painter bundle reads `smart_icons_color` directly from each entity's state attributes, no WS calls

The painter bundle shrunk from 4.4 KB → 3.3 KB after removing the rule store from it.

Rule editor UX overhaul

Section-grouped layout (Apply to / React to / Decoration / Options), inline error placement, sticky save bar at the bottom of the dialog, validation-gated Save button, Duplicate action, reorderable threshold entries (↑ / ↓), HA-native dialog-style delete confirmation. Action error banner for toggle/delete failures.

Responsive panel layout

The rules table reformats as a labeled card stack on narrow widths using a CSS container query against the panel card. Unlike viewport-based media queries, this correctly fires when the HA sidebar opens or closes (which changes the panel width independently of the viewport).

Integration brand icon

Painted-favicon brand mark under `custom_components/smart_icons/brand/` following HA's brands-proxy convention (HA 2026.3+). No manifest changes needed — the icon shows up automatically in Settings → Devices & services and HACS.

Bug fixes from the betas

  • Painter color race eliminated. The painter and HA's card Lit re-render were both microtask-scheduled in the same tick with no ordering guarantee — the painter often read a stale `stateObj`, so colors appeared stuck until the user navigated away and back. The state-watcher now caches the full attribute bag synchronously inside the event dispatch; the painter reads from there, removing the race.
  • Glob rules survive HA restart. Entities whose owning integration publishes them seconds after Smart Icons loads (the classic post-restart case for MQTT / Zigbee / lock integrations) are now caught by a `state_changed` listener filtered for `old_state is None`. The matching glob rule is applied immediately rather than only after a dashboard switch.
  • mwc-button migrated to ha-button. `mwc-*` elements are unregistered in modern HA and render as invisible unknown elements — `ha-button` with `variant=brand|neutral|danger` is the right primitive.
  • ha-selector replaces ha-entity-picker. Direct `ha-entity-picker` has a CSS click-area bug in dialog contexts (only a thin band at the top of each row was clickable). `ha-selector` with an entity selector config (the same dispatcher HA's own options flows use) hands off to the right picker variant per HA version.
  • Mobile table overflow. The rules table now reformats as a labeled card stack below ~860 px.

Upgrade

Drop-in. No manual migration. After updating, restart HA. Existing rules keep working and the singular-`target` form is rewritten to `targets: [...]` on first load.

HACS users: if you previously opted in to beta versions, you can turn that off — v0.2.0 is the stable release of the v0.2 line.

Compatibility

  • Home Assistant 2024.7 or newer (`StaticPathConfig` requirement — declared as `min_ha_version` in the integration manifest).
  • Works on any card that uses ``: all default cards (entities, tile, glance, more-info) and most third-party cards (mushroom, button-card via its default icon path).
  • Out of scope: cards that draw their own SVG icons (mini-graph-card, apex-charts-card custom paths).

Internals

  • `manifest.json` declares `min_ha_version: "2024.7"`.
  • WS version endpoint reads `homeassistant.version` directly.
  • `store.async_load` exception catch narrowed to `(vol.Invalid, ValueError)` so unrelated bugs surface in the log.
  • 86 pytest + 36 Web Test Runner tests green; typecheck clean.

Known limitations (unchanged from v0.1.1)

  • Template-mode rules are stored but not evaluated at runtime — v0.3 work.
  • Releasing a rule clears the color override but leaves the last injected icon on the target's state until the source integration pushes a fresh state update.

What's next (v0.3)

  • Template-mode evaluation — Jinja rendered server-side, with a `smart_icons/render_template` WS command for live preview in the panel.
  • Door 1 — entity settings dialog injection so individual entity pages get a "Smart Icon" section.
  • YAML loader — for users who want to keep rules in `configuration.yaml` alongside the rest of their config.
  • Translations framework.

Full Changelog: v0.1.1...v0.2.0