mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Amcrest: Add on/off support & attributes. Bump amcrest to 1.3.0 (#22418)
* Amcrest: Add on/off support & attributes to camera entity. Bump amcrest package to 1.3.0. Add support for turn_on & turn_off services. Add implementation of is_recording method, as well as brand, model, hardware_version, machine_name, serial_number, software_build and software_version attributes. Bump amcrest package to 1.3.0 required for above changes and also handles errors in storage commands which resolves #19982. * Update per review Rebase to upstream/dev. Remove video_enabled property and setter and replace with _enable_video_stream method. Remove static attributes from camera and sensors.
This commit is contained in:
parent
e78709c5f5
commit
82296aeb71
@ -12,7 +12,7 @@ from homeassistant.helpers import discovery
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
REQUIREMENTS = ['amcrest==1.2.7']
|
REQUIREMENTS = ['amcrest==1.3.0']
|
||||||
DEPENDENCIES = ['ffmpeg']
|
DEPENDENCIES = ['ffmpeg']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -3,7 +3,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.camera import (
|
from homeassistant.components.camera import (
|
||||||
Camera, SUPPORT_STREAM)
|
Camera, SUPPORT_ON_OFF, SUPPORT_STREAM)
|
||||||
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.helpers.aiohttp_client import (
|
from homeassistant.helpers.aiohttp_client import (
|
||||||
@ -39,18 +39,23 @@ class AmcrestCam(Camera):
|
|||||||
super(AmcrestCam, self).__init__()
|
super(AmcrestCam, self).__init__()
|
||||||
self._name = amcrest.name
|
self._name = amcrest.name
|
||||||
self._camera = amcrest.device
|
self._camera = amcrest.device
|
||||||
self._base_url = self._camera.get_base_url()
|
|
||||||
self._ffmpeg = hass.data[DATA_FFMPEG]
|
self._ffmpeg = hass.data[DATA_FFMPEG]
|
||||||
self._ffmpeg_arguments = amcrest.ffmpeg_arguments
|
self._ffmpeg_arguments = amcrest.ffmpeg_arguments
|
||||||
self._stream_source = amcrest.stream_source
|
self._stream_source = amcrest.stream_source
|
||||||
self._resolution = amcrest.resolution
|
self._resolution = amcrest.resolution
|
||||||
self._token = self._auth = amcrest.authentication
|
self._token = self._auth = amcrest.authentication
|
||||||
|
self._is_recording = False
|
||||||
|
self._model = None
|
||||||
self._snapshot_lock = asyncio.Lock()
|
self._snapshot_lock = asyncio.Lock()
|
||||||
|
|
||||||
async def async_camera_image(self):
|
async def async_camera_image(self):
|
||||||
"""Return a still image response from the camera."""
|
"""Return a still image response from the camera."""
|
||||||
from amcrest import AmcrestError
|
from amcrest import AmcrestError
|
||||||
|
|
||||||
|
if not self.is_on:
|
||||||
|
_LOGGER.error(
|
||||||
|
'Attempt to take snaphot when %s camera is off', self.name)
|
||||||
|
return None
|
||||||
async with self._snapshot_lock:
|
async with self._snapshot_lock:
|
||||||
try:
|
try:
|
||||||
# Send the request to snap a picture and return raw jpg data
|
# Send the request to snap a picture and return raw jpg data
|
||||||
@ -59,7 +64,8 @@ class AmcrestCam(Camera):
|
|||||||
return response.data
|
return response.data
|
||||||
except AmcrestError as error:
|
except AmcrestError as error:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
'Could not get camera image due to error %s', error)
|
'Could not get image from %s camera due to error: %s',
|
||||||
|
self.name, error)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def handle_async_mjpeg_stream(self, request):
|
async def handle_async_mjpeg_stream(self, request):
|
||||||
@ -94,6 +100,8 @@ class AmcrestCam(Camera):
|
|||||||
finally:
|
finally:
|
||||||
await stream.close()
|
await stream.close()
|
||||||
|
|
||||||
|
# Entity property overrides
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of this camera."""
|
"""Return the name of this camera."""
|
||||||
@ -102,9 +110,80 @@ class AmcrestCam(Camera):
|
|||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Return supported features."""
|
"""Return supported features."""
|
||||||
return SUPPORT_STREAM
|
return SUPPORT_ON_OFF | SUPPORT_STREAM
|
||||||
|
|
||||||
|
# Camera property overrides
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_recording(self):
|
||||||
|
"""Return true if the device is recording."""
|
||||||
|
return self._is_recording
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brand(self):
|
||||||
|
"""Return the camera brand."""
|
||||||
|
return 'Amcrest'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def model(self):
|
||||||
|
"""Return the camera model."""
|
||||||
|
return self._model
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def stream_source(self):
|
def stream_source(self):
|
||||||
"""Return the source of the stream."""
|
"""Return the source of the stream."""
|
||||||
return self._camera.rtsp_url(typeno=self._resolution)
|
return self._camera.rtsp_url(typeno=self._resolution)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""Return true if on."""
|
||||||
|
return self.is_streaming
|
||||||
|
|
||||||
|
# Other Entity method overrides
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Update entity status."""
|
||||||
|
from amcrest import AmcrestError
|
||||||
|
|
||||||
|
_LOGGER.debug('Pulling data from %s camera', self.name)
|
||||||
|
if self._model is None:
|
||||||
|
try:
|
||||||
|
self._model = self._camera.device_type.split('=')[-1].strip()
|
||||||
|
except AmcrestError as error:
|
||||||
|
_LOGGER.error(
|
||||||
|
'Could not get %s camera model due to error: %s',
|
||||||
|
self.name, error)
|
||||||
|
self._model = ''
|
||||||
|
try:
|
||||||
|
self.is_streaming = self._camera.video_enabled
|
||||||
|
self._is_recording = self._camera.record_mode == 'Manual'
|
||||||
|
except AmcrestError as error:
|
||||||
|
_LOGGER.error(
|
||||||
|
'Could not get %s camera attributes due to error: %s',
|
||||||
|
self.name, error)
|
||||||
|
|
||||||
|
# Other Camera method overrides
|
||||||
|
|
||||||
|
def turn_off(self):
|
||||||
|
"""Turn off camera."""
|
||||||
|
self._enable_video_stream(False)
|
||||||
|
|
||||||
|
def turn_on(self):
|
||||||
|
"""Turn on camera."""
|
||||||
|
self._enable_video_stream(True)
|
||||||
|
|
||||||
|
# Utility methods
|
||||||
|
|
||||||
|
def _enable_video_stream(self, enable):
|
||||||
|
"""Enable or disable camera video stream."""
|
||||||
|
from amcrest import AmcrestError
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._camera.video_enabled = enable
|
||||||
|
except AmcrestError as error:
|
||||||
|
_LOGGER.error(
|
||||||
|
'Could not %s %s camera video stream due to error: %s',
|
||||||
|
'enable' if enable else 'disable', self.name, error)
|
||||||
|
else:
|
||||||
|
self.is_streaming = enable
|
||||||
|
self.schedule_update_ha_state()
|
||||||
|
@ -75,19 +75,6 @@ class AmcrestSensor(Entity):
|
|||||||
"""Get the latest data and updates the state."""
|
"""Get the latest data and updates the state."""
|
||||||
_LOGGER.debug("Pulling data from %s sensor.", self._name)
|
_LOGGER.debug("Pulling data from %s sensor.", self._name)
|
||||||
|
|
||||||
try:
|
|
||||||
version, build_date = self._camera.software_information
|
|
||||||
self._attrs['Build Date'] = build_date.split('=')[-1]
|
|
||||||
self._attrs['Version'] = version.split('=')[-1]
|
|
||||||
except ValueError:
|
|
||||||
self._attrs['Build Date'] = 'Not Available'
|
|
||||||
self._attrs['Version'] = 'Not Available'
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._attrs['Serial Number'] = self._camera.serial_number
|
|
||||||
except ValueError:
|
|
||||||
self._attrs['Serial Number'] = 'Not Available'
|
|
||||||
|
|
||||||
if self._sensor_type == 'motion_detector':
|
if self._sensor_type == 'motion_detector':
|
||||||
self._state = self._camera.is_motion_detected
|
self._state = self._camera.is_motion_detected
|
||||||
self._attrs['Record Mode'] = self._camera.record_mode
|
self._attrs['Record Mode'] = self._camera.record_mode
|
||||||
|
@ -155,7 +155,7 @@ alarmdecoder==1.13.2
|
|||||||
alpha_vantage==2.1.0
|
alpha_vantage==2.1.0
|
||||||
|
|
||||||
# homeassistant.components.amcrest
|
# homeassistant.components.amcrest
|
||||||
amcrest==1.2.7
|
amcrest==1.3.0
|
||||||
|
|
||||||
# homeassistant.components.androidtv.media_player
|
# homeassistant.components.androidtv.media_player
|
||||||
androidtv==0.0.14
|
androidtv==0.0.14
|
||||||
|
Loading…
x
Reference in New Issue
Block a user