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]
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]
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
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
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, )