mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Add use_wallclock_as_timestamps option to generic (#71245)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
a746d7c1d7
commit
7e49ae6410
@ -37,6 +37,7 @@ from .const import (
|
||||
CONF_RTSP_TRANSPORT,
|
||||
CONF_STILL_IMAGE_URL,
|
||||
CONF_STREAM_SOURCE,
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS,
|
||||
DEFAULT_NAME,
|
||||
FFMPEG_OPTION_MAP,
|
||||
GET_IMAGE_TIMEOUT,
|
||||
@ -160,6 +161,10 @@ class GenericCamera(Camera):
|
||||
CONF_RTSP_TRANSPORT
|
||||
]
|
||||
self._auth = generate_auth(device_info)
|
||||
if device_info.get(CONF_USE_WALLCLOCK_AS_TIMESTAMPS):
|
||||
self.stream_options[
|
||||
FFMPEG_OPTION_MAP[CONF_USE_WALLCLOCK_AS_TIMESTAMPS]
|
||||
] = "1"
|
||||
|
||||
self._last_url = None
|
||||
self._last_image = None
|
||||
|
@ -41,6 +41,7 @@ from .const import (
|
||||
CONF_RTSP_TRANSPORT,
|
||||
CONF_STILL_IMAGE_URL,
|
||||
CONF_STREAM_SOURCE,
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS,
|
||||
DEFAULT_NAME,
|
||||
DOMAIN,
|
||||
FFMPEG_OPTION_MAP,
|
||||
@ -64,6 +65,7 @@ SUPPORTED_IMAGE_TYPES = {"png", "jpeg", "gif", "svg+xml", "webp"}
|
||||
def build_schema(
|
||||
user_input: dict[str, Any] | MappingProxyType[str, Any],
|
||||
is_options_flow: bool = False,
|
||||
show_advanced_options=False,
|
||||
):
|
||||
"""Create schema for camera config setup."""
|
||||
spec = {
|
||||
@ -106,6 +108,13 @@ def build_schema(
|
||||
default=user_input.get(CONF_LIMIT_REFETCH_TO_URL_CHANGE, False),
|
||||
)
|
||||
] = bool
|
||||
if show_advanced_options:
|
||||
spec[
|
||||
vol.Required(
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS,
|
||||
default=user_input.get(CONF_USE_WALLCLOCK_AS_TIMESTAMPS, False),
|
||||
)
|
||||
] = bool
|
||||
return vol.Schema(spec)
|
||||
|
||||
|
||||
@ -199,6 +208,8 @@ async def async_test_stream(hass, info) -> dict[str, str]:
|
||||
}
|
||||
if rtsp_transport := info.get(CONF_RTSP_TRANSPORT):
|
||||
stream_options[FFMPEG_OPTION_MAP[CONF_RTSP_TRANSPORT]] = rtsp_transport
|
||||
if info.get(CONF_USE_WALLCLOCK_AS_TIMESTAMPS):
|
||||
stream_options[FFMPEG_OPTION_MAP[CONF_USE_WALLCLOCK_AS_TIMESTAMPS]] = "1"
|
||||
_LOGGER.debug("Attempting to open stream %s", stream_source)
|
||||
container = await hass.async_add_executor_job(
|
||||
partial(
|
||||
@ -356,6 +367,9 @@ class GenericOptionsFlowHandler(OptionsFlow):
|
||||
],
|
||||
CONF_FRAMERATE: user_input[CONF_FRAMERATE],
|
||||
CONF_VERIFY_SSL: user_input[CONF_VERIFY_SSL],
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS: user_input.get(
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS
|
||||
),
|
||||
}
|
||||
return self.async_create_entry(
|
||||
title=title,
|
||||
@ -363,6 +377,10 @@ class GenericOptionsFlowHandler(OptionsFlow):
|
||||
)
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
data_schema=build_schema(user_input or self.config_entry.options, True),
|
||||
data_schema=build_schema(
|
||||
user_input or self.config_entry.options,
|
||||
True,
|
||||
self.show_advanced_options,
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
@ -8,7 +8,11 @@ CONF_STILL_IMAGE_URL = "still_image_url"
|
||||
CONF_STREAM_SOURCE = "stream_source"
|
||||
CONF_FRAMERATE = "framerate"
|
||||
CONF_RTSP_TRANSPORT = "rtsp_transport"
|
||||
FFMPEG_OPTION_MAP = {CONF_RTSP_TRANSPORT: "rtsp_transport"}
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS = "use_wallclock_as_timestamps"
|
||||
FFMPEG_OPTION_MAP = {
|
||||
CONF_RTSP_TRANSPORT: "rtsp_transport",
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS: "use_wallclock_as_timestamps",
|
||||
}
|
||||
RTSP_TRANSPORTS = {
|
||||
"tcp": "TCP",
|
||||
"udp": "UDP",
|
||||
|
@ -55,9 +55,13 @@
|
||||
"authentication": "[%key:component::generic::config::step::user::data::authentication%]",
|
||||
"limit_refetch_to_url_change": "[%key:component::generic::config::step::user::data::limit_refetch_to_url_change%]",
|
||||
"password": "[%key:common::config_flow::data::password%]",
|
||||
"use_wallclock_as_timestamps": "Use wallclock as timestamps",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"framerate": "[%key:component::generic::config::step::user::data::framerate%]",
|
||||
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
|
||||
},
|
||||
"data_description": {
|
||||
"use_wallclock_as_timestamps": "This option may correct segmenting or crashing issues arising from buggy timestamp implementations on some cameras"
|
||||
}
|
||||
},
|
||||
"content_type": {
|
||||
|
@ -32,7 +32,6 @@
|
||||
"user": {
|
||||
"data": {
|
||||
"authentication": "Authentication",
|
||||
"content_type": "Content Type",
|
||||
"framerate": "Frame Rate (Hz)",
|
||||
"limit_refetch_to_url_change": "Limit refetch to url change",
|
||||
"password": "Password",
|
||||
@ -72,15 +71,18 @@
|
||||
"init": {
|
||||
"data": {
|
||||
"authentication": "Authentication",
|
||||
"content_type": "Content Type",
|
||||
"framerate": "Frame Rate (Hz)",
|
||||
"limit_refetch_to_url_change": "Limit refetch to url change",
|
||||
"password": "Password",
|
||||
"rtsp_transport": "RTSP transport protocol",
|
||||
"still_image_url": "Still Image URL (e.g. http://...)",
|
||||
"stream_source": "Stream Source URL (e.g. rtsp://...)",
|
||||
"use_wallclock_as_timestamps": "Use wallclock as timestamps",
|
||||
"username": "Username",
|
||||
"verify_ssl": "Verify SSL certificate"
|
||||
},
|
||||
"data_description": {
|
||||
"use_wallclock_as_timestamps": "This option may correct segmenting or crashing issues arising from buggy timestamp implementations on some cameras"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ from homeassistant.components.generic.const import (
|
||||
CONF_RTSP_TRANSPORT,
|
||||
CONF_STILL_IMAGE_URL,
|
||||
CONF_STREAM_SOURCE,
|
||||
CONF_USE_WALLCLOCK_AS_TIMESTAMPS,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
@ -653,3 +654,32 @@ async def test_migrate_existing_ids(hass) -> None:
|
||||
|
||||
entity_entry = registry.async_get(entity_id)
|
||||
assert entity_entry.unique_id == new_unique_id
|
||||
|
||||
|
||||
@respx.mock
|
||||
async def test_use_wallclock_as_timestamps_option(hass, fakeimg_png, mock_av_open):
|
||||
"""Test the use_wallclock_as_timestamps option flow."""
|
||||
|
||||
mock_entry = MockConfigEntry(
|
||||
title="Test Camera",
|
||||
domain=DOMAIN,
|
||||
data={},
|
||||
options=TESTDATA,
|
||||
)
|
||||
|
||||
with mock_av_open:
|
||||
mock_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
result = await hass.config_entries.options.async_init(
|
||||
mock_entry.entry_id, context={"show_advanced_options": True}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result2 = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_USE_WALLCLOCK_AS_TIMESTAMPS: True, **TESTDATA},
|
||||
)
|
||||
assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
Loading…
x
Reference in New Issue
Block a user