Split automations into HA-style `triggers`, ongoing `conditions`, and
`actions`, with compatibility migrations for existing Advanced Camera
Card configs.
## Summary
At a glance (details below):
- **Added** `triggers:` -- a required, HA-shaped block: stock `state` /
`numeric_state` / `template` plus card-specific triggers (`camera`,
`view`, `fullscreen`, ...).
- **Added** the HA-native `if` / `then` / `else` action.
- **Removed** `actions_not` (replaced by `if` / `then` / `else`).
- **Removed** the ambient `advanced_camera_card` template namespace (use
`acc` instead).
- **Changed** the trigger template surface to a top-level `trigger.*`
variable (as in HA); the nested `acc.trigger.*` paths are removed.
- **Changed** `conditions:` to ongoing gates only -- they no longer wake
an automation, and change-only forms (`config`, valueless `camera` /
`view` / `state`) become triggers, not conditions.
- **Changed** action templates to render per step, so a later action
sees state an earlier one changed.
- **Compatibility:** HA-shaped YAML is accepted (singular keys,
single-or-list, `and` / `or` / `not` shorthand, `entity` / `entity_id`).
- **Migration:** existing configs upgrade automatically; anything that
cannot be converted faithfully is recorded under `__UPGRADE_FAILURE__`
for manual fixup.
## Breaking Changes
### 1. Automations now require triggers
Before this PR, `automations[].conditions` served two roles:
- They decided whether the automation should run.
- They also acted as the thing that woke the automation up.
After this PR:
- `triggers` wake the automation.
- `conditions` only gate it at the instant a trigger fires.
Most existing automations are migrated automatically from `conditions:`
to `triggers:`.
### 2. `actions_not` is retired
Legacy `actions_not` is replaced by an HA-style `if` action with `then`
/ `else`.
Faithful conversions are automatic. Cases that cannot be faithfully
converted are recorded under `__UPGRADE_FAILURE__.automations` and must
be migrated manually.
### 3. Template surface aligned with Home Assistant
Two related template changes, both auto-migrated:
- **Top-level `trigger.*`.** Automation actions now receive a top-level
`trigger` template variable, like Home Assistant. Legacy nested paths
such as `acc.trigger.state.to` and
`advanced_camera_card.trigger.camera.to` are migrated automatically when
they appear inside template strings.
- **The ambient `advanced_camera_card` template namespace is removed.**
The long-form ambient namespace (`advanced_camera_card.camera`,
`advanced_camera_card.view`, `advanced_camera_card.config`) is retired
in favour of its shorter `acc` alias -- supported since v7.1.0, and the
only spelling the new trigger surface uses. Existing templates are
migrated automatically by rewriting the `advanced_camera_card.` prefix
to `acc.`.
### 4. Trigger-only condition forms are no longer valid conditions
Some legacy "conditions" were really change detectors. These are now
triggers only:
- `condition: config`
- valueless `camera`
- valueless `view`
- valueless `state` / picture-elements state condition with neither
`state` nor `state_not`
These are automatically promoted in automations and stripped from
overrides/elements where they would no longer be meaningful as ongoing
conditions.
### 5. Template truthiness now follows Home Assistant behavior
Template conditions and template triggers intentionally use different
truthiness rules, matching HA:
- A template condition passes only when the rendered value is `true`
(case-insensitive), matching HA's `condition.py`.
- A template trigger uses HA's broader `result_as_boolean` coercion: a
non-zero number, or `1` / `true` / `yes` / `on` / `enable`
(case-insensitive), counts as true.
### 6. Action templates render when each action executes
Action templates are now rendered per action step, not once for the
whole sequence. This means a later action can see card-local state
changed by an earlier action in the same sequence.
The `trigger` context is fixed for the automation run. HA entity state
updates still depend on the frontend receiving updated HASS state over
the websocket.
## Automatic Migrations
### Automation `conditions:` to `triggers:`
Simple legacy automation:
```yaml
# Before
automations:
- conditions:
- condition: fullscreen
fullscreen: true
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
```
```yaml
# After, automatic
automations:
- triggers:
- trigger: fullscreen
fullscreen: true
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
```
State conditions become HA-style state triggers:
```yaml
# Before
automations:
- conditions:
- condition: state
entity_id: binary_sensor.front_door
state: 'on'
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
```
```yaml
# After, automatic
automations:
- triggers:
- trigger: state
entity_id: binary_sensor.front_door
to: 'on'
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
```
Multiple conditions become both triggers and ongoing conditions:
```yaml
# Before
automations:
- conditions:
- condition: camera
cameras: [front_door]
- condition: fullscreen
fullscreen: true
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
```
```yaml
# After, automatic
automations:
- triggers:
- trigger: camera
cameras: [front_door]
- trigger: fullscreen
fullscreen: true
conditions:
- condition: camera
cameras: [front_door]
- condition: fullscreen
fullscreen: true
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
```
The flattened trigger list is an implicit OR. The retained `conditions:`
list is an implicit AND checked when any trigger fires.
### Trigger-only legacy conditions
Legacy `config` conditions become `config` triggers:
```yaml
# Before
automations:
- conditions:
- condition: config
paths: [menu.style]
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: status_bar
```
```yaml
# After, automatic
automations:
- triggers:
- trigger: config
paths: [menu.style]
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: status_bar
```
Trigger-only leaves are removed from retained `conditions:` blocks
because they no longer describe an ongoing state.
### `actions_not` to `if` / `then` / `else`
```yaml
# Before
automations:
- conditions:
- condition: state
entity_id: input_boolean.camera_alerts
state: 'on'
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
actions_not:
- action: none
```
```yaml
# After, automatic
automations:
- triggers:
- trigger: state
entity_id: input_boolean.camera_alerts
actions:
- if:
- condition: state
entity_id: input_boolean.camera_alerts
state: 'on'
then:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
else:
- action: none
```
If the legacy automation had no conditions, or only trigger-only
conditions, `actions_not` is dropped because the old `else` branch could
not be reproduced as an ongoing predicate.
### Trigger template paths
```yaml
# Before
message: 'Door is {{ acc.trigger.state.to }} from {{ acc.trigger.state.from }}'
```
```yaml
# After, automatic
message: 'Door is {{ trigger.to_state.state }} from {{ trigger.from_state.state }}'
```
Path rewrites performed automatically:
| Old path | New path |
| -------------------------- | -------------------------- |
| `acc.trigger.state.entity` | `trigger.entity_id` |
| `acc.trigger.state.from` | `trigger.from_state.state` |
| `acc.trigger.state.to` | `trigger.to_state.state` |
| `acc.trigger.camera.from` | `trigger.from_acc.camera` |
| `acc.trigger.camera.to` | `trigger.to_acc.camera` |
| `acc.trigger.view.from` | `trigger.from_acc.view` |
| `acc.trigger.view.to` | `trigger.to_acc.view` |
| `acc.trigger.config.from` | `trigger.from_acc.config` |
| `acc.trigger.config.to` | `trigger.to_acc.config` |
The same rewrites are applied for the older
`advanced_camera_card.trigger.*` namespace.
### Ambient template namespace
Any remaining long-form ambient `advanced_camera_card.*` references
(outside the trigger surface) are rewritten to the `acc.*` alias:
```yaml
# Before
title: 'Now viewing {{ advanced_camera_card.camera }}'
```
```yaml
# After, automatic
title: 'Now viewing {{ acc.camera }}'
```
## Manual Migration Cases
### `__UPGRADE_FAILURE__.automations`
If a legacy automation cannot be converted faithfully, the original
automation is recorded under:
```yaml
__UPGRADE_FAILURE__:
automations:
- ...
```
These entries require manual migration.
The main known case is legacy `actions_not` with a condition whose
trigger can only fire on a rising edge, such as:
- `condition: template`
- `condition: screen`
- `condition: numeric_state` without an entity-backed state to watch
Those conditions can start the `then` branch, but cannot reliably start
the `else` branch when they stop matching.
### Unsupported HA conditions and triggers
This PR aligns the card with HA where supported, but it is not a full HA
automation engine.
Unsupported HA condition families include:
- `time`
- `zone`
- `sun`
- `location`
- `device`
- `condition: trigger`
Unsupported HA trigger platforms include:
- `event`
- `time`
- `time_pattern`
- `sun`
- `zone`
- `calendar`
- `webhook`
- `tag`
- `device`
- `mqtt`
The card-specific camera `triggers:` feature (which auto-selects and
wakes the card on camera events such as motion) is a separate feature
from automation `triggers:`, despite the shared word.
### Trigger IDs and variables
HA keys such as `id`, `alias`, and `variables` are accepted so pasted HA
YAML validates, but they are ignored by the card. There is no
`trigger.id` support in this PR.
## New Compatibility Features
This PR also makes card config more forgiving for HA-style YAML:
- `trigger`, `condition`, and `action` singular keys are accepted and
normalized to `triggers`, `conditions`, and `actions`.
- Single trigger, condition, and action objects are accepted where lists
are expected.
- `if`, `then`, and `else` accept a single item or a list.
- Composite condition shorthand is accepted:
- `{ and: [...] }`
- `{ or: [...] }`
- `{ not: [...] }`
- `{ condition: [...] }` as an implicit AND
- State conditions resolve expected state values that name another
entity, matching HA/Lovelace behavior.
- Both `entity` and `entity_id` are accepted on state and numeric
conditions and triggers (a superset of HA's two dialects), so there is
no forced rename.
- `state_not` remains supported as a card/Lovelace-friendly extension.
## Trigger Payloads
Automation action templates receive a top-level `trigger` object.
For stock `state` and `numeric_state` triggers:
```yaml
trigger.platform
trigger.entity_id
trigger.entity
trigger.from_state
trigger.to_state
```
For template triggers:
```yaml
trigger.platform
```
For card-specific triggers:
```yaml
trigger.platform # "acc"
trigger.type
trigger.from_acc
trigger.to_acc
```
The card does not currently expose HA's `id`, `idx`, `for`, `attribute`,
`above`, `below`, or `alias` trigger fields.
BREAKING CHANGE: Automations now follow Home Assistant's `triggers:` /
`conditions:` / `actions:` model. Automations require a `triggers:`
block and `conditions:` no longer wake an automation; `actions_not` is
removed in favour of an `if` / `then` / `else` action; the nested
`acc.trigger.*` template paths and the ambient `advanced_camera_card`
template namespace are removed (use the top-level `trigger.*` surface
and the `acc` alias); trigger-only condition forms (`config`, valueless
`camera` / `view` / `state`) are no longer valid conditions; and
template-condition vs template-trigger truthiness now follow HA.
Existing configs are upgraded automatically where a faithful conversion
exists; anything that cannot be converted is recorded under
`__UPGRADE_FAILURE__` for manual migration.
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Custom Elements
conditional
Restrict a set of elements to only render when the card is matches a set of conditions. This is analogous to the stock conditional element except supporting a rich set of Advanced Camera Card conditions.
elements:
- type: custom:advanced-camera-card-conditional
# [...]
Parameters for the custom:advanced-camera-card-conditional element:
| Parameter | Description |
|---|---|
type |
Must be custom:advanced-camera-card-conditional. |
conditions |
A list of conditions that must evaluate to true in order for the elements to be rendered. |
elements |
The elements to render. Can be any supported element. |
See the conditional elements example.
menu-icon
Add an arbitrary icon to the Advanced Camera Card menu.
elements:
- type: custom:advanced-camera-card-menu-icon
# [...]
Configuration is similar to a stock Picture Elements Icon.
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-menu-icon. |
|
alignment |
matching |
Whether this menu item should have an alignment that is matching the menu alignment or opposing the menu alignment. Can be used to create two separate groups of buttons on the menu. The priority option orders buttons within a given alignment. |
enabled |
true |
Whether or not to show this menu item. |
entity |
An optional Home Assistant entity for use with actions. | |
icon |
An required icon to display, e.g. mdi:car. See also custom icons. |
|
permanent |
false |
If false the menu item is hidden when the menu has the hidden style and the menu is closed, otherwise it is shown (and sorted to the front). |
priority |
50 |
The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority 70 will order further to the left than a button with priority 60). Priority applies separately to matching and opposing groups (see alignment above). Minimum 0, maximum 100. |
style |
Position and style the element using CSS. | |
tap_action, double_tap_action, hold_action, start_tap, end_tap |
The actions to take when this item is interacted with. | |
title |
An optional title to display. |
menu-submenu
Add a configurable submenu dropdown.
elements:
- type: custom:advanced-camera-card-menu-submenu
# [...]
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-menu-submenu. |
|
alignment |
matching |
Whether this menu item should have an alignment that is matching the menu alignment or opposing the menu alignment. Can be used to create two separate groups of buttons on the menu. The priority option orders buttons within a given alignment. |
enabled |
true |
Whether or not to show this menu item. |
entity |
An optional Home Assistant entity for use with actions. | |
icon |
An required icon to display, e.g. mdi:car. See also custom icons. |
|
items |
A list of menu items, as described below. | |
permanent |
false |
If false the menu item is hidden when the menu has the hidden style and the menu is closed, otherwise it is shown (and sorted to the front). |
priority |
50 |
The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority 70 will order further to the left than a button with priority 60). Priority applies separately to matching and opposing groups (see alignment above). Minimum 0, maximum 100. |
style |
Position and style the element using CSS. | |
tap_action, double_tap_action, hold_action, start_tap, end_tap |
The actions to take when this item is interacted with. | |
title |
An optional title to display. |
Submenu items
| Parameter | Default | Description |
|---|---|---|
enabled |
true |
Whether or not to show this item as enabled / selectable. |
entity |
An optional Home Assistant entity from which title, icon and style can be automatically computed. | |
icon |
An optional item icon to display, e.g. mdi:car. See also custom icons. |
|
selected |
false |
Whether or not to show this item as selected. |
state_color |
true |
Whether or not the title and icon should be stylized based on state. |
style |
Position and style the element using CSS. | |
subtitle |
Optional additional text to display. | |
tap_action, double_tap_action, hold_action, start_tap, end_tap |
The actions to take when this item is interacted with. | |
title |
An optional title to display. |
menu-submenu-select
Add a submenu based on a select or input_select. This element allows you to convert a Home Assistant Select Entity or Home Assistant Input Select Entity (an entity either starting with select or input_select) into an overridable submenu. This could be done by hand using a regular submenu (above) -- this element is a convenience.
elements:
- type: custom:advanced-camera-card-menu-submenu-select
# [...]
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-menu-submenu-select. |
|
alignment |
matching |
Whether this menu item should have an alignment that is matching the menu alignment or opposing the menu alignment. Can be used to create two separate groups of buttons on the menu. The priority option orders buttons within a given alignment. |
enabled |
true |
Whether or not to show this menu item. |
entity |
An optional Home Assistant entity for use with actions. | |
icon |
An required icon to display, e.g. mdi:car. See also custom icons. |
|
options |
An optional dictionary of overrides keyed by the option name that the given select entity supports. These options can be used to set or override submenu item parameters on a per-option basis. The format is as described in Submenu Items above. | |
permanent |
false |
If false the menu item is hidden when the menu has the hidden style and the menu is closed, otherwise it is shown (and sorted to the front). |
priority |
50 |
The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority 70 will order further to the left than a button with priority 60). Priority applies separately to matching and opposing groups (see alignment above). Minimum 0, maximum 100. |
style |
Position and style the element using CSS. | |
tap_action, double_tap_action, hold_action, start_tap, end_tap |
The actions to take when this item is interacted with. | |
title |
An optional title to display. |
See the select submenu example.
menu-state-icon
Add a state icon to the Advanced Camera Card menu that represents the state of a Home Assistant entity.
elements:
- type: custom:advanced-camera-card-menu-state-icon
# [...]
Configuration is similar to a stock Picture Elements State Icon.
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-menu-state-icon. |
|
alignment |
matching |
Whether this menu item should have an alignment that is matching the menu alignment or opposing the menu alignment. Can be used to create two separate groups of buttons on the menu. The priority option orders buttons within a given alignment. |
enabled |
true |
Whether or not to show this menu item. |
entity |
An optional Home Assistant entity for use with actions. | |
icon |
An required icon to display, e.g. mdi:car. See also custom icons. |
|
permanent |
false |
If false the menu item is hidden when the menu has the hidden style and the menu is closed, otherwise it is shown (and sorted to the front). |
priority |
50 |
The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority 70 will order further to the left than a button with priority 60). Priority applies separately to matching and opposing groups (see alignment above). Minimum 0, maximum 100. |
tap_action, double_tap_action, hold_action, start_tap, end_tap |
The actions to take when this item is interacted with. | |
state_color |
true |
Set to true to have icons colored when entity is active. |
style |
Position and style the element using CSS. | |
title |
An optional title to display. |
status-bar-icon
Add an arbitrary icon to the status bar.
elements:
- type: custom:advanced-camera-card-status-bar-icon
# [...]
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-status-bar-icon. |
|
actions |
Actions to performs when the status bar item is interacted with. See actions. | |
enabled |
true |
true to enable this status bar item, false to disable. |
exclusive |
false |
Whether or not this item should evict non-exclusive items from the status bar. |
expand |
false |
If false this status bar item will consume the minimum possible space, if true will expand to the available space. |
icon |
The icon to show in the status bar, e.g. mdi:camera-front. See also custom icons. |
|
priority |
50 |
The item priority. Higher priority items are ordered closer to the start of the status bar (i.e. an item with priority 70 will order further to the left than an item with priority 60). Minimum 0, maximum 100. |
severity |
An optional severity level, one of low, medium or high. Colors the item accordingly. |
|
sufficient |
false |
Whether or not this item is sufficient to display the status bar if it's otherwise hidden (e.g. with the popup status bar style). |
title |
An optional tooltip shown on hover. |
status-bar-image
Add an arbitrary image to the status bar.
elements:
- type: custom:advanced-camera-card-status-bar-image
# [...]
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-status-bar-image. |
|
actions |
Actions to performs when the status bar item is interacted with. See actions. | |
enabled |
true |
true to enable this status bar item, false to disable. |
exclusive |
false |
Whether or not this item should evict non-exclusive items from the status bar. |
expand |
false |
If false this status bar item will consume the minimum possible space, if true will expand to the available space. |
image |
The image to show in the status bar, e.g. https://my.site.com/status.png. |
|
priority |
50 |
The item priority. Higher priority items are ordered closer to the start of the status bar (i.e. an item with priority 70 will order further to the left than an item with priority 60). Minimum 0, maximum 100. |
severity |
An optional severity level, one of low, medium or high. Colors the item accordingly. |
|
sufficient |
false |
Whether or not this item is sufficient to display the status bar if it's otherwise hidden (e.g. with the popup status bar style). |
title |
An optional tooltip shown on hover. |
status-bar-string
Add an arbitrary string to the status bar.
elements:
- type: custom:advanced-camera-card-status-bar-string
# [...]
| Parameter | Default | Description |
|---|---|---|
type |
Must be custom:advanced-camera-card-status-bar-string. |
|
actions |
Actions to performs when the status bar item is interacted with. See actions. | |
enabled |
true |
true to enable this status bar item, false to disable. |
exclusive |
false |
Whether or not this item should evict non-exclusive items from the status bar. |
expand |
false |
If false this status bar item will consume the minimum possible space, if true will expand to the available space. |
string |
The string to show in the status bar, e.g. Intruder detected! |
|
priority |
50 |
The item priority. Higher priority items are ordered closer to the start of the status bar (i.e. an item with priority 70 will order further to the left than an item with priority 60). Minimum 0, maximum 100. |
severity |
An optional severity level, one of low, medium or high. Colors the item accordingly. |
|
sufficient |
false |
Whether or not this item is sufficient to display the status bar if it's otherwise hidden (e.g. with the popup status bar style). |
title |
An optional tooltip shown on hover. |
Fully expanded reference
Note
Actions are omitted for simplicity.
elements:
- type: custom:advanced-camera-card-menu-icon
alignment: matching
enabled: true
entity: light.office_main_lights
icon: mdi:car
permanent: false
priority: 50
style:
color: white
title: Vroom
- type: custom:advanced-camera-card-menu-state-icon
alignment: matching
enabled: true
entity: light.office_main_lights
icon: mdi:chair-rolling
permanent: false
priority: 50
state_color: true
style:
color: white
title: Office lights
- type: custom:advanced-camera-card-menu-submenu
alignment: matching
enabled: true
entity: light.office_main_lights
icon: mdi:menu
items:
- enabled: true
entity: light.office_main_lights
icon: mdi:lightbulb
selected: false
state_color: true
style:
color: white
tap_action:
action: toggle
title: Lights
- enabled: true
icon: mdi:google
selected: false
state_color: false
style:
color: white
tap_action:
action: url
url_path: https://www.google.com
title: Google
permanent: false
priority: 50
style:
color: white
title: Office lights
- type: custom:advanced-camera-card-menu-submenu-select
alignment: matching
enabled: true
entity: input_select.kitchen_scene
icon: mdi:lamps
options:
items:
scene.kitchen_cooking_scene:
enabled: true
icon: mdi:chef-hat
selected: false
state_color: true
style:
color: white
title: Cooking time!
scene.kitchen_tv_scene:
icon: mdi:television
title: TV!
permanent: false
priority: 50
style:
color: white
title: 'Kitchen Scene'
# Show a pig icon if a variety of conditions are met.
- type: custom:advanced-camera-card-conditional
elements:
- type: icon
icon: mdi:pig
title: Oink
style:
left: 300px
top: 100px
conditions:
- condition: view
views:
- live
- condition: fullscreen
fullscreen: true
- condition: expand
expand: true
- condition: camera
cameras: camera.front_door
- condition: media_loaded
media_loaded: true
- condition: display_mode
display_mode: single
- condition: triggered
triggered:
- camera.front_door
- condition: interaction
interaction: true
- condition: microphone
muted: true
connected: true
- condition: state
entity: light.office_main_lights
state: on
state_not: off
- condition: numeric_state
entity: sensor.light_level
above: 20
below: 100
- condition: user
users:
- 581fca7fdc014b8b894519cc531f9a04
- type: custom:advanced-camera-card-status-bar-string
enabled: true
exclusive: false
expand: false
string: 'Intruder alert!'
priority: 50
severity: high
sufficient: false
- type: custom:advanced-camera-card-status-bar-icon
enabled: true
exclusive: false
expand: false
icon: 'mdi:cow'
priority: 50
severity: medium
sufficient: false
- type: custom:advanced-camera-card-status-bar-image
enabled: true
exclusive: false
expand: false
image: https://my.site.com/status.png
priority: 50
severity: low
sufficient: false