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>
592 lines
63 KiB
Markdown
592 lines
63 KiB
Markdown
# Cameras
|
|
|
|
The `cameras` block configures a list of cameras the card should support. This block is optional. When present, the first listed camera is the default.
|
|
|
|
```yaml
|
|
cameras:
|
|
- [...camera 0 (default camera)...]
|
|
- [...camera 1...]
|
|
- [...camera 2...]
|
|
```
|
|
|
|
The `cameras_global` block can be used to set defaults across multiple cameras.
|
|
|
|
```yaml
|
|
cameras_global:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `always_error_if_entity_unavailable` | `false` | When `true` and when `camera_entity` is specified, attempting to live stream this camera will always error out if the entity state is `unavailable`, even if the `live_provider` does not actually need the `camera_entity`. |
|
|
| `camera_entity` | | The Home Assistant camera entity. Used by most live providers for live stream data, and to auto-detect other camera metadata (e.g. Frigate camera name, camera title/icon). |
|
|
| `capabilities` | | Allows selective disabling of camera capabilities. See [`capabilities`](#capabilities). |
|
|
| `cast` | | Configuration that controls how this camera is "casted" / sent to media players. See [`cast`](#cast). |
|
|
| `dependencies` | | Other cameras that this camera should depend upon. See [`dependencies`](#dependencies). |
|
|
| `dimensions` | | Controls the dimensions and layout for media from this camera. See [`dimensions`](#dimensions). |
|
|
| `engine` | `auto` | The camera engine to use. If `auto` the card will attempt to choose the correct engine from the specified options. See [Engine](engine.md). |
|
|
| `frigate` | | Options for Frigate cameras. See [Frigate camera engine configuration](engine.md?id=frigate). |
|
|
| `icon` | Autodetected from `camera_entity` if that is specified. | The icon to use for this camera in the camera menu and in the next & previous controls when using the `icon` style. |
|
|
| `id` | `camera_entity`, `webrtc_card.entity` or `frigate.camera_name` if set (in that preference order). If none of these are set, the camera has no `id` and cannot be referenced by name in conditions or actions. | An optional identifier to use throughout the card configuration to refer unambiguously to this camera. This `id` may be used in [conditions](../conditions-triggers.md), dependencies or custom [actions](../actions/README.md) to refer to a given camera unambiguously. |
|
|
| `live_provider` | `auto` | The choice of live stream provider. See [Live Provider](live-provider.md). |
|
|
| `media` | | Controls the default media configuration (e.g. thumbnails) for this camera. See [`media`](#media). |
|
|
| `proxy` | | Controls whether/how content is proxied via [hass-web-proxy-integration](https://github.com/dermotduffy/hass-web-proxy-integration) (must be installed separately). See [`proxy`](#proxy). |
|
|
| `title` | Autodetected from `camera_entity` if that is specified. | A friendly name for this camera to use in the card. |
|
|
| `triggers` | | Define what should cause this camera to update/trigger. See [`triggers`](#triggers). |
|
|
| `webrtc_card` | | The WebRTC entity/URL to use for this camera with the `webrtc-card` live provider. See [Live Provider](live-provider.md?id=webrtc_card). |
|
|
|
|
## `capabilities`
|
|
|
|
The `capabilities` block allows selected disabling of auto-detected camera capabilities. This is rarely used, with substreams being a notable exception.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
capabilities:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
| `disable` | | A list of camera capabilities to disable. By default all capabilities supported by the camera are enabled. |
|
|
| `disable_except` | | A list of camera capabilities to leave enabled if supported. Everything else will be disabled. |
|
|
| `force` | | A list of capabilities to force-enable instead of auto-detecting them. Currently only supports `2-way-audio`. `disable` / `disable_except` take precedence over `force`. |
|
|
|
|
### Capabilities
|
|
|
|
| Capability | Purpose |
|
|
| ----------------------- | ------------------------------------------------------------------------------------------------- |
|
|
| `clips` | Clips can be fetched from the camera. |
|
|
| `remote-control-entity` | The camera can be selected by a [Camera Remote Control Entity](../remote-control.md?id=entities). |
|
|
| `favorite-events` | Events can be favorited. |
|
|
| `favorite-recordings` | Recordings can be favorited. |
|
|
| `live` | Live video can be received from the camera. |
|
|
| `menu` | The camera should show up in the card camera menu. |
|
|
| `ptz` | The camera can be PTZ controlled. |
|
|
| `recordings` | Recordings can be fetched from the camera. |
|
|
| `reviews` | Review items (alerts/detections) can be fetched from the camera. |
|
|
| `seek` | Clips can be seeked / scrubbed by the timeline. |
|
|
| `snapshots` | Snapshots can be fetched from the camera. |
|
|
| `substream` | The camera can be used as a substream on another camera. |
|
|
| `trigger` | The camera can be triggered. |
|
|
| `2-way-audio` | The camera can be used for 2-way audio. |
|
|
|
|
> [!NOTE]
|
|
> If using a camera only as a `substream`, don't forget to keep both the
|
|
> `substream` and `ptz` capabilities enabled if you wish to use PTZ controls for
|
|
> the substream.
|
|
|
|
## `cast`
|
|
|
|
The `cast` block configures how a camera is cast / sent to media players.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
cast:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `dashboard` | | Configuration for the dashboard to cast. See [Dashboard Configuration](#dashboard-configuration). |
|
|
| `method` | `standard` | Whether to use `standard` media casting to send the live view to your media player, or to instead cast a `dashboard` you have manually setup. Casting a dashboard supports a much wider variety of video media, including low latency video providers (e.g. `go2rtc`). This setting has no effect on casting non-live media. |
|
|
|
|
See the [dashboard method cast example](../../examples.md?id=cast-a-dashboard).
|
|
|
|
### Dashboard Configuration
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
cast:
|
|
dashboard:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `dashboard_path` | | A required field that specifies the name of the dashboard to cast. You can see this name in your HA URL when you visit the dashboard. |
|
|
| `view_path` | | A required field that specifies view/"tab" on that dashboard to cast. This is the value you have specified in the `url` field of the view configuration on the dashboard. |
|
|
|
|
## `dependencies`
|
|
|
|
The `dependencies` block configures other cameras as dependents of this camera. Dependent cameras have their media fetched and merged with this camera by default, and offer their respective live views as 'substreams' of the main (depended upon) camera. Configuration is under:
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
dependencies:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `all_cameras` | `false` | Shortcut to specify all other cameras as dependent cameras. |
|
|
| `cameras` | | An optional list of other camera identifiers (see `id` parameter). If specified the card will fetch media for this camera and _also_ recursively for the named cameras by default. Live views for the involved cameras will be available as 'substreams' of the main (depended upon) camera. All dependent cameras must themselves be a configured camera in the card. This can be useful to group events for cameras that are close together, to show multiple related live views, to always have clips/snapshots show fully merged events across all cameras or to show events for the `birdseye` camera that otherwise would not have events itself. |
|
|
|
|
## `dimensions`
|
|
|
|
The `dimensions` block configures the dimensions and layout of media of a given camera (see [Card Dimensions](../dimensions.md) to set the dimensions of the whole card and not just a single camera).
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
dimensions:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| -------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `aspect_ratio` | | An optional aspect ratio for media from this camera which will be used in `live` or media viewer related views (e.g. `clip`, `snapshot` and `recording`). Format is the same as the parameter of the same name under the [dimensions block](../dimensions.md) (which controls dimensions for the whole card), e.g. `16 / 9`. |
|
|
| `grid` | | Grid layout configuration for this camera when displayed in grid mode. See [Grid Configuration](#grid-configuration). |
|
|
| `layout` | | How the media should be laid out _within_ the camera dimensions. See [Layout Configuration](#layout-configuration). |
|
|
| `rotation` | `0` | Rotates the camera clockwise by `0`, `90`, `180` or `270` degrees. |
|
|
|
|
> [!NOTE]
|
|
> Use of `rotation` causes the browser to rotate the video player, unavoidably _including_ rotating the builtin video controls on the player, which may be distracting or confusing (e.g. upside down controls). Builtin controls can be disabled using the [`live.controls.builtin` parameter](../live.md?id=controls). Rotation is not available in iOS fullscreen, due to the limited fullscreen support offered by that OS.
|
|
|
|
> [!TIP]
|
|
> When rotation is configured, directional PTZ actions (`left`, `right`, `up`, `down`) are automatically rotated to match the camera's orientation.
|
|
|
|
> [!WARNING]
|
|
> Rotating the camera incurs a rendering performance penalty. Always rotate "upstream" if possible (e.g. in your camera settings).
|
|
|
|
### Grid Configuration
|
|
|
|
The `grid` block configures how this camera appears in grid display mode.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
dimensions:
|
|
grid:
|
|
width_factor: 2
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `width_factor` | `1` | Width multiplier for this camera in grid mode (minimum: `0.1`). When selected, width becomes `width_factor * grid_selected_width_factor`, capped at 100%. |
|
|
|
|
## `media`
|
|
|
|
The `media` block configures the default media options for this camera which
|
|
defines which media is shown as thumbnails and on the timeline.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
media:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `type` | `auto` | The default media type to show for this camera. One of `auto`, `events`, `recordings`, `reviews` or `folder`. See [Media Types](#media-types) for description of each. |
|
|
| `events_type` | `all` | If `type` is `events`, what subtype of events to show. One of `clips`, `snapshots` or `all` (default). |
|
|
| `reviewed` | `unreviewed` | Whether to filter the media based on review status. One of `unreviewed` (default, shows only unreviewed media), `reviewed` (shorts only reviewed media) or `all` (show regardless of whether reviewed or unreviewed). Only relevant when `type` is `reviews` or `auto`. |
|
|
| `folders` | | An optional list of folder IDs to use when `type` is `folder`. If not specified, and `type` is `folder`, will default to showing the default (first) configured folder. See [Folder Configuration](../folders.md) and the [worked example](../../examples.md?id=show-a-folder-as-a-cameras-default-media). |
|
|
|
|
### Media Types
|
|
|
|
Not all camera engines support all media types. See [Camera Engines](engine.md) for details.
|
|
|
|
| Type | Description |
|
|
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `events` | Typically represents an interesting event recorded from the camera, in either a video clip or image snapshot (see `events_type` parameter). |
|
|
| `recordings` | Typically represents continuous video recordings from the camera. |
|
|
| `reviews` | Typically represents an alert / detection of some kind that the user can review. |
|
|
| `folder` | Arbitrary media from a [folder](../folders.md), e.g. a Home Assistant media folder. |
|
|
| `auto` | Automatically prioritize available media based on camera capabilities. Order of precedence: `reviews` > `clips` > `snapshots` > `recordings`. |
|
|
|
|
### Layout Configuration
|
|
|
|
The `layout` block configures the fit and position of the media _within_ the camera dimensions (in order to control the dimensions for the whole card see [the card dimensions configuration](../dimensions.md) ).
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
dimensions:
|
|
layout:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ---------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `fit` | `contain` | If `contain`, the media is contained within the camera container/card and letterboxed if necessary. If `cover`, the media is expanded proportionally (i.e. maintaining the media aspect ratio) until the camera/card dimensions are fully covered. If `fill`, the media is stretched to fill the camera/card dimensions (i.e. ignoring the media aspect ratio). See [CSS object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/object-fit) for technical details and a visualization. Note that if `aspect_ratio` is also set, this is controlling the behavior "within" that aspect-ratio, otherwise it's within the container for the camera (which is effectively the whole card for single card configurations). |
|
|
| `pan` | | A dictionary that may contain an `x` and `y` percentage (`0` - `100`) to control the position of the media when "digitally zoomed in" (see `zoom` parameter). This can be effectively used to "pan"/cut the media shown. A value of `0` means maximally to the left or top of the media, a value of `100` means maximally to the right or bottom of the media. See [visualizations](#layout-visualizations) below. |
|
|
| `position` | | A dictionary that may contain an `x` and `y` percentage (`0` - `100`) to control the position of the media when the fit is `cover` (for other values of `fit` this option has no effect). This can be effectively used to "pan"/cut the media shown. At any given time, only one of `x` and `y` will have an effect, depending on whether media width is larger than the camera/card dimensions (in which case `x` controls the position) or the media height is larger than the camera/card dimensions (in which case `y` controls the position). A value of `0` means maximally to the left or top of the media, a value of `100` means maximally to the right or bottom of the media. See [CSS object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/object-position) for technicals. See [visualizations](#layout-visualizations) below. |
|
|
| `view_box` | | A dictionary that may contain a `top`, `bottom`, `left` and `right` percentage (`0` - `100`) to precisely crop what part of the media to show by specifying a % inset value from each side. Browsers apply this cropping after `position` and `fit` have been applied. Unlike `zoom`, the user cannot dynamically zoom back out -- however the builtin media controls will work as normal. See [visualizations](#layout-visualizations) below. Limited [browser support](https://caniuse.com/mdn-css_properties_object-view-box):    |
|
|
| `zoom` | `1.0` | A value between `1.0` and `10.0` inclusive that defines how much additional "digital zoom" to apply to this camera by default. Unlike with `view_box` the user can easily "zoom back out". Often used in conjuction with `pan`. When zoomed in the [builtin browser media controls](../live.md?id=controls) will automatically be disabled (as otherwise they would be enlarged also). |
|
|
|
|
> [!NOTE]
|
|
> Layout operations are effectively applied in this order: `fit`, `position`, `view_box`, `zoom` then `pan`.
|
|
|
|
See [media layout examples](../../examples.md?id=media-layout).
|
|
|
|
#### Layout **Visualizations**
|
|
|
|
##### `fit`
|
|
|
|

|
|
|
|
##### `position`: When media is shorter than dimensions height
|
|
|
|

|
|
|
|
##### `position`: When media is thinner than dimensions width
|
|
|
|

|
|
|
|
#### `view_box`: Precise media cropping
|
|
|
|

|
|
|
|
#### `pan` and `zoom`: Predefined panning and zooming
|
|
|
|

|
|
|
|
### Order of Operations
|
|
|
|
Camera `dimensions` settings are applied in this order:
|
|
|
|
- `aspect_ratio` defines the aspect ratio of the video player ...
|
|
- ... then `fit`, `position` and `view_box` defines how the media is laid out within that ratio ...
|
|
- ... then `rotation` defines whether the video is rotated ...
|
|
- ... then `zoom` and `pan` define the zoom and pan settings respectively.
|
|
|
|
## `ptz`
|
|
|
|
Configure the PTZ actions taken for a camera (not to be confused with configuration of the PTZ _controls_, see [Live PTZ Controls](../live.md?id=ptz) or [Media Viewer PTZ Controls](../media-viewer.md?id=ptz)). Manually configured actions override any auto-detected actions.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
ptz:
|
|
# [...]
|
|
```
|
|
|
|
### Movement types
|
|
|
|
Generally PTZ cameras/integrations may support two kinds of PTZ actions:
|
|
|
|
- `relative`: Single relative steps, e.g. "Pan to the left one step".
|
|
- `continuous`: Separate start and stop, e.g. "Start panning to the left", following by a later command "Stop panning".
|
|
|
|
The card supports both, and with the help of the
|
|
`r2c_delay_between_calls_seconds` and `c2r_delay_between_calls_seconds` can
|
|
translate between them where necessary. See the [ONVIF
|
|
specification](https://www.onvif.org/specs/srv/ptz/ONVIF-PTZ-Service-Spec.pdf)
|
|
for more details on the distinction between `relative` and `continuous`.
|
|
|
|
The card UI (e.g. PTZ controls) will always try to call the `continuous` variety
|
|
to allow for precise/smooth controls, and if unavailable will translate multiple
|
|
`relative` steps with optional delays between each step. Manually configured
|
|
[actions](../actions/README.md) may be configured to call either variety.
|
|
|
|
When PTZ actions are manually set in the config, they will replace the
|
|
auto-detected actions. For example if `actions_left` is set for a Frigate
|
|
camera, it will be used for all `left` PTZ actions even though Frigate cameras
|
|
natively support continuous actions (`actions_left_start`, `actions_left_stop`).
|
|
|
|
> [!NOTE]
|
|
> Frigate auto-detected PTZ actions will always be `continuous` as this is what
|
|
> the integration currently offers.
|
|
|
|
### Parameters
|
|
|
|
| Option | Default | Description |
|
|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `actions_left`, `actions_right`, `actions_up`, `actions_down`, `actions_zoom_in`, `actions_zoom_out` | Set by camera [engine](./engine.md) of the selected camera | The [perform-action](../actions/stock/README.md?id=perform-action) action that will be called for each PTZ action for relative movements. |
|
|
| `actions_left_start`, `actions_left_stop`, `actions_right_start`, `actions_right_stop`,`actions_up_start`, `actions_up_stop`,`actions_down_start`, `actions_down_stop`,`actions_zoom_in_start`, `actions_zoom_in_stop`,`actions_zoom_out_start`, `actions_zoom_out_stop` | Set by camera [engine](./engine.md) of the selected camera | The [perform-action](../actions/stock/README.md?id=perform-action) action that will be called for each PTZ action for continous movements. Both a `_start` and `_stop` variety must be provided for an action to be usable. |
|
|
| `c2r_delay_between_calls_seconds` | `0.2` | When the camera is configured with continuous actions only (e.g. `left_start` and `left_stop`, but not `left`), if something requests a relative action (e.g. a manually configured [action](../actions/README.md)), then `start` will be called, followed by a delay of this number of seconds and finally `stop` will be called. Cameras / integrations that are slower to respond to continuous steps may need to increase this value to avoid the continuous motion being too small. Cameras / integrations that are rapid to respond may need to decrease this value to avoid the "relative step" being too large. |
|
|
| `data_left`, `data_right`, `data_up`, `data_down`, `data_zoom_in`, `data_zoom_out`, `data_home` | | Shorthand for relative actions that call the service defined by the `service` parameter, with the data provided in this argument. Internally, this is just translated into the longer-form `actions_[action]`. `data_home` is automatically converted into a `home` preset. If both `actions_X` and `data_X` are specified, `actions_X` takes priority. This is compatible with [AlexxIT's WebRTC Card PTZ configuration](https://github.com/AlexxIT/WebRTC/wiki/PTZ-Config-Examples). |
|
|
| `data_start_left`, `data_end_left`, `data_start_right`, `data_end_right`, `data_start_up`, `data_end_up`, `data_start_down`, `data_end_down`, `data_start_zoom_in`, `data_end_zoom_in`, `data_start_zoom_out`, `data_end_zoom_out` | | Shorthand for continuous actions that call the service defined by the `service` parameter, with the data provided in this argument. Internally, `data_start_*` and `data_end_*` are translated into `actions_*_start` and `actions_*_stop`. If an equivalent `actions_` key already exists, it takes priority. This uses [AlexxIT's WebRTC Card](https://github.com/AlexxIT/WebRTC/wiki/PTZ-Config-Examples) key ordering. Both a `data_start_` and `data_end_` variety must be provided for an action to be usable. |
|
|
| `presets` | | PTZ preset actions. See [`presets`](#presets). |
|
|
| `r2c_delay_between_calls_seconds` | `0.5` | When the camera is configured with relative actions only (e.g. `left` but not `left_start` and `left_stop`), if something requests a continuous action (e.g. the card PTZ controls have a button held down), then a delay of this number of seconds will be inserted between each call of the relative action. Cameras / integrations that are slower to respond to relative steps may need to increase this value to avoid multiple simultaneous actions being sent. Cameras / integrations that are rapid to respond may need to decrease this value to increase the appearance of one single continuous motion. |
|
|
| `service` | | An optional Home Assistant service to call when the `data_` parameters are used. |
|
|
|
|
### `presets`
|
|
|
|
Configures named PTZ presets. If presets are provided in the configuration, they
|
|
will take precedence over auto-detected presets from the camera.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
ptz:
|
|
presets:
|
|
[preset_name]:
|
|
? [action]
|
|
```
|
|
|
|
`[action]` is any [perform-action](../actions/stock/README.md?id=perform-action) action.
|
|
|
|
> [!NOTE]
|
|
> The 'Home' PTZ button (:house:) activates the first preset.
|
|
|
|
> [!WARNING]
|
|
> WebRTC Card's `data_long_*` parameters are not supported.
|
|
|
|
## `proxy`
|
|
|
|
Configures whether and how the content is proxied via
|
|
[hass-web-proxy-integration](https://github.com/dermotduffy/hass-web-proxy-integration)
|
|
(this must be installed separately). This allows fetching media or live streams
|
|
**through** the Home Assistant process itself, allowing the card to access
|
|
resources it otherwise would not be able to directly access.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
proxy:
|
|
# [...]
|
|
```
|
|
|
|

|
|
|
|
[](../common/proxy-warning.md ':include')
|
|
|
|
For live streams, only the `go2rtc` [live provider](./live-provider.md) currently supports live stream proxying.
|
|
|
|
For media, not all [engines](./engine.md) benefit from proxying:
|
|
|
|
| Engine | Purpose of proxying |
|
|
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `frigate` | The Frigate integration already comes with a built-in proxy, so this functionality does not serve any purpose for `frigate`. |
|
|
| `reolink`, `motioneye` | May be used to fetch videos in cases where the browser may not be able to access the camera/NVR, or the camera/NVR may use a self-signed SSL certificate that your browser would otherwise reject due to [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Mixed_content). |
|
|
| `generic` | `generic` cameras do not have media, so proxying currently would serve no purpose. |
|
|
|
|
Proxying parameters:
|
|
|
|
| Option | Default | Description |
|
|
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
| `live` | `auto` | Whether or not to proxy live streams. `true` to proxy (will show an error if the proxy integration is unavailable), `false` to not proxy, or `auto` to allow the camera engine to decide whether to proxy or not. If `auto` resolves to proxying, the card will still fall back to the original URL if the proxy integration is unavailable. Not all [live providers](./live-provider.md) support proxying live streams. |
|
|
| `media` | `auto` | Whether or not to proxy media items. `true` to proxy (will show an error if the proxy integration is unavailable), `false` to not proxy, or `auto` to allow the camera engine to decide whether to proxy or not. If `auto` resolves to proxying, the card will still fall back to the original URL if the proxy integration is unavailable. |
|
|
| `dynamic` | `true` | Whether to dynamically (at the time) request proxying of the required media item, or rely on statically user-configured pre-existing proxying. See the [hass-web-proxy-integration documentation](https://github.com/dermotduffy/hass-web-proxy-integration). |
|
|
| `ssl_verification` | `auto` | Whether to verify the validity of SSL certificates. If `true` always verifies, if `false` never verifies and if `auto` the [engine](./engine.md) decides the best setting for that camera ecosystem. |
|
|
| `ssl_ciphers` | `auto` | Whether to use `default`, `intermediate`, `insecure` or `modern` SSL ciphers. See the [Home Assistant code](https://github.com/home-assistant/core/blob/dev/homeassistant/util/ssl.py) for the precise list of SSL ciphers each implies. If `auto` the [engine](./engine.md) decides the best setting for that camera ecosystem. |
|
|
|
|
## `triggers`
|
|
|
|
The `triggers` block configures what triggers a camera. Triggering can be used
|
|
to activate an action (e.g. view a camera in live, reset the card to the default
|
|
view). See [`view.triggers`](../view.md?id=triggers) to control what happens when a
|
|
camera is triggered.
|
|
|
|
> [!TIP]
|
|
> A camera's `triggers` are not the same as an
|
|
> [automation's](../automations.md) [`triggers`](../conditions-triggers.md). Camera
|
|
> triggers take action on per-camera events such as motion; automation triggers
|
|
> _initiate [automations](../automations.md)_. They share only the word
|
|
> "trigger".
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
triggers:
|
|
# [...]
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| -------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `doorbell` | `false` | Whether to trigger the camera by automatically detecting an [HA `event.*` entity](https://www.home-assistant.io/integrations/event/#device-class) with `device_class: doorbell` on the same HA device as the camera entity. Requires `camera_entity` to be set. |
|
|
| `entities` | | Whether to not to trigger the camera when the state of any Home Assistant entity becomes active (i.e. state becomes `on` or `open`). |
|
|
| `events` | `[]` | A list of Home Assistant bus events to trigger on, with optional payload filtering. Each entry subscribes to one HA event type and fires the camera trigger every time that event is dispatched (and the optional `event_data` filter matches). See [`events`](#events). |
|
|
| `media_events` | `[]` | Whether to trigger the camera when `events` occur (whether or not media is available) or whenever updated `clips` or `snapshots` are detected. Detection support varies by camera [engine](engine.md). |
|
|
| `motion` | `false` | Whether to not to trigger the camera by automatically detecting and using the motion `binary_sensor` for this camera. This autodetection only works for Frigate cameras, and only when the motion `binary_sensor` entity has been enabled in Home Assistant. |
|
|
| `occupancy` | `false` | Whether to not to trigger the camera by automatically detecting and using the occupancy `binary_sensor` for this camera and its configured zones and labels. This autodetection only works for Frigate cameras, and only when the occupancy `binary_sensor` entity has been enabled in Home Assistant. If this camera has configured zones, only occupancy sensors for those zones are used -- if the overall _camera_ occupancy sensor is also required, it can be manually added to `entities`. If this camera has configured labels, only occupancy sensors for those labels are used. |
|
|
| `reviews` | | Configuration for triggering on review items. Currently only supported by Frigate. See [`reviews`](#reviews). |
|
|
|
|
### `events`
|
|
|
|
The `events` list subscribes the card to Home Assistant bus events. Each entry maps to a single `event_type` (e.g. `zha_event`, `deconz_event`, or any custom event your automations fire). Because events are momentary (HA fires them once, with no on/off), the card treats each fire as an instantaneous trigger; the visible "active" window is then controlled by [`view.triggers.event_hold_seconds`](../view.md?id=triggers).
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.front_door
|
|
triggers:
|
|
events:
|
|
# Trigger only on a specific ZHA device firing its 'press' command.
|
|
- event_type: zha_event
|
|
event_data:
|
|
device_ieee: '00:11:22:33:44:55:66:77'
|
|
command: press
|
|
# No `event_data` filter -- triggers every time this event is fired.
|
|
- event_type: home_doorbell_pressed
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `event_type` | | The Home Assistant event type to subscribe to (e.g. `zha_event`, `deconz_event`, or a custom event name fired by one of your automations). Same field name and meaning as in HA automation YAML. |
|
|
| `event_data` | | Optional dictionary of key/value pairs the event's payload must contain for this entry to trigger. Matching is a deep subset (every key listed must be present in the event payload and match; extra keys in the event are ignored). Same field name and semantics as in HA automation YAML. Omit entirely to trigger on every fire of this `event_type`. |
|
|
|
|
> [!TIP] Shared `event_type` values like `zha_event` and `deconz_event` fire for **every** device on that integration. Without an `event_data` filter the camera would trigger on any Zigbee/deCONZ device press in your home. Use `event_data` to narrow down to the specific device you care about; you can copy values straight out of **Developer tools → Events** in Home Assistant.
|
|
|
|
### `reviews`
|
|
|
|
The `reviews` block configures triggering based on review items (e.g., alerts and detections from Frigate).
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.office
|
|
triggers:
|
|
reviews:
|
|
severities:
|
|
- high
|
|
description: true
|
|
```
|
|
|
|
| Option | Default | Description |
|
|
| ------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `severities` | `[high]` | An array of severity levels to trigger on. Possible values: `high` (equivalent to Frigate alerts), `medium` (equivalent to Frigate detections), `low`. At least one severity must be configured for review triggers to be active. |
|
|
| `description` | `true` | Whether to trigger on review description updates (e.g. Frigate GenAI descriptions). Severity must also match. |
|
|
|
|
## Fully expanded reference
|
|
|
|
[](../common/expanded-warning.md ':include')
|
|
|
|
See [Engines](engine.md) and [Live Providers](live-provider.md) for other options nested under `cameras`.
|
|
|
|
```yaml
|
|
cameras:
|
|
- camera_entity: camera.front_Door
|
|
# Show events for camera-2 when this camera is viewed.
|
|
dependencies:
|
|
all_cameras: false
|
|
cameras:
|
|
- camera-2
|
|
triggers:
|
|
motion: false
|
|
occupancy: true
|
|
entities:
|
|
- binary_sensor.front_door_sensor
|
|
events:
|
|
- event_type: zha_event
|
|
event_data:
|
|
device_ieee: '00:11:22:33:44:55:66:77'
|
|
command: press
|
|
media_events:
|
|
- events
|
|
- clips
|
|
- snapshots
|
|
reviews:
|
|
severities:
|
|
- high
|
|
description: true
|
|
cast:
|
|
method: standard
|
|
dimensions:
|
|
aspect_ratio: 16:9
|
|
layout:
|
|
fit: contain
|
|
position:
|
|
x: 50
|
|
y: 50
|
|
always_error_if_entity_unavailable: false
|
|
- camera_entity: camera.entrance
|
|
icon: 'mdi:car'
|
|
title: 'Front entrance'
|
|
# Custom identifier for the camera to refer to it above.
|
|
id: 'camera-2'
|
|
triggers:
|
|
motion: false
|
|
occupancy: true
|
|
entities:
|
|
- binary_sensor.entrance_sensor
|
|
dependencies:
|
|
all_cameras: false
|
|
- camera_entity: camera.zoomed
|
|
dimensions:
|
|
layout:
|
|
zoom: 2.0
|
|
pan:
|
|
x: 50
|
|
y: 50
|
|
- camera_entity: camera.manual-ptz
|
|
ptz:
|
|
c2r_delay_between_calls_seconds: 0.2
|
|
r2c_delay_between_calls_seconds: 0.5
|
|
# Relative action (only `left` shown)
|
|
actions_left:
|
|
action: perform-action
|
|
perform_action: service.of_your_choice
|
|
data:
|
|
device: '048123'
|
|
cmd: left
|
|
# Continuous action (only `right` shown)
|
|
actions_right_start:
|
|
action: perform-action
|
|
perform_action: service.of_your_choice
|
|
data:
|
|
device: '048123'
|
|
cmd: right
|
|
phase: start
|
|
actions_right_stop:
|
|
action: perform-action
|
|
perform_action: service.of_your_choice
|
|
data:
|
|
device: '048123'
|
|
phase: stop
|
|
# Equivalent relative short form (only `up` shown)
|
|
service: service.send_command
|
|
data_up:
|
|
device: '048123'
|
|
cmd: up
|
|
# Equivalent continuous short form (only `down` shown)
|
|
service: service.send_command
|
|
data_up_start:
|
|
device: '048123'
|
|
cmd: down
|
|
phase: start
|
|
data_up_stop:
|
|
device: '048123'
|
|
cmd: down
|
|
phase: stop
|
|
presets:
|
|
# Preset using long form.
|
|
armchair:
|
|
action: perform-action
|
|
perform_action: service.of_your_choice
|
|
data:
|
|
device: '048123'
|
|
cmd: preset
|
|
preset: armchair
|
|
# Preset using short form.
|
|
service: service.of_your_choice
|
|
window:
|
|
device: '048123'
|
|
cmd: preset
|
|
preset: window
|
|
- camera_entity: camera.needs_proxy
|
|
proxy:
|
|
live: auto
|
|
media: auto
|
|
dynamic: true
|
|
ssl_verification: auto
|
|
ssl_ciphers: auto
|
|
- camera_entity: camera.capabilities_reference
|
|
capabilities:
|
|
disable_except:
|
|
- clips
|
|
- favorite-events
|
|
- favorite-recordings
|
|
- live
|
|
- menu
|
|
- ptz
|
|
- recordings
|
|
- seek
|
|
- snapshots
|
|
- substream
|
|
- trigger
|
|
- 2-way-audio
|
|
disable:
|
|
# Capabilities to selectively disable.
|
|
- camera_entity: camera.rotated
|
|
dimensions:
|
|
rotation: 90
|
|
cameras_global:
|
|
triggers:
|
|
motion: false
|
|
```
|