2019-02-13 20:21:14 +00:00
|
|
|
"""Support for Axis camera streaming."""
|
2017-05-12 15:51:54 +00:00
|
|
|
|
2019-04-05 17:14:54 +00:00
|
|
|
from homeassistant.components.camera import SUPPORT_STREAM
|
2019-03-17 03:44:05 +00:00
|
|
|
from homeassistant.components.mjpeg.camera import (
|
2019-01-03 18:56:36 +00:00
|
|
|
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, MjpegCamera, filter_urllib3_logging)
|
2018-01-21 06:35:38 +00:00
|
|
|
from homeassistant.const import (
|
2019-03-24 15:16:50 +00:00
|
|
|
CONF_AUTHENTICATION, CONF_DEVICE, CONF_HOST, CONF_MAC, CONF_NAME,
|
|
|
|
CONF_PASSWORD, CONF_PORT, CONF_USERNAME, HTTP_DIGEST_AUTHENTICATION)
|
2019-03-29 14:20:12 +00:00
|
|
|
from homeassistant.core import callback
|
2019-03-24 15:16:50 +00:00
|
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
2017-05-12 15:51:54 +00:00
|
|
|
|
2019-03-24 15:16:50 +00:00
|
|
|
from .const import DOMAIN as AXIS_DOMAIN
|
2017-05-12 15:51:54 +00:00
|
|
|
|
2019-03-24 15:16:50 +00:00
|
|
|
AXIS_IMAGE = 'http://{}:{}/axis-cgi/jpg/image.cgi'
|
|
|
|
AXIS_VIDEO = 'http://{}:{}/axis-cgi/mjpg/video.cgi'
|
2019-04-05 17:14:54 +00:00
|
|
|
AXIS_STREAM = 'rtsp://{}:{}@{}/axis-media/media.amp?videocodec=h264'
|
2017-05-12 15:51:54 +00:00
|
|
|
|
|
|
|
|
2019-03-24 15:16:50 +00:00
|
|
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
|
|
|
"""Set up the Axis camera video stream."""
|
2019-01-03 18:56:36 +00:00
|
|
|
filter_urllib3_logging()
|
|
|
|
|
2019-03-24 15:16:50 +00:00
|
|
|
serial_number = config_entry.data[CONF_MAC]
|
|
|
|
device = hass.data[AXIS_DOMAIN][serial_number]
|
|
|
|
|
|
|
|
config = {
|
|
|
|
CONF_NAME: config_entry.data[CONF_NAME],
|
|
|
|
CONF_USERNAME: config_entry.data[CONF_DEVICE][CONF_USERNAME],
|
|
|
|
CONF_PASSWORD: config_entry.data[CONF_DEVICE][CONF_PASSWORD],
|
|
|
|
CONF_MJPEG_URL: AXIS_VIDEO.format(
|
|
|
|
config_entry.data[CONF_DEVICE][CONF_HOST],
|
|
|
|
config_entry.data[CONF_DEVICE][CONF_PORT]),
|
|
|
|
CONF_STILL_IMAGE_URL: AXIS_IMAGE.format(
|
|
|
|
config_entry.data[CONF_DEVICE][CONF_HOST],
|
|
|
|
config_entry.data[CONF_DEVICE][CONF_PORT]),
|
2017-05-12 15:51:54 +00:00
|
|
|
CONF_AUTHENTICATION: HTTP_DIGEST_AUTHENTICATION,
|
|
|
|
}
|
2019-03-24 15:16:50 +00:00
|
|
|
async_add_entities([AxisCamera(config, device)])
|
2017-06-24 07:14:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AxisCamera(MjpegCamera):
|
2018-01-21 06:35:38 +00:00
|
|
|
"""Representation of a Axis camera."""
|
2017-06-24 07:14:57 +00:00
|
|
|
|
2019-03-24 15:16:50 +00:00
|
|
|
def __init__(self, config, device):
|
2017-06-24 07:14:57 +00:00
|
|
|
"""Initialize Axis Communications camera component."""
|
2018-09-15 09:26:29 +00:00
|
|
|
super().__init__(config)
|
2019-03-24 15:16:50 +00:00
|
|
|
self.device_config = config
|
|
|
|
self.device = device
|
|
|
|
self.port = device.config_entry.data[CONF_DEVICE][CONF_PORT]
|
2019-03-29 14:20:12 +00:00
|
|
|
self.unsub_dispatcher = []
|
2019-03-24 15:16:50 +00:00
|
|
|
|
|
|
|
async def async_added_to_hass(self):
|
|
|
|
"""Subscribe camera events."""
|
2019-03-29 14:20:12 +00:00
|
|
|
self.unsub_dispatcher.append(async_dispatcher_connect(
|
2019-04-02 18:13:11 +00:00
|
|
|
self.hass, self.device.event_new_address, self._new_address))
|
2019-03-29 14:20:12 +00:00
|
|
|
self.unsub_dispatcher.append(async_dispatcher_connect(
|
|
|
|
self.hass, self.device.event_reachable, self.update_callback))
|
|
|
|
|
2019-04-05 17:14:54 +00:00
|
|
|
@property
|
|
|
|
def supported_features(self):
|
|
|
|
"""Return supported features."""
|
|
|
|
return SUPPORT_STREAM
|
|
|
|
|
|
|
|
@property
|
|
|
|
def stream_source(self):
|
|
|
|
"""Return the stream source."""
|
|
|
|
return AXIS_STREAM.format(
|
|
|
|
self.device.config_entry.data[CONF_DEVICE][CONF_USERNAME],
|
|
|
|
self.device.config_entry.data[CONF_DEVICE][CONF_PASSWORD],
|
|
|
|
self.device.host)
|
|
|
|
|
2019-03-29 14:20:12 +00:00
|
|
|
@callback
|
|
|
|
def update_callback(self, no_delay=None):
|
|
|
|
"""Update the cameras state."""
|
|
|
|
self.async_schedule_update_ha_state()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def available(self):
|
|
|
|
"""Return True if device is available."""
|
|
|
|
return self.device.available
|
2017-06-24 07:14:57 +00:00
|
|
|
|
2019-04-02 18:13:11 +00:00
|
|
|
def _new_address(self):
|
|
|
|
"""Set new device address for video stream."""
|
|
|
|
self._mjpeg_url = AXIS_VIDEO.format(self.device.host, self.port)
|
|
|
|
self._still_image_url = AXIS_IMAGE.format(self.device.host, self.port)
|
2019-03-27 17:25:01 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return a unique identifier for this device."""
|
|
|
|
return '{}-camera'.format(self.device.serial)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def device_info(self):
|
|
|
|
"""Return a device description for device registry."""
|
|
|
|
return {
|
|
|
|
'identifiers': {(AXIS_DOMAIN, self.device.serial)}
|
|
|
|
}
|