diff --git a/homeassistant/components/amcrest/manifest.json b/homeassistant/components/amcrest/manifest.json index 0d6c1380c20..1431b10a638 100644 --- a/homeassistant/components/amcrest/manifest.json +++ b/homeassistant/components/amcrest/manifest.json @@ -2,7 +2,7 @@ "domain": "amcrest", "name": "Amcrest", "documentation": "https://www.home-assistant.io/integrations/amcrest", - "requirements": ["amcrest==1.9.3"], + "requirements": ["amcrest==1.9.4"], "dependencies": ["ffmpeg"], "codeowners": ["@flacjacket"], "iot_class": "local_polling" diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index 078bb4b4225..ae506989e00 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -155,7 +155,8 @@ class FritzBoxTools(update_coordinator.DataUpdateCoordinator): self.hass = hass self.host = host self.mesh_role = MeshRoles.NONE - self.device_is_router: bool = True + self.device_conn_type: str | None = None + self.device_is_router: bool = False self.password = password self.port = port self.username = username @@ -213,7 +214,15 @@ class FritzBoxTools(update_coordinator.DataUpdateCoordinator): self._current_firmware = info.get("NewSoftwareVersion") self._update_available, self._latest_firmware = self._update_device_info() - self.device_is_router = "WANIPConn1" in self.connection.services + if "Layer3Forwarding1" in self.connection.services: + if connection_type := self.connection.call_action( + "Layer3Forwarding1", "GetDefaultConnectionService" + ).get("NewDefaultConnectionService"): + # Return NewDefaultConnectionService sample: "1.WANPPPConnection.1" + self.device_conn_type = connection_type[2:][:-2] + self.device_is_router = self.connection.call_action( + self.device_conn_type, "GetInfo" + ).get("NewEnable") @callback async def _async_update_data(self) -> None: diff --git a/homeassistant/components/fritz/diagnostics.py b/homeassistant/components/fritz/diagnostics.py index f35eca6b914..fa4ff6a7db8 100644 --- a/homeassistant/components/fritz/diagnostics.py +++ b/homeassistant/components/fritz/diagnostics.py @@ -25,6 +25,7 @@ async def async_get_config_entry_diagnostics( "current_firmware": avm_wrapper.current_firmware, "latest_firmware": avm_wrapper.latest_firmware, "update_available": avm_wrapper.update_available, + "connection_type": avm_wrapper.device_conn_type, "is_router": avm_wrapper.device_is_router, "mesh_role": avm_wrapper.mesh_role, "last_update success": avm_wrapper.last_update_success, diff --git a/homeassistant/components/fritz/switch.py b/homeassistant/components/fritz/switch.py index fec760fbe7a..daddae5720c 100644 --- a/homeassistant/components/fritz/switch.py +++ b/homeassistant/components/fritz/switch.py @@ -81,16 +81,12 @@ def port_entities_list( _LOGGER.debug("Setting up %s switches", SWITCH_TYPE_PORTFORWARD) entities_list: list[FritzBoxPortSwitch] = [] - connection_type = avm_wrapper.get_default_connection() - if not connection_type: + if not avm_wrapper.device_conn_type: _LOGGER.debug("The FRITZ!Box has no %s options", SWITCH_TYPE_PORTFORWARD) return [] - # Return NewDefaultConnectionService sample: "1.WANPPPConnection.1" - con_type: str = connection_type["NewDefaultConnectionService"][2:][:-2] - # Query port forwardings and setup a switch for each forward for the current device - resp = avm_wrapper.get_num_port_mapping(con_type) + resp = avm_wrapper.get_num_port_mapping(avm_wrapper.device_conn_type) if not resp: _LOGGER.debug("The FRITZ!Box has no %s options", SWITCH_TYPE_DEFLECTION) return [] @@ -107,7 +103,7 @@ def port_entities_list( for i in range(port_forwards_count): - portmap = avm_wrapper.get_port_mapping(con_type, i) + portmap = avm_wrapper.get_port_mapping(avm_wrapper.device_conn_type, i) if not portmap: _LOGGER.debug("The FRITZ!Box has no %s options", SWITCH_TYPE_DEFLECTION) continue @@ -133,7 +129,7 @@ def port_entities_list( portmap, port_name, i, - con_type, + avm_wrapper.device_conn_type, ) ) diff --git a/homeassistant/components/generic/camera.py b/homeassistant/components/generic/camera.py index b6084d148a3..b4aaad38618 100644 --- a/homeassistant/components/generic/camera.py +++ b/homeassistant/components/generic/camera.py @@ -96,7 +96,7 @@ class GenericCamera(Camera): if self._stream_source is not None: self._stream_source.hass = hass self._limit_refetch = device_info[CONF_LIMIT_REFETCH_TO_URL_CHANGE] - self._attr_frames_interval = 1 / device_info[CONF_FRAMERATE] + self._attr_frame_interval = 1 / device_info[CONF_FRAMERATE] self._supported_features = SUPPORT_STREAM if self._stream_source else 0 self.content_type = device_info[CONF_CONTENT_TYPE] self.verify_ssl = device_info[CONF_VERIFY_SSL] diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index f4613018b20..5663f343296 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -577,6 +577,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: websocket_api.async_register_command(hass, websocket_subscribe) websocket_api.async_register_command(hass, websocket_remove_device) websocket_api.async_register_command(hass, websocket_mqtt_info) + debug_info.initialize(hass) if conf is None: # If we have a config entry, setup is done by that config entry. @@ -595,8 +596,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: ) ) - debug_info.initialize(hass) - return True diff --git a/homeassistant/components/simplisafe/manifest.json b/homeassistant/components/simplisafe/manifest.json index 62b5b9aa7b7..a5a4b5f4821 100644 --- a/homeassistant/components/simplisafe/manifest.json +++ b/homeassistant/components/simplisafe/manifest.json @@ -3,7 +3,7 @@ "name": "SimpliSafe", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/simplisafe", - "requirements": ["simplisafe-python==2022.02.0"], + "requirements": ["simplisafe-python==2022.02.1"], "codeowners": ["@bachya"], "iot_class": "cloud_polling", "dhcp": [ diff --git a/homeassistant/components/synology_dsm/common.py b/homeassistant/components/synology_dsm/common.py index 54a0735186f..e27c7475251 100644 --- a/homeassistant/components/synology_dsm/common.py +++ b/homeassistant/components/synology_dsm/common.py @@ -33,7 +33,7 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant, callback -from .const import CONF_DEVICE_TOKEN +from .const import CONF_DEVICE_TOKEN, DOMAIN, SYSTEM_LOADED LOGGER = logging.getLogger(__name__) @@ -218,6 +218,11 @@ class SynoApi: ) self.surveillance_station = self.dsm.surveillance_station + def _set_system_loaded(self, state: bool = False) -> None: + """Set system loaded flag.""" + dsm_device = self._hass.data[DOMAIN].get(self.information.serial) + dsm_device[SYSTEM_LOADED] = state + async def _syno_api_executer(self, api_call: Callable) -> None: """Synology api call wrapper.""" try: @@ -231,10 +236,12 @@ class SynoApi: async def async_reboot(self) -> None: """Reboot NAS.""" await self._syno_api_executer(self.system.reboot) + self._set_system_loaded() async def async_shutdown(self) -> None: """Shutdown NAS.""" await self._syno_api_executer(self.system.shutdown) + self._set_system_loaded() async def async_unload(self) -> None: """Stop interacting with the NAS and prepare for removal from hass.""" diff --git a/homeassistant/components/synology_dsm/service.py b/homeassistant/components/synology_dsm/service.py index f26a43b2ca0..a7a336e0c1b 100644 --- a/homeassistant/components/synology_dsm/service.py +++ b/homeassistant/components/synology_dsm/service.py @@ -15,7 +15,6 @@ from .const import ( SERVICE_SHUTDOWN, SERVICES, SYNO_API, - SYSTEM_LOADED, ) LOGGER = logging.getLogger(__name__) @@ -57,7 +56,6 @@ async def async_setup_services(hass: HomeAssistant) -> None: ) dsm_api: SynoApi = dsm_device[SYNO_API] try: - dsm_device[SYSTEM_LOADED] = False await getattr(dsm_api, f"async_{call.service}")() except SynologyDSMException as ex: LOGGER.error( diff --git a/homeassistant/const.py b/homeassistant/const.py index dd09308b3b5..75cd20528bb 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 2 -PATCH_VERSION: Final = "4" +PATCH_VERSION: Final = "5" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) diff --git a/requirements_all.txt b/requirements_all.txt index 94de7f855dd..a50bc68b199 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -308,7 +308,7 @@ amberelectric==1.0.3 ambiclimate==0.2.1 # homeassistant.components.amcrest -amcrest==1.9.3 +amcrest==1.9.4 # homeassistant.components.androidtv androidtv[async]==0.0.63 @@ -2190,7 +2190,7 @@ simplehound==0.3 simplepush==1.1.4 # homeassistant.components.simplisafe -simplisafe-python==2022.02.0 +simplisafe-python==2022.02.1 # homeassistant.components.sisyphus sisyphus-control==3.1.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c55531e1ba7..a5bd1a6443c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1337,7 +1337,7 @@ sharkiqpy==0.1.8 simplehound==0.3 # homeassistant.components.simplisafe -simplisafe-python==2022.02.0 +simplisafe-python==2022.02.1 # homeassistant.components.slack slackclient==2.5.0 diff --git a/setup.cfg b/setup.cfg index 6ade0983650..7d73060f322 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = homeassistant -version = 2022.2.4 +version = 2022.2.5 author = The Home Assistant Authors author_email = hello@home-assistant.io license = Apache-2.0 diff --git a/tests/components/generic/test_camera.py b/tests/components/generic/test_camera.py index 60e68a1e7b1..042cd2ee650 100644 --- a/tests/components/generic/test_camera.py +++ b/tests/components/generic/test_camera.py @@ -9,6 +9,7 @@ import pytest import respx from homeassistant import config as hass_config +from homeassistant.components.camera import async_get_mjpeg_stream from homeassistant.components.generic import DOMAIN from homeassistant.components.websocket_api.const import TYPE_RESULT from homeassistant.const import SERVICE_RELOAD @@ -515,3 +516,29 @@ async def test_no_still_image_url(hass, hass_client): mock_stream.async_get_image.assert_called_once() assert resp.status == HTTPStatus.OK assert await resp.read() == b"stream_keyframe_image" + + +async def test_frame_interval_property(hass): + """Test that the frame interval is calculated and returned correctly.""" + + await async_setup_component( + hass, + "camera", + { + "camera": { + "name": "config_test", + "platform": "generic", + "stream_source": "rtsp://example.com:554/rtsp/", + "framerate": 5, + }, + }, + ) + await hass.async_block_till_done() + + request = Mock() + with patch( + "homeassistant.components.camera.async_get_still_stream" + ) as mock_get_stream: + await async_get_mjpeg_stream(hass, request, "camera.config_test") + + assert mock_get_stream.call_args_list[0][0][3] == pytest.approx(0.2) diff --git a/tests/components/homewizard/test_sensor.py b/tests/components/homewizard/test_sensor.py index 6f5396f8702..c1a98c07108 100644 --- a/tests/components/homewizard/test_sensor.py +++ b/tests/components/homewizard/test_sensor.py @@ -663,10 +663,10 @@ async def test_sensors_unreachable(hass, mock_config_entry_data, mock_config_ent entry = mock_config_entry entry.data = mock_config_entry_data entry.add_to_hass(hass) - utcnow = dt_util.utcnow() await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() + utcnow = dt_util.utcnow() # Time after the integration is setup assert ( hass.states.get( @@ -717,7 +717,7 @@ async def test_api_disabled(hass, mock_config_entry_data, mock_config_entry): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - utcnow = dt_util.utcnow() + utcnow = dt_util.utcnow() # Time after the integration is setup assert ( hass.states.get(