Skip to content

Commit

Permalink
Support multiple motion entites per camera (#50)
Browse files Browse the repository at this point in the history
* Support multiple motion entites per camera

Signed-off-by: Marcus Noble <[email protected]>

* Added some safety checks around missing entities.

* fix for no motion entity

* fix check

Signed-off-by: Marcus Noble <[email protected]>
Co-authored-by: Blake Niemyjski <[email protected]>
  • Loading branch information
AverageMarcus and niemyjski authored Oct 15, 2022
1 parent 14a5a5e commit c2c744c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 13 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Each entry in the camera list takes the following options

| Name | Type | Description | Default
| ---- | ---- | ----------- | -------
| entity | string | Camera entity_id | **Required**
| entity | string or array | Camera entity_id | **Required**
| motion_entity | string | entity_id of a binary sensor to use for motion detection (_uses state=='on' as motion detected_) | none

---
Expand Down Expand Up @@ -81,7 +81,29 @@ Clicking the _record button_ will grab as many images as it can (based on the up

Note: This functionality is not available in native app versions (iOS & Android) and depends on the browser/device's ability to download image files.

---
## Motion entities

Cameras can automatically be set to foccussed when motion is detected from the associated motion entities.

`motion_entity` can either be a single entity ID or a list of multiple entity IDs.

Note: The entities don't necessarily need to be motion sensors, they just need to be a binary sensor that is triggered when in the "on" state. E.g. a door sensor could also be used.

```yaml
views:
- title: Surveillance
icon: mdi:cctv
cards:
- type: custom:surveillance-card
cameras:
- entity: camera.front_porch
motion_entity: binary_sensor.front_porch_motion
- entity: camera.back_yard
motion_entity:
- binary_sensor.back_yard_motion
- binary_sensor.back_yard_gate
```

## Thanks

Expand Down
25 changes: 14 additions & 11 deletions surveillance-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,18 +114,21 @@ class SurveillanceCard extends LitElement {

const now = Date.now();
this.cameras = config.cameras.map((camera) => {
const entity = this.hass && hass.states[camera.entity];
const attributes = entity && entity.attributes;
const { states } = this.hass || {};
const entity = states[camera.entity];
const attributes = entity?.attributes;
const motionEntities = Array.isArray(camera.motion_entity) ? camera.motion_entity : [camera.motion_entity].filter(entityId => !!entityId);

return {
access_token: attributes && attributes.access_token,
access_token: attributes?.access_token,
entity: camera.entity,
motion_entity: camera.motion_entity,
name: attributes && attributes.friendly_name,
has_motion: this.hass && this.hass.states[camera.motion_entity].state === "on",
motion_entities: motionEntities,
name: attributes?.friendly_name,
has_motion: motionEntities.some(entityId => states[entityId]?.state === "on"),
last_motion: now,
last_update: now,
stream_url: "",
url: attributes && attributes.entity_picture,
url: attributes?.entity_picture,
};
});
this.updateCameras = this.throttle(() => this._updateCameras(), this.thumbInterval);
Expand All @@ -134,13 +137,13 @@ class SurveillanceCard extends LitElement {

_updateCameras() {
const now = Date.now();
const { states } = this.hass;
const { states } = this.hass || {};
const activatedCameras = [];

for (const camera of this.cameras) {
const hadMotion = camera.has_motion === true;
const { motion_entity } = camera;
camera.has_motion = motion_entity in states && states[motion_entity].state === "on";
const { motion_entities } = camera;
camera.has_motion = motion_entities.some(entityId => states[entityId]?.state === "on");
if (camera.has_motion) {
camera.last_motion = now;
}
Expand All @@ -155,7 +158,7 @@ class SurveillanceCard extends LitElement {
camera.last_update = now;
}

const attributes = camera.entity in states ? states[camera.entity].attributes || {} : {};
const attributes = states[camera.entity]?.attributes || {};
camera.access_token = attributes.access_token;
camera.name = attributes.friendly_name;
camera.url = `${attributes.entity_picture}&last_update=${camera.last_update}`;
Expand Down

0 comments on commit c2c744c

Please sign in to comment.