diff --git a/.coveragerc b/.coveragerc index 712c5292e57..eaeee0f992d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -647,8 +647,6 @@ omit = homeassistant/components/nederlandse_spoorwegen/sensor.py homeassistant/components/nello/lock.py homeassistant/components/nest/legacy/* - homeassistant/components/netatmo/data_handler.py - homeassistant/components/netatmo/helper.py homeassistant/components/netdata/sensor.py homeassistant/components/netgear/device_tracker.py homeassistant/components/netgear_lte/* diff --git a/homeassistant/components/netatmo/data_handler.py b/homeassistant/components/netatmo/data_handler.py index 358ae79edd2..6982a651a45 100644 --- a/homeassistant/components/netatmo/data_handler.py +++ b/homeassistant/components/netatmo/data_handler.py @@ -12,7 +12,7 @@ from typing import Deque import pyatmo from homeassistant.config_entries import ConfigEntry -from homeassistant.core import CALLBACK_TYPE, HomeAssistant +from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.event import async_track_time_interval @@ -98,6 +98,12 @@ class NetatmoDataHandler: self._queue.rotate(BATCH_SIZE) + @callback + def async_force_update(self, data_class_entry): + """Prioritize data retrieval for given data class entry.""" + self._data_classes[data_class_entry][NEXT_SCAN] = time() + self._queue.rotate(-(self._queue.index(self._data_classes[data_class_entry]))) + async def async_cleanup(self): """Clean up the Netatmo data handler.""" for listener in self.listeners: @@ -115,7 +121,7 @@ class NetatmoDataHandler: elif event["data"]["push_type"] == "NACamera-connection": _LOGGER.debug("%s camera reconnected", MANUFACTURER) - self._data_classes[CAMERA_DATA_CLASS_NAME][NEXT_SCAN] = time() + self.async_force_update(CAMERA_DATA_CLASS_NAME) async def async_fetch_data(self, data_class, data_class_entry, **kwargs): """Fetch data and notify.""" diff --git a/tests/components/netatmo/test_camera.py b/tests/components/netatmo/test_camera.py index a58f2f3e1aa..10e3ca46b2a 100644 --- a/tests/components/netatmo/test_camera.py +++ b/tests/components/netatmo/test_camera.py @@ -1,4 +1,5 @@ """The tests for Netatmo camera.""" +from datetime import timedelta from unittest.mock import patch from homeassistant.components import camera @@ -9,8 +10,11 @@ from homeassistant.components.netatmo.const import ( SERVICE_SET_PERSONS_HOME, ) from homeassistant.const import CONF_WEBHOOK_ID +from homeassistant.util import dt -from .common import simulate_webhook +from .common import fake_post_request, simulate_webhook + +from tests.common import async_fire_time_changed async def test_setup_component_with_webhook(hass, camera_entry): @@ -205,3 +209,47 @@ async def test_service_set_camera_light(hass, camera_entry): camera_id="12:34:56:00:a5:a4", floodlight="on", ) + + +async def test_camera_reconnect_webhook(hass, config_entry): + """Test webhook event on camera reconnect.""" + with patch( + "homeassistant.components.netatmo.api.ConfigEntryNetatmoAuth.post_request" + ) as mock_post, patch( + "homeassistant.components.netatmo.PLATFORMS", ["camera"] + ), patch( + "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", + ), patch( + "homeassistant.components.webhook.async_generate_url" + ) as mock_webhook: + mock_post.side_effect = fake_post_request + mock_webhook.return_value = "https://example.com" + await hass.config_entries.async_setup(config_entry.entry_id) + + await hass.async_block_till_done() + + webhook_id = config_entry.data[CONF_WEBHOOK_ID] + + # Fake webhook activation + response = { + "push_type": "webhook_activation", + } + await simulate_webhook(hass, webhook_id, response) + await hass.async_block_till_done() + + mock_post.assert_called() + mock_post.reset_mock() + + # Fake camera reconnect + response = { + "push_type": "NACamera-connection", + } + await simulate_webhook(hass, webhook_id, response) + await hass.async_block_till_done() + + async_fire_time_changed( + hass, + dt.utcnow() + timedelta(seconds=60), + ) + await hass.async_block_till_done() + mock_post.assert_called() diff --git a/tests/components/netatmo/test_init.py b/tests/components/netatmo/test_init.py index 49e3ab14684..1ad07fe55d3 100644 --- a/tests/components/netatmo/test_init.py +++ b/tests/components/netatmo/test_init.py @@ -152,7 +152,7 @@ async def test_setup_without_https(hass, config_entry): "homeassistant.components.webhook.async_generate_url" ) as mock_webhook: mock_auth.return_value.post_request.side_effect = fake_post_request - mock_webhook.return_value = "http://example.com" + mock_webhook.return_value = "https://example.com" assert await async_setup_component( hass, "netatmo", {"netatmo": {"client_id": "123", "client_secret": "abc"}} ) @@ -166,7 +166,8 @@ async def test_setup_without_https(hass, config_entry): climate_entity_livingroom = "climate.netatmo_livingroom" assert hass.states.get(climate_entity_livingroom).state == "auto" await simulate_webhook(hass, webhook_id, FAKE_WEBHOOK) - assert hass.states.get(climate_entity_livingroom).state == "auto" + await hass.async_block_till_done() + assert hass.states.get(climate_entity_livingroom).state == "heat" async def test_setup_with_cloud(hass, config_entry):