예제 #1
0
    def __init__(self, hass, config: dict, options: dict):  # pylint: disable=too-many-arguments
        """Initialize a Reolink camera."""
        _LOGGER.debug(config)
        _LOGGER.debug(options)
        self._username = config[CONF_USERNAME]
        self._password = config[CONF_PASSWORD]

        if CONF_CHANNEL not in config:
            self.channel = DEFAULT_CHANNEL
        else:
            self.channel = config[CONF_CHANNEL]

        if CONF_TIMEOUT not in config:
            self._timeout = DEFAULT_TIMEOUT
        else:
            self._timeout = config[CONF_TIMEOUT]

        self._api = Api(
            config[CONF_HOST],
            config[CONF_PORT],
            self._username,
            self._password,
            channel=self.channel - 1,
            timeout=self._timeout,
        )
        self._sman = None
        self._webhook_url = None
        self._hass = hass
        self.sync_functions = list()
        self.motion_detection_state = True

        if CONF_MOTION_OFF_DELAY not in options:
            self.motion_off_delay = DEFAULT_MOTION_OFF_DELAY
        else:
            self.motion_off_delay = options[CONF_MOTION_OFF_DELAY]
예제 #2
0
    def __init__(self, hass: HomeAssistant, config: dict, options: dict):  # pylint: disable=too-many-arguments
        """Initialize a Reolink camera."""

        self._username = config[CONF_USERNAME]
        self._password = config[CONF_PASSWORD]

        if CONF_CHANNEL not in config:
            self._channel = DEFAULT_CHANNEL
        else:
            self._channel = config[CONF_CHANNEL]

        if CONF_TIMEOUT not in options:
            self._timeout = DEFAULT_TIMEOUT
        else:
            self._timeout = options[CONF_TIMEOUT]

        if CONF_STREAM not in options:
            self._stream = DEFAULT_STREAM
        else:
            self._stream = options[CONF_STREAM]

        if CONF_PROTOCOL not in options:
            self._protocol = DEFAULT_PROTOCOL
        else:
            self._protocol = options[CONF_PROTOCOL]

        self._api = Api(
            config[CONF_HOST],
            config[CONF_PORT],
            self._username,
            self._password,
            channel=self._channel - 1,
            stream=self._stream,
            protocol=self._protocol,
            timeout=self._timeout,
        )

        self._hass = hass
        self.async_functions = list()
        self.sync_functions = list()
        self.motion_detection_state = True

        if CONF_MOTION_OFF_DELAY not in options:
            self.motion_off_delay = DEFAULT_MOTION_OFF_DELAY
        else:
            self.motion_off_delay: int = options[CONF_MOTION_OFF_DELAY]

        if CONF_PLAYBACK_MONTHS not in options:
            self.playback_months = DEFAULT_PLAYBACK_MONTHS
        else:
            self.playback_months: int = options[CONF_PLAYBACK_MONTHS]

        if CONF_THUMBNAIL_PATH not in options:
            self._thumbnail_path = None
        else:
            self._thumbnail_path: str = options[CONF_THUMBNAIL_PATH]
예제 #3
0
    def __init__(self, hass, host, port, username, password):  # pylint: disable=too-many-arguments
        """Initialize a Reolink camera."""
        self._username = username
        self._password = password

        self._api = Api(host, port, username, password)
        self._sman = None
        self._webhook_url = None
        self._hass = hass
        self.sync_functions = list()
        self.motion_detection_state = True
        self.motion_off_delay = 60
예제 #4
0
    def __init__(self, hass: HomeAssistant, config: dict, options: dict):  # pylint: disable=too-many-arguments
        """Initialize a Reolink camera."""

        self._username = config[CONF_USERNAME]
        self._password = config[CONF_PASSWORD]

        if CONF_CHANNEL not in config:
            self._channel = DEFAULT_CHANNEL
        else:
            self._channel = config[CONF_CHANNEL]

        if CONF_USE_HTTPS not in config:
            self._use_https = DEFAULT_USE_HTTPS
        else:
            self._use_https = config[CONF_USE_HTTPS]

        if config[CONF_PORT] == 80 and self._use_https:
            _LOGGER.warning("Port 80 is used, USE_HTTPS set back to False")
            self._use_https = False

        if CONF_TIMEOUT not in options:
            self._timeout = DEFAULT_TIMEOUT
        else:
            self._timeout = options[CONF_TIMEOUT]

        if CONF_STREAM not in options:
            self._stream = DEFAULT_STREAM
        else:
            self._stream = options[CONF_STREAM]

        if CONF_STREAM_FORMAT not in options:
            self._stream_format = DEFAULT_STREAM_FORMAT
        else:
            self._stream_format = options[CONF_STREAM_FORMAT]

        if CONF_PROTOCOL not in options:
            self._protocol = DEFAULT_PROTOCOL
        else:
            self._protocol = options[CONF_PROTOCOL]

        global last_known_hass
        last_known_hass = hass

        self._api = Api(
            config[CONF_HOST],
            config[CONF_PORT],
            self._username,
            self._password,
            use_https=self._use_https,
            channel=self._channel - 1,
            stream=self._stream,
            stream_format=self._stream_format,
            protocol=self._protocol,
            timeout=self._timeout,
            aiohttp_get_session_callback=callback_get_iohttp_session)

        self._hass = hass
        self.async_functions = list()
        self.sync_functions = list()

        self.motion_detection_state = True
        self.object_person_detection_state = True
        self.object_vehicle_detection_state = True

        if CONF_MOTION_OFF_DELAY not in options:
            self.motion_off_delay = DEFAULT_MOTION_OFF_DELAY
        else:
            self.motion_off_delay: int = options[CONF_MOTION_OFF_DELAY]

        if CONF_PLAYBACK_MONTHS not in options:
            self.playback_months = DEFAULT_PLAYBACK_MONTHS
        else:
            self.playback_months: int = options[CONF_PLAYBACK_MONTHS]

        if CONF_THUMBNAIL_PATH not in options:
            self._thumbnail_path = None
        else:
            self._thumbnail_path: str = options[CONF_THUMBNAIL_PATH]

        if CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY not in options:
            self.motion_states_update_fallback_delay = DEFAULT_MOTION_STATES_UPDATE_FALLBACK_DELAY
        else:
            self.motion_states_update_fallback_delay = options[
                CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY]

        from .binary_sensor import MotionSensor, ObjectDetectedSensor

        self.sensor_motion_detection: Optional[MotionSensor] = None
        self.sensor_person_detection: Optional[ObjectDetectedSensor] = None
        self.sensor_vehicle_detection: Optional[ObjectDetectedSensor] = None
        self.sensor_pet_detection: Optional[ObjectDetectedSensor] = None
예제 #5
0
class ReolinkBase:
    """The implementation of the Reolink IP base class."""
    def __init__(self, hass: HomeAssistant, config: dict, options: dict):  # pylint: disable=too-many-arguments
        """Initialize a Reolink camera."""

        self._username = config[CONF_USERNAME]
        self._password = config[CONF_PASSWORD]

        if CONF_CHANNEL not in config:
            self._channel = DEFAULT_CHANNEL
        else:
            self._channel = config[CONF_CHANNEL]

        if CONF_USE_HTTPS not in config:
            self._use_https = DEFAULT_USE_HTTPS
        else:
            self._use_https = config[CONF_USE_HTTPS]

        if config[CONF_PORT] == 80 and self._use_https:
            _LOGGER.warning("Port 80 is used, USE_HTTPS set back to False")
            self._use_https = False

        if CONF_TIMEOUT not in options:
            self._timeout = DEFAULT_TIMEOUT
        else:
            self._timeout = options[CONF_TIMEOUT]

        if CONF_STREAM not in options:
            self._stream = DEFAULT_STREAM
        else:
            self._stream = options[CONF_STREAM]

        if CONF_STREAM_FORMAT not in options:
            self._stream_format = DEFAULT_STREAM_FORMAT
        else:
            self._stream_format = options[CONF_STREAM_FORMAT]

        if CONF_PROTOCOL not in options:
            self._protocol = DEFAULT_PROTOCOL
        else:
            self._protocol = options[CONF_PROTOCOL]

        global last_known_hass
        last_known_hass = hass

        self._api = Api(
            config[CONF_HOST],
            config[CONF_PORT],
            self._username,
            self._password,
            use_https=self._use_https,
            channel=self._channel - 1,
            stream=self._stream,
            stream_format=self._stream_format,
            protocol=self._protocol,
            timeout=self._timeout,
            aiohttp_get_session_callback=callback_get_iohttp_session)

        self._hass = hass
        self.async_functions = list()
        self.sync_functions = list()

        self.motion_detection_state = True
        self.object_person_detection_state = True
        self.object_vehicle_detection_state = True

        if CONF_MOTION_OFF_DELAY not in options:
            self.motion_off_delay = DEFAULT_MOTION_OFF_DELAY
        else:
            self.motion_off_delay: int = options[CONF_MOTION_OFF_DELAY]

        if CONF_PLAYBACK_MONTHS not in options:
            self.playback_months = DEFAULT_PLAYBACK_MONTHS
        else:
            self.playback_months: int = options[CONF_PLAYBACK_MONTHS]

        if CONF_THUMBNAIL_PATH not in options:
            self._thumbnail_path = None
        else:
            self._thumbnail_path: str = options[CONF_THUMBNAIL_PATH]

        if CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY not in options:
            self.motion_states_update_fallback_delay = DEFAULT_MOTION_STATES_UPDATE_FALLBACK_DELAY
        else:
            self.motion_states_update_fallback_delay = options[
                CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY]

        from .binary_sensor import MotionSensor, ObjectDetectedSensor

        self.sensor_motion_detection: Optional[MotionSensor] = None
        self.sensor_person_detection: Optional[ObjectDetectedSensor] = None
        self.sensor_vehicle_detection: Optional[ObjectDetectedSensor] = None
        self.sensor_pet_detection: Optional[ObjectDetectedSensor] = None

    @property
    def name(self):
        """Create the device name."""
        return self._api.name

    @property
    def unique_id(self):
        """Create the unique ID, base for all entities."""
        uid = self._api.mac_address.replace(":", "")
        return f"{uid}-{self.channel}"

    @property
    def event_id(self):
        """Create the event ID string."""
        event_id = self._api.mac_address.replace(":", "")
        return f"{EVENT_DATA_RECEIVED}-{event_id}"

    @property
    def push_manager(self):
        """Create the event ID string."""
        push_id = self._api.mac_address.replace(":", "")
        return f"{PUSH_MANAGER}-{push_id}"

    @property
    def timeout(self):
        """Return the timeout setting."""
        return self._timeout

    @property
    def channel(self):
        """Return the channel setting."""
        return self._channel

    @property
    def api(self):
        """Return the API object."""
        return self._api

    @property
    def thumbnail_path(self):
        """ Thumbnail storage location """
        if not self._thumbnail_path:
            self._thumbnail_path = self._hass.config.path(
                f"{STORAGE_DIR}/{DOMAIN}/{self.unique_id}")
        return self._thumbnail_path

    def enable_https(self, enable: bool):
        self._use_https = enable
        self._api.enable_https(enable)

    def set_thumbnail_path(self, value):
        """ Set custom thumbnail path"""
        self._thumbnail_path = value

    async def connect_api(self):
        """Connect to the Reolink API and fetch initial dataset."""
        if not await self._api.get_settings():
            return False
        if not await self._api.get_states():
            return False

        await self._api.get_ai_state()
        await self._api.is_admin()
        return True

    async def set_channel(self, channel):
        """Set the API channel."""
        self._channel = channel
        await self._api.set_channel(channel - 1)

    async def set_protocol(self, protocol):
        """Set the protocol."""
        self._protocol = protocol
        await self._api.set_protocol(protocol)

    async def set_stream(self, stream):
        """Set the stream."""
        self._stream = stream
        await self._api.set_stream(stream)

    async def set_stream_format(self, stream_format):
        """Set the stream format."""
        self._stream_format = stream_format
        await self._api.set_stream_format(stream_format)

    async def set_timeout(self, timeout):
        """Set the API timeout."""
        self._timeout = timeout
        await self._api.set_timeout(timeout)

    async def update_states(self):
        """Call the API of the camera device to update the states."""
        await self._api.get_states()

    async def update_settings(self):
        """Call the API of the camera device to update the settings."""
        await self._api.get_settings()

    async def disconnect_api(self):
        """Disconnect from the API, so the connection will be released."""
        await self._api.logout()

    async def stop(self):
        """Disconnect the API and deregister the event listener."""
        await self.disconnect_api()
        for func in self.async_functions:
            await func()
        for func in self.sync_functions:
            await self._hass.async_add_executor_job(func)

    async def send_search(self,
                          start: dt.datetime,
                          end: dt.datetime,
                          only_status: bool = False):
        """ Call the API of the camera device to search for VoDs """
        return await self._api.send_search(start, end, only_status)

    async def emit_search_results(
        self,
        bus_event_id: str,
        camera_id: str,
        start: Optional[dt.datetime] = None,
        end: Optional[dt.datetime] = None,
        context: Optional[Context] = None,
    ):
        """ Run search and emit VoD results to event """

        if end is None:
            end = dt_util.now()
        if start is None:
            start = dt.datetime.combine(end.date().replace(day=1), dt.time.min)
            if self.playback_months > 1:
                start -= relativedelta(months=int(self.playback_months))

        _, files = await self._api.send_search(start, end)

        for file in files:
            end = searchtime_to_datetime(file["EndTime"], end.tzinfo)
            start = searchtime_to_datetime(file["StartTime"], end.tzinfo)
            event_id = str(start.timestamp())
            url = VOD_URL.format(camera_id=camera_id,
                                 event_id=quote_plus(file["name"]))

            thumbnail = os.path.join(self.thumbnail_path,
                                     f"{event_id}.{THUMBNAIL_EXTENSION}")

            self._hass.bus.fire(
                bus_event_id,
                VoDEvent(
                    event_id,
                    start,
                    end - start,
                    file["name"],
                    url,
                    VoDEventThumbnail(
                        THUMBNAIL_URL.format(camera_id=camera_id,
                                             event_id=event_id),
                        os.path.isfile(thumbnail),
                        thumbnail,
                    ),
                ),
                context=context,
            )