1 """Support for Xiaomi Cameras (HiSilicon Hi3518e V200)."""
3 from __future__
import annotations
7 from aioftp
import Client, StatusCodeError
8 from haffmpeg.camera
import CameraMjpeg
9 import voluptuous
as vol
13 PLATFORM_SCHEMA
as CAMERA_PLATFORM_SCHEMA,
32 _LOGGER = logging.getLogger(__name__)
34 DEFAULT_BRAND =
"YI Home Camera"
36 DEFAULT_PATH =
"/tmp/sd/record"
38 DEFAULT_USERNAME =
"root"
39 DEFAULT_ARGUMENTS =
"-pred 1"
41 CONF_FFMPEG_ARGUMENTS =
"ffmpeg_arguments"
43 PLATFORM_SCHEMA = CAMERA_PLATFORM_SCHEMA.extend(
45 vol.Required(CONF_NAME): cv.string,
46 vol.Required(CONF_HOST): cv.string,
47 vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
48 vol.Optional(CONF_PATH, default=DEFAULT_PATH): cv.string,
49 vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string,
50 vol.Required(CONF_PASSWORD): cv.string,
51 vol.Optional(CONF_FFMPEG_ARGUMENTS, default=DEFAULT_ARGUMENTS): cv.string,
59 async_add_entities: AddEntitiesCallback,
60 discovery_info: DiscoveryInfoType |
None =
None,
62 """Set up a Yi Camera."""
67 """Define an implementation of a Yi Camera."""
76 self.
_name_name = config[CONF_NAME]
78 self.
hosthost = config[CONF_HOST]
79 self.
portport = config[CONF_PORT]
80 self.
pathpath = config[CONF_PATH]
81 self.
useruser = config[CONF_USERNAME]
82 self.
passwdpasswd = config[CONF_PASSWORD]
91 """Determine whether the camera is on."""
96 """Return the name of this camera."""
97 return self.
_name_name
100 """Retrieve the latest video file from the customized Yi FTP server."""
103 await ftp.connect(self.
hosthost)
104 await ftp.login(self.
useruser, self.
passwdpasswd)
105 except (ConnectionRefusedError, StatusCodeError)
as err:
109 await ftp.change_directory(self.
pathpath)
111 for path, attrs
in await ftp.list():
112 if attrs[
"type"] ==
"dir" and "." not in str(path):
114 latest_dir = dirs[-1]
115 await ftp.change_directory(latest_dir)
118 for path, _
in await ftp.list():
121 _LOGGER.info(
'Video folder "%s" empty; delaying', latest_dir)
127 f
"ftp://{self.user}:{self.passwd}@{self.host}:"
128 f
"{self.port}{self.path}/{latest_dir}/{videos[-1]}"
130 except (ConnectionRefusedError, StatusCodeError)
as err:
131 _LOGGER.error(
"Error while fetching video: %s", err)
136 self, width: int |
None =
None, height: int |
None =
None
138 """Return a still image response from the camera."""
140 if url
and url != self.
_last_url_last_url:
141 self.
_last_image_last_image = await ffmpeg.async_get_image(
153 """Generate an HTTP MJPEG stream from the camera."""
157 stream = CameraMjpeg(self.
_manager_manager.binary)
161 stream_reader = await stream.get_reader()
166 self.
_manager_manager.ffmpeg_stream_content_type,
def _get_latest_video_url(self)
def __init__(self, hass, config)
bytes|None async_camera_image(self, int|None width=None, int|None height=None)
def handle_async_mjpeg_stream(self, request)
FFmpegManager get_ffmpeg_manager(HomeAssistant hass)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
web.StreamResponse async_aiohttp_proxy_stream(HomeAssistant hass, web.BaseRequest request, aiohttp.StreamReader stream, str|None content_type, int buffer_size=102400, int timeout=10)