From 459236fcdd8c4beaa77aedde0ca12d40537ce2ef Mon Sep 17 00:00:00 2001 From: Ryan Fleming Date: Wed, 27 Jan 2021 04:50:44 -0500 Subject: [PATCH] Camera Status and Motion record status (#44936) --- homeassistant/components/uvc/camera.py | 27 ++++++++++++++++++++++- tests/components/uvc/test_camera.py | 30 +++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/uvc/camera.py b/homeassistant/components/uvc/camera.py index 1988350eed3..4f5cfa3907e 100644 --- a/homeassistant/components/uvc/camera.py +++ b/homeassistant/components/uvc/camera.py @@ -1,4 +1,5 @@ """Support for Ubiquiti's UVC cameras.""" +from datetime import datetime import logging import re @@ -109,10 +110,28 @@ class UnifiVideoCamera(Camera): return 0 + @property + def state_attributes(self): + """Return the camera state attributes.""" + attr = super().state_attributes + if self.motion_detection_enabled: + attr["last_recording_start_time"] = timestamp_ms_to_date( + self._caminfo["lastRecordingStartTime"] + ) + return attr + @property def is_recording(self): """Return true if the camera is recording.""" - return self._caminfo["recordingSettings"]["fullTimeRecordEnabled"] + recording_state = "DISABLED" + if "recordingIndicator" in self._caminfo.keys(): + recording_state = self._caminfo["recordingIndicator"] + + return ( + self._caminfo["recordingSettings"]["fullTimeRecordEnabled"] + or recording_state == "MOTION_INPROGRESS" + or recording_state == "MOTION_FINISHED" + ) @property def motion_detection_enabled(self): @@ -235,3 +254,9 @@ class UnifiVideoCamera(Camera): def update(self): """Update the info.""" self._caminfo = self._nvr.get_camera(self._uuid) + + +def timestamp_ms_to_date(epoch_ms) -> datetime or None: + """Convert millisecond timestamp to datetime.""" + if epoch_ms: + return datetime.fromtimestamp(epoch_ms / 1000) diff --git a/tests/components/uvc/test_camera.py b/tests/components/uvc/test_camera.py index 9e904f82357..00c827b9973 100644 --- a/tests/components/uvc/test_camera.py +++ b/tests/components/uvc/test_camera.py @@ -1,4 +1,5 @@ """The tests for UVC camera module.""" +from datetime import datetime import socket import unittest from unittest import mock @@ -198,10 +199,14 @@ class TestUVC(unittest.TestCase): self.nvr.get_camera.return_value = { "model": "UVC Fake", "uuid": "06e3ff29-8048-31c2-8574-0852d1bd0e03", - "recordingSettings": {"fullTimeRecordEnabled": True}, + "recordingSettings": { + "fullTimeRecordEnabled": True, + "motionRecordEnabled": False, + }, "host": "host-a", "internalHost": "host-b", "username": "admin", + "lastRecordingStartTime": 1610070992367, "channels": [ { "id": "0", @@ -241,6 +246,29 @@ class TestUVC(unittest.TestCase): assert SUPPORT_STREAM == self.uvc.supported_features assert "uuid" == self.uvc.unique_id + def test_motion_recording_mode_properties(self): + """Test the properties.""" + self.nvr.get_camera.return_value["recordingSettings"][ + "fullTimeRecordEnabled" + ] = False + self.nvr.get_camera.return_value["recordingSettings"][ + "motionRecordEnabled" + ] = True + assert not self.uvc.is_recording + assert ( + datetime(2021, 1, 8, 1, 56, 32, 367000) + == self.uvc.state_attributes["last_recording_start_time"] + ) + + self.nvr.get_camera.return_value["recordingIndicator"] = "DISABLED" + assert not self.uvc.is_recording + + self.nvr.get_camera.return_value["recordingIndicator"] = "MOTION_INPROGRESS" + assert self.uvc.is_recording + + self.nvr.get_camera.return_value["recordingIndicator"] = "MOTION_FINISHED" + assert self.uvc.is_recording + def test_stream(self): """Test the RTSP stream URI.""" stream_source = yield from self.uvc.stream_source()