mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 09:23:17 -04:00
Add Switcher heater support (#162588)
Co-authored-by: Shay Levy <levyshay1@gmail.com>
This commit is contained in:
co-authored by
Shay Levy
parent
95df5b9ec9
commit
b11a75d438
@@ -7,6 +7,6 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aioswitcher"],
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["aioswitcher==6.0.0"],
|
||||
"requirements": ["aioswitcher==6.1.0"],
|
||||
"single_config_entry": true
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ TEMPERATURE_SENSORS: list[SwitcherSensorEntityDescription] = [
|
||||
]
|
||||
|
||||
POWER_PLUG_SENSORS = POWER_SENSORS
|
||||
WATER_HEATER_SENSORS = [*POWER_SENSORS, *TIME_SENSORS]
|
||||
HEATER_SENSORS = [*POWER_SENSORS, *TIME_SENSORS]
|
||||
THERMOSTAT_SENSORS = TEMPERATURE_SENSORS
|
||||
|
||||
|
||||
@@ -100,10 +100,13 @@ async def async_setup_entry(
|
||||
SwitcherSensorEntity(coordinator, description)
|
||||
for description in POWER_PLUG_SENSORS
|
||||
)
|
||||
elif coordinator.data.device_type.category == DeviceCategory.WATER_HEATER:
|
||||
elif coordinator.data.device_type.category in [
|
||||
DeviceCategory.WATER_HEATER,
|
||||
DeviceCategory.HEATER,
|
||||
]:
|
||||
async_add_entities(
|
||||
SwitcherSensorEntity(coordinator, description)
|
||||
for description in WATER_HEATER_SENSORS
|
||||
for description in HEATER_SENSORS
|
||||
)
|
||||
elif coordinator.data.device_type.category == DeviceCategory.THERMOSTAT:
|
||||
async_add_entities(
|
||||
|
||||
@@ -79,8 +79,11 @@ async def async_setup_entry(
|
||||
|
||||
if coordinator.data.device_type.category == DeviceCategory.POWER_PLUG:
|
||||
entities.append(SwitcherPowerPlugSwitchEntity(coordinator))
|
||||
elif coordinator.data.device_type.category == DeviceCategory.WATER_HEATER:
|
||||
entities.append(SwitcherWaterHeaterSwitchEntity(coordinator))
|
||||
elif coordinator.data.device_type.category in [
|
||||
DeviceCategory.WATER_HEATER,
|
||||
DeviceCategory.HEATER,
|
||||
]:
|
||||
entities.append(SwitcherHeaterSwitchEntity(coordinator))
|
||||
elif coordinator.data.device_type.category in (
|
||||
DeviceCategory.SHUTTER,
|
||||
DeviceCategory.SINGLE_SHUTTER_DUAL_LIGHT,
|
||||
@@ -143,8 +146,8 @@ class SwitcherPowerPlugSwitchEntity(SwitcherBaseSwitchEntity):
|
||||
_attr_device_class = SwitchDeviceClass.OUTLET
|
||||
|
||||
|
||||
class SwitcherWaterHeaterSwitchEntity(SwitcherBaseSwitchEntity):
|
||||
"""Representation of a Switcher water heater switch entity."""
|
||||
class SwitcherHeaterSwitchEntity(SwitcherBaseSwitchEntity):
|
||||
"""Representation of a Switcher heater switch entity."""
|
||||
|
||||
_attr_device_class = SwitchDeviceClass.SWITCH
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -413,7 +413,7 @@ aiosteamist==1.0.1
|
||||
aiostreammagic==2.12.1
|
||||
|
||||
# homeassistant.components.switcher_kis
|
||||
aioswitcher==6.0.0
|
||||
aioswitcher==6.1.0
|
||||
|
||||
# homeassistant.components.syncthing
|
||||
aiosyncthing==0.7.1
|
||||
|
||||
Generated
+1
-1
@@ -398,7 +398,7 @@ aiosteamist==1.0.1
|
||||
aiostreammagic==2.12.1
|
||||
|
||||
# homeassistant.components.switcher_kis
|
||||
aioswitcher==6.0.0
|
||||
aioswitcher==6.1.0
|
||||
|
||||
# homeassistant.components.syncthing
|
||||
aiosyncthing==0.7.1
|
||||
|
||||
@@ -6,6 +6,7 @@ from aioswitcher.device import (
|
||||
ShutterChildLock,
|
||||
ShutterDirection,
|
||||
SwitcherDualShutterSingleLight,
|
||||
SwitcherHeater,
|
||||
SwitcherLight,
|
||||
SwitcherPowerPlug,
|
||||
SwitcherShutter,
|
||||
@@ -28,6 +29,7 @@ DUMMY_DEVICE_ID6 = "bcdc64"
|
||||
DUMMY_DEVICE_ID7 = "bcdd64"
|
||||
DUMMY_DEVICE_ID8 = "bcde64"
|
||||
DUMMY_DEVICE_ID9 = "bcdf64"
|
||||
DUMMY_DEVICE_ID10 = "cafe66"
|
||||
DUMMY_DEVICE_KEY1 = "18"
|
||||
DUMMY_DEVICE_KEY2 = "01"
|
||||
DUMMY_DEVICE_KEY3 = "12"
|
||||
@@ -37,8 +39,9 @@ DUMMY_DEVICE_KEY6 = "16"
|
||||
DUMMY_DEVICE_KEY7 = "17"
|
||||
DUMMY_DEVICE_KEY8 = "18"
|
||||
DUMMY_DEVICE_KEY9 = "19"
|
||||
DUMMY_DEVICE_KEY10 = "20"
|
||||
DUMMY_DEVICE_NAME1 = "Plug 23BC"
|
||||
DUMMY_DEVICE_NAME2 = "Heater FE12"
|
||||
DUMMY_DEVICE_NAME2 = "WaterHeater FE12"
|
||||
DUMMY_DEVICE_NAME3 = "Breeze AB39"
|
||||
DUMMY_DEVICE_NAME4 = "Runner DD77"
|
||||
DUMMY_DEVICE_NAME5 = "RunnerS11 6CF5"
|
||||
@@ -46,9 +49,11 @@ DUMMY_DEVICE_NAME6 = "RunnerS12 A9BE"
|
||||
DUMMY_DEVICE_NAME7 = "Light 36BB"
|
||||
DUMMY_DEVICE_NAME8 = "Light 36CB"
|
||||
DUMMY_DEVICE_NAME9 = "Light 36DB"
|
||||
DUMMY_DEVICE_NAME10 = "Heater FE66"
|
||||
DUMMY_DEVICE_PASSWORD = "12345678"
|
||||
DUMMY_ELECTRIC_CURRENT1 = 0.5
|
||||
DUMMY_ELECTRIC_CURRENT2 = 12.8
|
||||
DUMMY_ELECTRIC_CURRENT3 = 10.0
|
||||
DUMMY_IP_ADDRESS1 = "192.168.100.157"
|
||||
DUMMY_IP_ADDRESS2 = "192.168.100.158"
|
||||
DUMMY_IP_ADDRESS3 = "192.168.100.159"
|
||||
@@ -58,6 +63,7 @@ DUMMY_IP_ADDRESS6 = "192.168.100.162"
|
||||
DUMMY_IP_ADDRESS7 = "192.168.100.163"
|
||||
DUMMY_IP_ADDRESS8 = "192.168.100.164"
|
||||
DUMMY_IP_ADDRESS9 = "192.168.100.165"
|
||||
DUMMY_IP_ADDRESS10 = "192.168.100.166"
|
||||
DUMMY_MAC_ADDRESS1 = "A1:B2:C3:45:67:D8"
|
||||
DUMMY_MAC_ADDRESS2 = "A1:B2:C3:45:67:D9"
|
||||
DUMMY_MAC_ADDRESS3 = "A1:B2:C3:45:67:DA"
|
||||
@@ -67,6 +73,7 @@ DUMMY_MAC_ADDRESS6 = "A1:B2:C3:45:67:DD"
|
||||
DUMMY_MAC_ADDRESS7 = "A1:B2:C3:45:67:DE"
|
||||
DUMMY_MAC_ADDRESS8 = "A1:B2:C3:45:67:DF"
|
||||
DUMMY_MAC_ADDRESS9 = "A1:B2:C3:45:67:DG"
|
||||
DUMMY_MAC_ADDRESS10 = "A1:B2:C3:45:67:DH"
|
||||
DUMMY_TOKEN_NEEDED1 = False
|
||||
DUMMY_TOKEN_NEEDED2 = False
|
||||
DUMMY_TOKEN_NEEDED3 = False
|
||||
@@ -76,9 +83,11 @@ DUMMY_TOKEN_NEEDED6 = True
|
||||
DUMMY_TOKEN_NEEDED7 = True
|
||||
DUMMY_TOKEN_NEEDED8 = True
|
||||
DUMMY_TOKEN_NEEDED9 = True
|
||||
DUMMY_TOKEN_NEEDED10 = True
|
||||
DUMMY_PHONE_ID = "1234"
|
||||
DUMMY_POWER_CONSUMPTION1 = 100
|
||||
DUMMY_POWER_CONSUMPTION2 = 2780
|
||||
DUMMY_POWER_CONSUMPTION3 = 1000
|
||||
DUMMY_REMAINING_TIME = "01:29:32"
|
||||
DUMMY_TIMER_MINUTES_SET = "90"
|
||||
DUMMY_THERMOSTAT_MODE = ThermostatMode.COOL
|
||||
@@ -127,6 +136,21 @@ DUMMY_WATER_HEATER_DEVICE = SwitcherWaterHeater(
|
||||
DUMMY_AUTO_SHUT_DOWN,
|
||||
)
|
||||
|
||||
DUMMY_HEATER_DEVICE = SwitcherHeater(
|
||||
DeviceType.HEATER,
|
||||
DeviceState.ON,
|
||||
DUMMY_DEVICE_ID10,
|
||||
DUMMY_DEVICE_KEY10,
|
||||
DUMMY_IP_ADDRESS10,
|
||||
DUMMY_MAC_ADDRESS10,
|
||||
DUMMY_DEVICE_NAME10,
|
||||
DUMMY_TOKEN_NEEDED10,
|
||||
DUMMY_POWER_CONSUMPTION3,
|
||||
DUMMY_ELECTRIC_CURRENT3,
|
||||
DUMMY_REMAINING_TIME,
|
||||
DUMMY_AUTO_SHUT_DOWN,
|
||||
)
|
||||
|
||||
DUMMY_SHUTTER_DEVICE = SwitcherShutter(
|
||||
DeviceType.RUNNER,
|
||||
DeviceState.ON,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
'ip_address': '**REDACTED**',
|
||||
'last_data_update': '2022-09-28T16:42:12.706017',
|
||||
'mac_address': '**REDACTED**',
|
||||
'name': 'Heater FE12',
|
||||
'name': 'WaterHeater FE12',
|
||||
'power_consumption': 2780,
|
||||
'remaining_time': '01:29:32',
|
||||
'token_needed': False,
|
||||
|
||||
@@ -14,7 +14,15 @@ from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util, slugify
|
||||
|
||||
from . import init_integration
|
||||
from .consts import DUMMY_DEVICE_ID1, DUMMY_DEVICE_ID4, DUMMY_SWITCHER_DEVICES
|
||||
from .consts import (
|
||||
DUMMY_DEVICE_ID1,
|
||||
DUMMY_DEVICE_ID4,
|
||||
DUMMY_DEVICE_ID10,
|
||||
DUMMY_HEATER_DEVICE,
|
||||
DUMMY_SWITCHER_DEVICES,
|
||||
DUMMY_TOKEN as TOKEN,
|
||||
DUMMY_USERNAME as USERNAME,
|
||||
)
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.typing import WebSocketGenerator
|
||||
@@ -71,6 +79,57 @@ async def test_update_fail(
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
|
||||
|
||||
async def test_update_fail_token_needed(
|
||||
hass: HomeAssistant,
|
||||
mock_bridge,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test entities state unavailable when updates fail.."""
|
||||
entry = await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
|
||||
mock_bridge.mock_callbacks([DUMMY_HEATER_DEVICE])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(entry.runtime_data) == 1
|
||||
|
||||
freezer.tick(timedelta(seconds=MAX_UPDATE_INTERVAL_SEC + 1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
f"Device {device.name} did not send update for {MAX_UPDATE_INTERVAL_SEC} seconds"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
entity_id = f"switch.{slugify(device.name)}"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
entity_id = f"sensor.{slugify(device.name)}_power"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
mock_bridge.mock_callbacks([DUMMY_HEATER_DEVICE])
|
||||
await hass.async_block_till_done()
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + timedelta(seconds=MAX_UPDATE_INTERVAL_SEC - 2)
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = f"switch.{slugify(device.name)}"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
|
||||
entity_id = f"sensor.{slugify(device.name)}_power"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
|
||||
|
||||
async def test_entry_unload(hass: HomeAssistant, mock_bridge) -> None:
|
||||
"""Test entry unload."""
|
||||
entry = await init_integration(hass)
|
||||
@@ -139,3 +198,58 @@ async def test_remove_device(
|
||||
assert (
|
||||
device_registry.async_get_device(identifiers={(DOMAIN, dead_device_id)}) is None
|
||||
)
|
||||
|
||||
|
||||
async def test_remove_device_token_needed(
|
||||
hass: HomeAssistant,
|
||||
mock_bridge,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test being able to remove a disconnected device."""
|
||||
assert await async_setup_component(hass, "config", {})
|
||||
entry = await init_integration(hass, USERNAME, TOKEN)
|
||||
entry_id = entry.entry_id
|
||||
assert mock_bridge
|
||||
|
||||
mock_bridge.mock_callbacks([DUMMY_HEATER_DEVICE])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(entry.runtime_data) == 1
|
||||
|
||||
live_device_id = DUMMY_DEVICE_ID10
|
||||
dead_device_id = DUMMY_DEVICE_ID4
|
||||
|
||||
assert len(dr.async_entries_for_config_entry(device_registry, entry_id)) == 1
|
||||
|
||||
# Create a dead device
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, dead_device_id)},
|
||||
manufacturer="Switcher",
|
||||
model="Switcher Model",
|
||||
name="Switcher Device",
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(dr.async_entries_for_config_entry(device_registry, entry_id)) == 2
|
||||
|
||||
# Try to remove a live device - fails
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, live_device_id)})
|
||||
client = await hass_ws_client(hass)
|
||||
response = await client.remove_device(device.id, entry_id)
|
||||
assert not response["success"]
|
||||
assert len(dr.async_entries_for_config_entry(device_registry, entry_id)) == 2
|
||||
assert (
|
||||
device_registry.async_get_device(identifiers={(DOMAIN, live_device_id)})
|
||||
is not None
|
||||
)
|
||||
|
||||
# Try to remove a dead device - succeeds
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, dead_device_id)})
|
||||
response = await client.remove_device(device.id, entry_id)
|
||||
assert response["success"]
|
||||
assert len(dr.async_entries_for_config_entry(device_registry, entry_id)) == 1
|
||||
assert (
|
||||
device_registry.async_get_device(identifiers={(DOMAIN, dead_device_id)}) is None
|
||||
)
|
||||
|
||||
@@ -7,9 +7,12 @@ from homeassistant.util import slugify
|
||||
|
||||
from . import init_integration
|
||||
from .consts import (
|
||||
DUMMY_HEATER_DEVICE,
|
||||
DUMMY_PLUG_DEVICE,
|
||||
DUMMY_SWITCHER_SENSORS_DEVICES,
|
||||
DUMMY_THERMOSTAT_DEVICE,
|
||||
DUMMY_TOKEN as TOKEN,
|
||||
DUMMY_USERNAME as USERNAME,
|
||||
DUMMY_WATER_HEATER_DEVICE,
|
||||
)
|
||||
|
||||
@@ -37,6 +40,17 @@ DEVICE_SENSORS_TUPLE = (
|
||||
),
|
||||
)
|
||||
|
||||
DEVICE_SENSORS_TOKEN_NEEDED_TUPLE = (
|
||||
(
|
||||
DUMMY_HEATER_DEVICE,
|
||||
[
|
||||
("power", "power_consumption"),
|
||||
("current", "electric_current"),
|
||||
("remaining_time", "remaining_time"),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [DUMMY_SWITCHER_SENSORS_DEVICES], indirect=True)
|
||||
async def test_sensor_platform(hass: HomeAssistant, mock_bridge) -> None:
|
||||
@@ -54,6 +68,22 @@ async def test_sensor_platform(hass: HomeAssistant, mock_bridge) -> None:
|
||||
assert state.state == str(getattr(device, field))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_sensor_platform_token_needed(hass: HomeAssistant, mock_bridge) -> None:
|
||||
"""Test sensor platform."""
|
||||
entry = await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
assert mock_bridge.is_running is True
|
||||
assert len(entry.runtime_data) == 1
|
||||
|
||||
for device, sensors in DEVICE_SENSORS_TOKEN_NEEDED_TUPLE:
|
||||
for sensor, field in sensors:
|
||||
entity_id = f"sensor.{slugify(device.name)}_{sensor}"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == str(getattr(device, field))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_WATER_HEATER_DEVICE]], indirect=True)
|
||||
async def test_sensor_update(
|
||||
hass: HomeAssistant, mock_bridge, monkeypatch: pytest.MonkeyPatch
|
||||
@@ -75,3 +105,26 @@ async def test_sensor_update(
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "1431"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_sensor_update_token_needed(
|
||||
hass: HomeAssistant, mock_bridge, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Test sensor update."""
|
||||
await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
field = "power_consumption"
|
||||
entity_id = f"sensor.{slugify(device.name)}_power"
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == str(getattr(device, field))
|
||||
|
||||
monkeypatch.setattr(device, field, 1431)
|
||||
mock_bridge.mock_callbacks([device])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "1431"
|
||||
|
||||
@@ -23,8 +23,11 @@ from homeassistant.util import slugify
|
||||
from . import init_integration
|
||||
from .consts import (
|
||||
DUMMY_AUTO_OFF_SET,
|
||||
DUMMY_HEATER_DEVICE,
|
||||
DUMMY_PLUG_DEVICE,
|
||||
DUMMY_TIMER_MINUTES_SET,
|
||||
DUMMY_TOKEN as TOKEN,
|
||||
DUMMY_USERNAME as USERNAME,
|
||||
DUMMY_WATER_HEATER_DEVICE,
|
||||
)
|
||||
|
||||
@@ -69,6 +72,46 @@ async def test_turn_on_with_timer_service(
|
||||
assert state.state == STATE_ON
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_turn_on_with_timer_service_token_needed(
|
||||
hass: HomeAssistant, mock_bridge, mock_api, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Test the turn on with timer service."""
|
||||
await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
entity_id = f"{SWITCH_DOMAIN}.{slugify(device.name)}"
|
||||
|
||||
# Test initial state - off
|
||||
monkeypatch.setattr(device, "device_state", DeviceState.OFF)
|
||||
mock_bridge.mock_callbacks([DUMMY_HEATER_DEVICE])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.switcher_kis.entity.SwitcherApi.control_device"
|
||||
) as mock_control_device:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_TURN_ON_WITH_TIMER_NAME,
|
||||
{
|
||||
ATTR_ENTITY_ID: entity_id,
|
||||
CONF_TIMER_MINUTES: DUMMY_TIMER_MINUTES_SET,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert mock_api.call_count == 2
|
||||
mock_control_device.assert_called_once_with(
|
||||
Command.ON, int(DUMMY_TIMER_MINUTES_SET)
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_WATER_HEATER_DEVICE]], indirect=True)
|
||||
async def test_set_auto_off_service(hass: HomeAssistant, mock_bridge, mock_api) -> None:
|
||||
"""Test the set auto off service."""
|
||||
@@ -94,6 +137,31 @@ async def test_set_auto_off_service(hass: HomeAssistant, mock_bridge, mock_api)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_set_auto_off_service_token_needed(
|
||||
hass: HomeAssistant, mock_bridge, mock_api
|
||||
) -> None:
|
||||
"""Test the set auto off service."""
|
||||
await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
entity_id = f"{SWITCH_DOMAIN}.{slugify(device.name)}"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.switcher_kis.entity.SwitcherApi.set_auto_shutdown"
|
||||
) as mock_set_auto_shutdown:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_AUTO_OFF_NAME,
|
||||
{ATTR_ENTITY_ID: entity_id, CONF_AUTO_OFF: DUMMY_AUTO_OFF_SET},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert mock_api.call_count == 2
|
||||
mock_set_auto_shutdown.assert_called_once_with(time_period_str(DUMMY_AUTO_OFF_SET))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_WATER_HEATER_DEVICE]], indirect=True)
|
||||
async def test_set_auto_off_service_fail(
|
||||
hass: HomeAssistant, mock_bridge, mock_api
|
||||
@@ -125,6 +193,37 @@ async def test_set_auto_off_service_fail(
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_set_auto_off_service_fail_token_needed(
|
||||
hass: HomeAssistant, mock_bridge, mock_api
|
||||
) -> None:
|
||||
"""Test set auto off service failed."""
|
||||
await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
entity_id = f"{SWITCH_DOMAIN}.{slugify(device.name)}"
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.switcher_kis.entity.SwitcherApi.set_auto_shutdown",
|
||||
return_value=None,
|
||||
) as mock_set_auto_shutdown,
|
||||
pytest.raises(HomeAssistantError),
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_AUTO_OFF_NAME,
|
||||
{ATTR_ENTITY_ID: entity_id, CONF_AUTO_OFF: DUMMY_AUTO_OFF_SET},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert mock_api.call_count == 2
|
||||
mock_set_auto_shutdown.assert_called_once_with(time_period_str(DUMMY_AUTO_OFF_SET))
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_PLUG_DEVICE]], indirect=True)
|
||||
async def test_plug_unsupported_services(
|
||||
hass: HomeAssistant, mock_bridge, mock_api, caplog: pytest.LogCaptureFixture
|
||||
|
||||
@@ -23,6 +23,7 @@ from homeassistant.util import slugify
|
||||
from . import init_integration
|
||||
from .consts import (
|
||||
DUMMY_DUAL_SHUTTER_SINGLE_LIGHT_DEVICE as DEVICE3,
|
||||
DUMMY_HEATER_DEVICE,
|
||||
DUMMY_PLUG_DEVICE,
|
||||
DUMMY_SHUTTER_DEVICE as DEVICE,
|
||||
DUMMY_SINGLE_SHUTTER_DUAL_LIGHT_DEVICE as DEVICE2,
|
||||
@@ -87,6 +88,56 @@ async def test_switch(
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_HEATER_DEVICE]], indirect=True)
|
||||
async def test_switch_token_needed(
|
||||
hass: HomeAssistant, mock_bridge, mock_api, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Test the switch."""
|
||||
await init_integration(hass, USERNAME, TOKEN)
|
||||
assert mock_bridge
|
||||
|
||||
device = DUMMY_HEATER_DEVICE
|
||||
entity_id = f"{SWITCH_DOMAIN}.{slugify(device.name)}"
|
||||
|
||||
# Test initial state - on
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Test state change on --> off
|
||||
monkeypatch.setattr(device, "device_state", DeviceState.OFF)
|
||||
mock_bridge.mock_callbacks([device])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
# Test turning on
|
||||
with patch(
|
||||
"homeassistant.components.switcher_kis.entity.SwitcherApi.control_device",
|
||||
) as mock_control_device:
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
|
||||
assert mock_api.call_count == 2
|
||||
mock_control_device.assert_called_once_with(Command.ON)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Test turning off
|
||||
with patch(
|
||||
"homeassistant.components.switcher_kis.entity.SwitcherApi.control_device"
|
||||
) as mock_control_device:
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
|
||||
assert mock_api.call_count == 4
|
||||
mock_control_device.assert_called_once_with(Command.OFF)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_bridge", [[DUMMY_WATER_HEATER_DEVICE]], indirect=True)
|
||||
async def test_switch_ignore_previous_async_state(
|
||||
hass: HomeAssistant, mock_bridge, mock_api
|
||||
|
||||
Reference in New Issue
Block a user