feat!: move recording_url and motion_region to attributes

these are no longer sensors themselves but attributes of the
motion sensor and they update when a change to motion happens

also, store_recording_in_media now returns the file name
instead of the full path
pull/106/head
Jeff Culverhouse 3 months ago
parent c16680bd04
commit 459a7f023a

@ -138,19 +138,12 @@ class AmcrestMixin:
"name": "Motion",
"uniq_id": self.mqtt_helper.dev_unique_id(device_id, "motion"),
"stat_t": self.mqtt_helper.stat_t(device_id, "binary_sensor", "motion"),
"jsn_atr_t": self.mqtt_helper.stat_t(device_id, "attributes"),
"json_attributes_topic": self.mqtt_helper.stat_t(device_id, "attributes"),
"payload_on": True,
"payload_off": False,
"device_class": "motion",
"icon": "mdi:eye-outline",
},
"motion_region": {
"p": "sensor",
"name": "Motion region",
"uniq_id": self.mqtt_helper.dev_unique_id(device_id, "motion_region"),
"stat_t": self.mqtt_helper.stat_t(device_id, "sensor", "motion_region"),
"icon": "mdi:map-marker",
},
"motion_snapshot": {
"p": "image",
"name": "Motion snapshot",
@ -243,15 +236,6 @@ class AmcrestMixin:
},
}
if "media" in self.config and "media_source" in self.config["media"]:
device["cmps"]["recording_url"] = {
"p": "sensor",
"name": "Recording url",
"uniq_id": self.mqtt_helper.dev_unique_id(device_id, "recording_url"),
"stat_t": self.mqtt_helper.stat_t(device_id, "sensor", "recording_url"),
"icon": "mdi:web",
}
if camera.get("is_doorbell", None):
device["cmps"]["doorbell"] = {
"p": "binary_sensor",
@ -283,8 +267,10 @@ class AmcrestMixin:
webrtc=rtc_url,
switch={"save_recordings": "ON" if "path" in self.config["media"] else "OFF"},
binary_sensor={"motion": False},
sensor={"motion_region": ""},
attributes={"recording_url": f"{self.config["media"]["media_source"]}/{camera["device_name"]}-latest.mp4"},
attributes={
"recording_url": f"{self.config["media"]["media_source"]}/{camera["device_name"]}-latest.mp4",
"region": "",
},
image={"motion_snapshot": ""},
)

@ -32,7 +32,10 @@ class EventsMixin:
event += ": snapshot"
elif payload["file"].endswith(".mp4"):
if "path" in self.config["media"] and self.states[device_id]["switch"].get("save_recordings", "OFF") == "ON":
await self.store_recording_in_media(device_id, payload["file"])
file_name = await self.store_recording_in_media(device_id, payload["file"])
if file_name:
self.upsert_state(device_id, attributes={"recording_url": f"{self.config["media"]["media_source"]}/{file_name}"})
needs_publish.add(device_id)
event += ": video"
elif event == "motion":
region = payload["region"] if payload["state"] != "off" else ""
@ -41,7 +44,7 @@ class EventsMixin:
self.upsert_state(
device_id,
binary_sensor={"motion": payload["state"]},
sensor={"motion_region": region},
attributes={"region": region},
)
needs_publish.add(device_id)
event += motion

@ -12,7 +12,7 @@ import threading
from types import FrameType
import yaml
from pathlib import Path
from datetime import datetime, timezone
from datetime import datetime
from typing import TYPE_CHECKING, Any, cast
if TYPE_CHECKING:
@ -272,11 +272,7 @@ class HelpersMixin:
self.logger.error(f"failed to save recording to {file_path}: {err!r}")
return None
self.upsert_state(
device_id,
media={"recording": str(file_path)},
sensor={"recording_time": datetime.now(timezone.utc).isoformat()},
)
# update the latest symlink
local_file = Path(f"./{file_name}")
latest_link = Path(f"{path}/{name}-latest.mp4")
@ -288,29 +284,7 @@ class HelpersMixin:
self.logger.error(f"failed to save symlink {latest_link} -> {local_file}: {err!r}")
pass
if "media_source" in self.config["media"]:
url = f"{self.config["media"]["media_source"]}/{file_name}"
self.upsert_state(device_id, sensor={"recording_url": url})
return url
self.upsert_state(
device_id,
media={"recording": file_path},
sensor={"recording_time": datetime.now(timezone.utc).isoformat()},
)
# update symlink to "lastest" recording
local_file = Path(f"./{file_name}")
latest_link = Path(f"{path}/{name}-latest.mp4")
if latest_link.is_symlink():
latest_link.unlink()
latest_link.symlink_to(local_file)
if "media_source" in self.config["media"]:
url = f"{self.config["media"]["media_source"]}/{file_name}"
self.upsert_state(device_id, sensor={"recording_url": url})
return url
return None
return file_name
def handle_signal(self: Amcrest2Mqtt, signum: int, _: FrameType | None) -> Any:
sig_name = signal.Signals(signum).name

@ -169,7 +169,11 @@ class PublishMixin:
for state, value in self.states[device_id].items():
if subject and state != subject:
continue
if isinstance(value, dict):
# Attributes need to be published as a single JSON object to the attributes topic
if state == "attributes" and isinstance(value, dict):
topic = self.mqtt_helper.stat_t(device_id, "attributes")
await asyncio.to_thread(self.mqtt_helper.safe_publish, topic, json.dumps(value))
elif isinstance(value, dict):
for k, v in value.items():
if sub and k != sub:
continue

Loading…
Cancel
Save