From 115fe266425654d042d633a20c5119918ffbcbcc Mon Sep 17 00:00:00 2001 From: Matt Zimmerman Date: Sat, 20 Feb 2021 14:25:02 -0800 Subject: [PATCH] Add smarttub sensor platform and state sensor (#46775) --- homeassistant/components/smarttub/__init__.py | 2 +- homeassistant/components/smarttub/climate.py | 5 --- homeassistant/components/smarttub/entity.py | 5 +++ homeassistant/components/smarttub/sensor.py | 30 ++++++++++++++++++ tests/components/smarttub/__init__.py | 14 +++++++++ tests/components/smarttub/conftest.py | 11 ++++++- tests/components/smarttub/test_climate.py | 31 ++----------------- tests/components/smarttub/test_config_flow.py | 2 +- tests/components/smarttub/test_init.py | 6 ++-- tests/components/smarttub/test_sensor.py | 18 +++++++++++ 10 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 homeassistant/components/smarttub/sensor.py create mode 100644 tests/components/smarttub/test_sensor.py diff --git a/homeassistant/components/smarttub/__init__.py b/homeassistant/components/smarttub/__init__.py index 4700b0df4de..2b80c92510f 100644 --- a/homeassistant/components/smarttub/__init__.py +++ b/homeassistant/components/smarttub/__init__.py @@ -7,7 +7,7 @@ from .controller import SmartTubController _LOGGER = logging.getLogger(__name__) -PLATFORMS = ["climate"] +PLATFORMS = ["climate", "sensor"] async def async_setup(hass, config): diff --git a/homeassistant/components/smarttub/climate.py b/homeassistant/components/smarttub/climate.py index 5f16bea8cf7..02d627d383e 100644 --- a/homeassistant/components/smarttub/climate.py +++ b/homeassistant/components/smarttub/climate.py @@ -36,11 +36,6 @@ class SmartTubThermostat(SmartTubEntity, ClimateEntity): """Initialize the entity.""" super().__init__(coordinator, spa, "thermostat") - @property - def unique_id(self) -> str: - """Return a unique id for the entity.""" - return f"{self.spa.id}-{self._entity_type}" - @property def temperature_unit(self): """Return the unit of measurement used by the platform.""" diff --git a/homeassistant/components/smarttub/entity.py b/homeassistant/components/smarttub/entity.py index 95d89971cb7..0e84c92e3e1 100644 --- a/homeassistant/components/smarttub/entity.py +++ b/homeassistant/components/smarttub/entity.py @@ -32,6 +32,11 @@ class SmartTubEntity(CoordinatorEntity): self.spa = spa self._entity_type = entity_type + @property + def unique_id(self) -> str: + """Return a unique id for the entity.""" + return f"{self.spa.id}-{self._entity_type}" + @property def device_info(self) -> str: """Return device info.""" diff --git a/homeassistant/components/smarttub/sensor.py b/homeassistant/components/smarttub/sensor.py new file mode 100644 index 00000000000..320f288f36a --- /dev/null +++ b/homeassistant/components/smarttub/sensor.py @@ -0,0 +1,30 @@ +"""Platform for sensor integration.""" +import logging + +from .const import DOMAIN, SMARTTUB_CONTROLLER +from .entity import SmartTubEntity + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass, entry, async_add_entities): + """Set up climate entity for the thermostat in the tub.""" + + controller = hass.data[DOMAIN][entry.entry_id][SMARTTUB_CONTROLLER] + + entities = [SmartTubState(controller.coordinator, spa) for spa in controller.spas] + + async_add_entities(entities) + + +class SmartTubState(SmartTubEntity): + """The state of the spa.""" + + def __init__(self, coordinator, spa): + """Initialize the entity.""" + super().__init__(coordinator, spa, "state") + + @property + def state(self) -> str: + """Return the current state of the sensor.""" + return self.get_spa_status("state").lower() diff --git a/tests/components/smarttub/__init__.py b/tests/components/smarttub/__init__.py index afbf271eb63..b19af1ee59a 100644 --- a/tests/components/smarttub/__init__.py +++ b/tests/components/smarttub/__init__.py @@ -1 +1,15 @@ """Tests for the smarttub integration.""" + +from datetime import timedelta + +from homeassistant.components.smarttub.const import SCAN_INTERVAL +from homeassistant.util import dt + +from tests.common import async_fire_time_changed + + +async def trigger_update(hass): + """Trigger a polling update by moving time forward.""" + new_time = dt.utcnow() + timedelta(seconds=SCAN_INTERVAL + 1) + async_fire_time_changed(hass, new_time) + await hass.async_block_till_done() diff --git a/tests/components/smarttub/conftest.py b/tests/components/smarttub/conftest.py index 3519d4f85ce..d1bd7c377e3 100644 --- a/tests/components/smarttub/conftest.py +++ b/tests/components/smarttub/conftest.py @@ -46,6 +46,7 @@ def mock_spa(): "setTemperature": 39, "water": {"temperature": 38}, "heater": "ON", + "state": "NORMAL", } return mock_spa @@ -60,7 +61,7 @@ def mock_account(spa): return mock_account -@pytest.fixture(name="smarttub_api") +@pytest.fixture(name="smarttub_api", autouse=True) def mock_api(account, spa): """Mock the SmartTub API.""" @@ -71,3 +72,11 @@ def mock_api(account, spa): api_mock = api_class_mock.return_value api_mock.get_account.return_value = account yield api_mock + + +@pytest.fixture +async def setup_entry(hass, config_entry): + """Initialize the config entry.""" + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() diff --git a/tests/components/smarttub/test_climate.py b/tests/components/smarttub/test_climate.py index ad47e3ede04..69fb642aab4 100644 --- a/tests/components/smarttub/test_climate.py +++ b/tests/components/smarttub/test_climate.py @@ -1,7 +1,5 @@ """Test the SmartTub climate platform.""" -from datetime import timedelta - import smarttub from homeassistant.components.climate.const import ( @@ -19,35 +17,19 @@ from homeassistant.components.climate.const import ( SERVICE_SET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE, ) -from homeassistant.components.smarttub.const import ( - DEFAULT_MAX_TEMP, - DEFAULT_MIN_TEMP, - SCAN_INTERVAL, -) +from homeassistant.components.smarttub.const import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, ) -from homeassistant.util import dt -from tests.common import async_fire_time_changed +from . import trigger_update -async def test_thermostat_update(spa, hass, config_entry, smarttub_api): +async def test_thermostat_update(spa, setup_entry, hass): """Test the thermostat entity.""" - spa.get_status.return_value = { - "heater": "ON", - "water": { - "temperature": 38, - }, - "setTemperature": 39, - } - config_entry.add_to_hass(hass) - await hass.config_entries.async_setup(config_entry.entry_id) - await hass.async_block_till_done() - entity_id = f"climate.{spa.brand}_{spa.model}_thermostat" state = hass.states.get(entity_id) assert state @@ -87,10 +69,3 @@ async def test_thermostat_update(spa, hass, config_entry, smarttub_api): spa.get_status.side_effect = smarttub.APIError await trigger_update(hass) # should not fail - - -async def trigger_update(hass): - """Trigger a polling update by moving time forward.""" - new_time = dt.utcnow() + timedelta(seconds=SCAN_INTERVAL + 1) - async_fire_time_changed(hass, new_time) - await hass.async_block_till_done() diff --git a/tests/components/smarttub/test_config_flow.py b/tests/components/smarttub/test_config_flow.py index a57eb43eef7..2608d867c0d 100644 --- a/tests/components/smarttub/test_config_flow.py +++ b/tests/components/smarttub/test_config_flow.py @@ -7,7 +7,7 @@ from homeassistant import config_entries from homeassistant.components.smarttub.const import DOMAIN -async def test_form(hass, smarttub_api): +async def test_form(hass): """Test we get the form.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} diff --git a/tests/components/smarttub/test_init.py b/tests/components/smarttub/test_init.py index 13a447529d4..01989818d3b 100644 --- a/tests/components/smarttub/test_init.py +++ b/tests/components/smarttub/test_init.py @@ -39,15 +39,13 @@ async def test_setup_auth_failed(setup_component, hass, config_entry, smarttub_a assert config_entry.state == ENTRY_STATE_SETUP_ERROR -async def test_config_passed_to_config_entry( - hass, config_entry, config_data, smarttub_api -): +async def test_config_passed_to_config_entry(hass, config_entry, config_data): """Test that configured options are loaded via config entry.""" config_entry.add_to_hass(hass) assert await async_setup_component(hass, smarttub.DOMAIN, config_data) -async def test_unload_entry(hass, config_entry, smarttub_api): +async def test_unload_entry(hass, config_entry): """Test being able to unload an entry.""" config_entry.add_to_hass(hass) diff --git a/tests/components/smarttub/test_sensor.py b/tests/components/smarttub/test_sensor.py new file mode 100644 index 00000000000..7d62440295e --- /dev/null +++ b/tests/components/smarttub/test_sensor.py @@ -0,0 +1,18 @@ +"""Test the SmartTub sensor platform.""" + +from . import trigger_update + + +async def test_state_update(spa, setup_entry, hass, smarttub_api): + """Test the state entity.""" + + entity_id = f"sensor.{spa.brand}_{spa.model}_state" + state = hass.states.get(entity_id) + assert state is not None + assert state.state == "normal" + + spa.get_status.return_value["state"] = "BAD" + await trigger_update(hass) + state = hass.states.get(entity_id) + assert state is not None + assert state.state == "bad"