diff --git a/CODEOWNERS b/CODEOWNERS index 3902f3f5d5f..29740431c37 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -336,7 +336,7 @@ homeassistant/components/pi_hole/* @fabaff @johnluetke @shenxn homeassistant/components/pilight/* @trekky12 homeassistant/components/plaato/* @JohNan homeassistant/components/plex/* @jjlawren -homeassistant/components/plugwise/* @CoMPaTech @bouwew +homeassistant/components/plugwise/* @CoMPaTech @bouwew @brefra homeassistant/components/plum_lightpad/* @ColinHarrington @prystupa homeassistant/components/point/* @fredrike homeassistant/components/poolsense/* @haemishkyd diff --git a/homeassistant/components/plugwise/__init__.py b/homeassistant/components/plugwise/__init__.py index ee6c44bc558..47a9a1e7d9c 100644 --- a/homeassistant/components/plugwise/__init__.py +++ b/homeassistant/components/plugwise/__init__.py @@ -1,16 +1,10 @@ """Plugwise platform for Home Assistant Core.""" -import asyncio - -import voluptuous as vol from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST from homeassistant.core import HomeAssistant -from .const import ALL_PLATFORMS, DOMAIN, UNDO_UPDATE_LISTENER -from .gateway import async_setup_entry_gw - -CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA) +from .gateway import async_setup_entry_gw, async_unload_entry_gw async def async_setup(hass: HomeAssistant, config: dict): @@ -27,19 +21,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): - """Unload a config entry.""" - unload_ok = all( - await asyncio.gather( - *[ - hass.config_entries.async_forward_entry_unload(entry, component) - for component in ALL_PLATFORMS - ] - ) - ) - - hass.data[DOMAIN][entry.entry_id][UNDO_UPDATE_LISTENER]() - - if unload_ok: - hass.data[DOMAIN].pop(entry.entry_id) - - return unload_ok + """Unload the Plugwise components.""" + if entry.data.get(CONF_HOST): + return await async_unload_entry_gw(hass, entry) + # PLACEHOLDER USB entry setup + return False diff --git a/homeassistant/components/plugwise/climate.py b/homeassistant/components/plugwise/climate.py index 7981283f27d..c8a2191963e 100644 --- a/homeassistant/components/plugwise/climate.py +++ b/homeassistant/components/plugwise/climate.py @@ -2,7 +2,7 @@ import logging -from Plugwise_Smile.Smile import Smile +from plugwise.exceptions import PlugwiseException from homeassistant.components.climate import ClimateEntity from homeassistant.components.climate.const import ( @@ -192,7 +192,7 @@ class PwThermostat(SmileGateway, ClimateEntity): await self._api.set_temperature(self._loc_id, temperature) self._setpoint = temperature self.async_write_ha_state() - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") else: _LOGGER.error("Invalid temperature requested") @@ -205,7 +205,7 @@ class PwThermostat(SmileGateway, ClimateEntity): try: await self._api.set_temperature(self._loc_id, self._schedule_temp) self._setpoint = self._schedule_temp - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") try: await self._api.set_schedule_state( @@ -213,7 +213,7 @@ class PwThermostat(SmileGateway, ClimateEntity): ) self._hvac_mode = hvac_mode self.async_write_ha_state() - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") async def async_set_preset_mode(self, preset_mode): @@ -223,7 +223,7 @@ class PwThermostat(SmileGateway, ClimateEntity): self._preset_mode = preset_mode self._setpoint = self._presets.get(self._preset_mode, "none")[0] self.async_write_ha_state() - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") @callback diff --git a/homeassistant/components/plugwise/config_flow.py b/homeassistant/components/plugwise/config_flow.py index 6fd7cde44bc..e0d22627737 100644 --- a/homeassistant/components/plugwise/config_flow.py +++ b/homeassistant/components/plugwise/config_flow.py @@ -1,7 +1,8 @@ """Config flow for Plugwise integration.""" import logging -from Plugwise_Smile.Smile import Smile +from plugwise.exceptions import InvalidAuthentication, PlugwiseException +from plugwise.smile import Smile import voluptuous as vol from homeassistant import config_entries, core, exceptions @@ -67,9 +68,9 @@ async def validate_gw_input(hass: core.HomeAssistant, data): try: await api.connect() - except Smile.InvalidAuthentication as err: + except InvalidAuthentication as err: raise InvalidAuth from err - except Smile.PlugwiseError as err: + except PlugwiseException as err: raise CannotConnect from err return api diff --git a/homeassistant/components/plugwise/const.py b/homeassistant/components/plugwise/const.py index f965676aef2..c6ef43af602 100644 --- a/homeassistant/components/plugwise/const.py +++ b/homeassistant/components/plugwise/const.py @@ -2,7 +2,9 @@ DOMAIN = "plugwise" SENSOR_PLATFORMS = ["sensor", "switch"] -ALL_PLATFORMS = ["binary_sensor", "climate", "sensor", "switch"] +PLATFORMS_GATEWAY = ["binary_sensor", "climate", "sensor", "switch"] +PW_TYPE = "plugwise_type" +GATEWAY = "gateway" # Sensor mapping SENSOR_MAP_DEVICE_CLASS = 2 diff --git a/homeassistant/components/plugwise/gateway.py b/homeassistant/components/plugwise/gateway.py index 5ba6eda2770..3b61bd3930d 100644 --- a/homeassistant/components/plugwise/gateway.py +++ b/homeassistant/components/plugwise/gateway.py @@ -5,8 +5,13 @@ from datetime import timedelta import logging from typing import Dict -from Plugwise_Smile.Smile import Smile import async_timeout +from plugwise.exceptions import ( + InvalidAuthentication, + PlugwiseException, + XMLDataMissingError, +) +from plugwise.smile import Smile import voluptuous as vol from homeassistant.config_entries import ConfigEntry @@ -28,13 +33,15 @@ from homeassistant.helpers.update_coordinator import ( ) from .const import ( - ALL_PLATFORMS, COORDINATOR, DEFAULT_PORT, DEFAULT_SCAN_INTERVAL, DEFAULT_TIMEOUT, DEFAULT_USERNAME, DOMAIN, + GATEWAY, + PLATFORMS_GATEWAY, + PW_TYPE, SENSOR_PLATFORMS, UNDO_UPDATE_LISTENER, ) @@ -64,11 +71,11 @@ async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: _LOGGER.error("Unable to connect to Smile") raise ConfigEntryNotReady - except Smile.InvalidAuthentication: + except InvalidAuthentication: _LOGGER.error("Invalid username or Smile ID") return False - except Smile.PlugwiseError as err: + except PlugwiseException as err: _LOGGER.error("Error while communicating to device %s", api.smile_name) raise ConfigEntryNotReady from err @@ -88,7 +95,7 @@ async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: async with async_timeout.timeout(DEFAULT_TIMEOUT): await api.full_update_device() return True - except Smile.XMLDataMissingError as err: + except XMLDataMissingError as err: raise UpdateFailed("Smile update failed") from err coordinator = DataUpdateCoordinator( @@ -115,6 +122,7 @@ async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { "api": api, COORDINATOR: coordinator, + PW_TYPE: GATEWAY, UNDO_UPDATE_LISTENER: undo_listener, } @@ -130,7 +138,7 @@ async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: single_master_thermostat = api.single_master_thermostat() - platforms = ALL_PLATFORMS + platforms = PLATFORMS_GATEWAY if single_master_thermostat is None: platforms = SENSOR_PLATFORMS @@ -150,13 +158,13 @@ async def _update_listener(hass: HomeAssistant, entry: ConfigEntry): ) -async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): +async def async_unload_entry_gw(hass: HomeAssistant, entry: ConfigEntry): """Unload a config entry.""" unload_ok = all( await asyncio.gather( *[ hass.config_entries.async_forward_entry_unload(entry, component) - for component in ALL_PLATFORMS + for component in PLATFORMS_GATEWAY ] ) ) diff --git a/homeassistant/components/plugwise/manifest.json b/homeassistant/components/plugwise/manifest.json index f431ce9ee97..5a32341139c 100644 --- a/homeassistant/components/plugwise/manifest.json +++ b/homeassistant/components/plugwise/manifest.json @@ -2,8 +2,8 @@ "domain": "plugwise", "name": "Plugwise", "documentation": "https://www.home-assistant.io/integrations/plugwise", - "requirements": ["Plugwise_Smile==1.6.0"], - "codeowners": ["@CoMPaTech", "@bouwew"], + "requirements": ["plugwise==0.8.3"], + "codeowners": ["@CoMPaTech", "@bouwew", "@brefra"], "zeroconf": ["_plugwise._tcp.local."], "config_flow": true } diff --git a/homeassistant/components/plugwise/switch.py b/homeassistant/components/plugwise/switch.py index 8221bc2cb57..ce3be04681a 100644 --- a/homeassistant/components/plugwise/switch.py +++ b/homeassistant/components/plugwise/switch.py @@ -2,7 +2,7 @@ import logging -from Plugwise_Smile.Smile import Smile +from plugwise.exceptions import PlugwiseException from homeassistant.components.switch import SwitchEntity from homeassistant.core import callback @@ -14,6 +14,12 @@ _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, config_entry, async_add_entities): + """Set up the Smile switches from a config entry.""" + # PLACEHOLDER USB entry setup + return await async_setup_entry_gateway(hass, config_entry, async_add_entities) + + +async def async_setup_entry_gateway(hass, config_entry, async_add_entities): """Set up the Smile switches from a config entry.""" api = hass.data[DOMAIN][config_entry.entry_id]["api"] coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR] @@ -37,7 +43,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): model = "Switch Group" entities.append( - PwSwitch( + GwSwitch( api, coordinator, device_properties["name"], dev_id, members, model ) ) @@ -45,7 +51,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): async_add_entities(entities, True) -class PwSwitch(SmileGateway, SwitchEntity): +class GwSwitch(SmileGateway, SwitchEntity): """Representation of a Plugwise plug.""" def __init__(self, api, coordinator, name, dev_id, members, model): @@ -79,7 +85,7 @@ class PwSwitch(SmileGateway, SwitchEntity): if state_on: self._is_on = True self.async_write_ha_state() - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") async def async_turn_off(self, **kwargs): @@ -91,7 +97,7 @@ class PwSwitch(SmileGateway, SwitchEntity): if state_off: self._is_on = False self.async_write_ha_state() - except Smile.PlugwiseError: + except PlugwiseException: _LOGGER.error("Error while communicating to device") @callback diff --git a/requirements_all.txt b/requirements_all.txt index e4672196675..f687f042b1f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -25,9 +25,6 @@ Mastodon.py==1.5.1 # homeassistant.components.orangepi_gpio OPi.GPIO==0.4.0 -# homeassistant.components.plugwise -Plugwise_Smile==1.6.0 - # homeassistant.components.essent PyEssent==0.14 @@ -1139,6 +1136,9 @@ plexauth==0.0.6 # homeassistant.components.plex plexwebsocket==0.0.12 +# homeassistant.components.plugwise +plugwise==0.8.3 + # homeassistant.components.plum_lightpad plumlightpad==0.0.11 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6c37691fd2a..3d1ad87e1de 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -6,9 +6,6 @@ # homeassistant.components.homekit HAP-python==3.0.0 -# homeassistant.components.plugwise -Plugwise_Smile==1.6.0 - # homeassistant.components.flick_electric PyFlick==0.0.2 @@ -562,6 +559,9 @@ plexauth==0.0.6 # homeassistant.components.plex plexwebsocket==0.0.12 +# homeassistant.components.plugwise +plugwise==0.8.3 + # homeassistant.components.plum_lightpad plumlightpad==0.0.11 diff --git a/tests/components/plugwise/common.py b/tests/components/plugwise/common.py index eb227322aa8..379929ce2f1 100644 --- a/tests/components/plugwise/common.py +++ b/tests/components/plugwise/common.py @@ -1,6 +1,6 @@ """Common initialisation for the Plugwise integration.""" -from homeassistant.components.plugwise import DOMAIN +from homeassistant.components.plugwise.const import DOMAIN from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry diff --git a/tests/components/plugwise/conftest.py b/tests/components/plugwise/conftest.py index 938e61146e5..ae934c565bc 100644 --- a/tests/components/plugwise/conftest.py +++ b/tests/components/plugwise/conftest.py @@ -3,8 +3,13 @@ from functools import partial import re -from Plugwise_Smile.Smile import Smile import jsonpickle +from plugwise.exceptions import ( + ConnectionFailedError, + InvalidAuthentication, + PlugwiseException, + XMLDataMissingError, +) import pytest from tests.async_mock import AsyncMock, Mock, patch @@ -24,8 +29,8 @@ def mock_smile(): with patch( "homeassistant.components.plugwise.config_flow.Smile", ) as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError smile_mock.return_value.connect.return_value = True yield smile_mock.return_value @@ -48,9 +53,9 @@ def mock_smile_error(aioclient_mock: AiohttpClientMocker) -> None: def mock_smile_notconnect(): """Mock the Plugwise Smile general connection failure for Home Assistant.""" with patch("homeassistant.components.plugwise.gateway.Smile") as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError - smile_mock.PlugwiseError = Smile.PlugwiseError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError + smile_mock.PlugwiseException = PlugwiseException smile_mock.return_value.connect.side_effect = AsyncMock(return_value=False) yield smile_mock.return_value @@ -65,9 +70,9 @@ def mock_smile_adam(): """Create a Mock Adam environment for testing exceptions.""" chosen_env = "adam_multiple_devices_per_zone" with patch("homeassistant.components.plugwise.gateway.Smile") as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError - smile_mock.XMLDataMissingError = Smile.XMLDataMissingError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError + smile_mock.XMLDataMissingError = XMLDataMissingError smile_mock.return_value.gateway_id = "fe799307f1624099878210aa0b9f1475" smile_mock.return_value.heater_id = "90986d591dcd426cae3ec3e8111ff730" @@ -110,9 +115,9 @@ def mock_smile_anna(): """Create a Mock Anna environment for testing exceptions.""" chosen_env = "anna_heatpump" with patch("homeassistant.components.plugwise.gateway.Smile") as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError - smile_mock.XMLDataMissingError = Smile.XMLDataMissingError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError + smile_mock.XMLDataMissingError = XMLDataMissingError smile_mock.return_value.gateway_id = "015ae9ea3f964e668e490fa39da3870b" smile_mock.return_value.heater_id = "1cbf783bb11e4a7c8a6843dee3a86927" @@ -155,9 +160,9 @@ def mock_smile_p1(): """Create a Mock P1 DSMR environment for testing exceptions.""" chosen_env = "p1v3_full_option" with patch("homeassistant.components.plugwise.gateway.Smile") as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError - smile_mock.XMLDataMissingError = Smile.XMLDataMissingError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError + smile_mock.XMLDataMissingError = XMLDataMissingError smile_mock.return_value.gateway_id = "e950c7d5e1ee407a858e2a8b5016c8b3" smile_mock.return_value.heater_id = None @@ -191,9 +196,9 @@ def mock_stretch(): """Create a Mock Stretch environment for testing exceptions.""" chosen_env = "stretch_v31" with patch("homeassistant.components.plugwise.gateway.Smile") as smile_mock: - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError - smile_mock.XMLDataMissingError = Smile.XMLDataMissingError + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError + smile_mock.XMLDataMissingError = XMLDataMissingError smile_mock.return_value.gateway_id = "259882df3c05415b99c2d962534ce820" smile_mock.return_value.heater_id = None diff --git a/tests/components/plugwise/test_climate.py b/tests/components/plugwise/test_climate.py index 7c74d970d7e..e85140660fd 100644 --- a/tests/components/plugwise/test_climate.py +++ b/tests/components/plugwise/test_climate.py @@ -1,5 +1,8 @@ """Tests for the Plugwise Climate integration.""" +from plugwise.exceptions import PlugwiseException + +from homeassistant.components.climate.const import HVAC_MODE_AUTO, HVAC_MODE_HEAT from homeassistant.config_entries import ENTRY_STATE_LOADED from tests.components.plugwise.common import async_init_integration @@ -13,7 +16,7 @@ async def test_adam_climate_entity_attributes(hass, mock_smile_adam): state = hass.states.get("climate.zone_lisa_wk") attrs = state.attributes - assert attrs["hvac_modes"] == ["heat", "auto"] + assert attrs["hvac_modes"] == [HVAC_MODE_HEAT, HVAC_MODE_AUTO] assert "preset_modes" in attrs assert "no_frost" in attrs["preset_modes"] @@ -29,7 +32,7 @@ async def test_adam_climate_entity_attributes(hass, mock_smile_adam): state = hass.states.get("climate.zone_thermostat_jessie") attrs = state.attributes - assert attrs["hvac_modes"] == ["heat", "auto"] + assert attrs["hvac_modes"] == [HVAC_MODE_HEAT, HVAC_MODE_AUTO] assert "preset_modes" in attrs assert "no_frost" in attrs["preset_modes"] @@ -41,6 +44,44 @@ async def test_adam_climate_entity_attributes(hass, mock_smile_adam): assert attrs["preset_mode"] == "asleep" +async def test_adam_climate_adjust_negative_testing(hass, mock_smile_adam): + """Test exceptions of climate entities.""" + mock_smile_adam.set_preset.side_effect = PlugwiseException + mock_smile_adam.set_schedule_state.side_effect = PlugwiseException + mock_smile_adam.set_temperature.side_effect = PlugwiseException + entry = await async_init_integration(hass, mock_smile_adam) + assert entry.state == ENTRY_STATE_LOADED + + await hass.services.async_call( + "climate", + "set_temperature", + {"entity_id": "climate.zone_lisa_wk", "temperature": 25}, + blocking=True, + ) + state = hass.states.get("climate.zone_lisa_wk") + attrs = state.attributes + assert attrs["temperature"] == 21.5 + + await hass.services.async_call( + "climate", + "set_preset_mode", + {"entity_id": "climate.zone_thermostat_jessie", "preset_mode": "home"}, + blocking=True, + ) + state = hass.states.get("climate.zone_thermostat_jessie") + attrs = state.attributes + assert attrs["preset_mode"] == "asleep" + + await hass.services.async_call( + "climate", + "set_hvac_mode", + {"entity_id": "climate.zone_thermostat_jessie", "hvac_mode": HVAC_MODE_AUTO}, + blocking=True, + ) + state = hass.states.get("climate.zone_thermostat_jessie") + attrs = state.attributes + + async def test_adam_climate_entity_climate_changes(hass, mock_smile_adam): """Test handling of user requests in adam climate device environment.""" entry = await async_init_integration(hass, mock_smile_adam) @@ -112,7 +153,7 @@ async def test_anna_climate_entity_attributes(hass, mock_smile_anna): assert attrs["current_temperature"] == 23.3 assert attrs["temperature"] == 21.0 - assert state.state == "auto" + assert state.state == HVAC_MODE_AUTO assert attrs["hvac_action"] == "idle" assert attrs["preset_mode"] == "home" diff --git a/tests/components/plugwise/test_config_flow.py b/tests/components/plugwise/test_config_flow.py index dea42dfb01d..fc0e5f9e69f 100644 --- a/tests/components/plugwise/test_config_flow.py +++ b/tests/components/plugwise/test_config_flow.py @@ -1,5 +1,9 @@ """Test the Plugwise config flow.""" -from Plugwise_Smile.Smile import Smile +from plugwise.exceptions import ( + ConnectionFailedError, + InvalidAuthentication, + PlugwiseException, +) import pytest from homeassistant import config_entries, data_entry_flow, setup @@ -47,9 +51,9 @@ def mock_smile(): with patch( "homeassistant.components.plugwise.config_flow.Smile", ) as smile_mock: - smile_mock.PlugwiseError = Smile.PlugwiseError - smile_mock.InvalidAuthentication = Smile.InvalidAuthentication - smile_mock.ConnectionFailedError = Smile.ConnectionFailedError + smile_mock.PlugwiseError = PlugwiseException + smile_mock.InvalidAuthentication = InvalidAuthentication + smile_mock.ConnectionFailedError = ConnectionFailedError smile_mock.return_value.connect.return_value = True yield smile_mock.return_value @@ -207,7 +211,7 @@ async def test_form_invalid_auth(hass, mock_smile): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - mock_smile.connect.side_effect = Smile.InvalidAuthentication + mock_smile.connect.side_effect = InvalidAuthentication mock_smile.gateway_id = "0a636a4fc1704ab4a24e4f7e37fb187a" result2 = await hass.config_entries.flow.async_configure( @@ -225,7 +229,7 @@ async def test_form_cannot_connect(hass, mock_smile): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - mock_smile.connect.side_effect = Smile.ConnectionFailedError + mock_smile.connect.side_effect = ConnectionFailedError mock_smile.gateway_id = "0a636a4fc1704ab4a24e4f7e37fb187a" result2 = await hass.config_entries.flow.async_configure( @@ -243,7 +247,7 @@ async def test_form_cannot_connect_port(hass, mock_smile): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - mock_smile.connect.side_effect = Smile.ConnectionFailedError + mock_smile.connect.side_effect = ConnectionFailedError mock_smile.gateway_id = "0a636a4fc1704ab4a24e4f7e37fb187a" result2 = await hass.config_entries.flow.async_configure( diff --git a/tests/components/plugwise/test_init.py b/tests/components/plugwise/test_init.py index db7a71d660b..eded1e55406 100644 --- a/tests/components/plugwise/test_init.py +++ b/tests/components/plugwise/test_init.py @@ -2,9 +2,9 @@ import asyncio -from Plugwise_Smile.Smile import Smile +from plugwise.exceptions import XMLDataMissingError -from homeassistant.components.plugwise import DOMAIN +from homeassistant.components.plugwise.const import DOMAIN from homeassistant.config_entries import ( ENTRY_STATE_NOT_LOADED, ENTRY_STATE_SETUP_ERROR, @@ -43,7 +43,7 @@ async def test_smile_timeout(hass, mock_smile_notconnect): async def test_smile_adam_xmlerror(hass, mock_smile_adam): """Detect malformed XML by Smile in Adam environment.""" - mock_smile_adam.full_update_device.side_effect = Smile.XMLDataMissingError + mock_smile_adam.full_update_device.side_effect = XMLDataMissingError entry = await async_init_integration(hass, mock_smile_adam) assert entry.state == ENTRY_STATE_SETUP_RETRY diff --git a/tests/components/plugwise/test_switch.py b/tests/components/plugwise/test_switch.py index ded21113f2b..b7237a26150 100644 --- a/tests/components/plugwise/test_switch.py +++ b/tests/components/plugwise/test_switch.py @@ -1,5 +1,7 @@ """Tests for the Plugwise switch integration.""" +from plugwise.exceptions import PlugwiseException + from homeassistant.config_entries import ENTRY_STATE_LOADED from tests.components.plugwise.common import async_init_integration @@ -17,6 +19,31 @@ async def test_adam_climate_switch_entities(hass, mock_smile_adam): assert str(state.state) == "on" +async def test_adam_climate_switch_negative_testing(hass, mock_smile_adam): + """Test exceptions of climate related switch entities.""" + mock_smile_adam.set_relay_state.side_effect = PlugwiseException + entry = await async_init_integration(hass, mock_smile_adam) + assert entry.state == ENTRY_STATE_LOADED + + await hass.services.async_call( + "switch", + "turn_off", + {"entity_id": "switch.cv_pomp"}, + blocking=True, + ) + state = hass.states.get("switch.cv_pomp") + assert str(state.state) == "on" + + await hass.services.async_call( + "switch", + "turn_on", + {"entity_id": "switch.fibaro_hc2"}, + blocking=True, + ) + state = hass.states.get("switch.fibaro_hc2") + assert str(state.state) == "on" + + async def test_adam_climate_switch_changes(hass, mock_smile_adam): """Test changing of climate related switch entities.""" entry = await async_init_integration(hass, mock_smile_adam)