mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add option to reverse switch behaviour in KMTronic (#47532)
This commit is contained in:
parent
520c4a8ee3
commit
ee25723468
@ -15,7 +15,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers import aiohttp_client
|
from homeassistant.helpers import aiohttp_client
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import DATA_COORDINATOR, DATA_HOST, DATA_HUB, DOMAIN, MANUFACTURER
|
from .const import DATA_COORDINATOR, DATA_HUB, DOMAIN, MANUFACTURER, UPDATE_LISTENER
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
@ -67,7 +67,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
DATA_HUB: hub,
|
DATA_HUB: hub,
|
||||||
DATA_HOST: entry.data[DATA_HOST],
|
|
||||||
DATA_COORDINATOR: coordinator,
|
DATA_COORDINATOR: coordinator,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +75,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
hass.config_entries.async_forward_entry_setup(entry, platform)
|
hass.config_entries.async_forward_entry_setup(entry, platform)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
update_listener = entry.add_update_listener(async_update_options)
|
||||||
|
hass.data[DOMAIN][entry.entry_id][UPDATE_LISTENER] = update_listener
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_update_options(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||||
|
"""Update options."""
|
||||||
|
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
unload_ok = all(
|
unload_ok = all(
|
||||||
@ -90,6 +97,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
if unload_ok:
|
if unload_ok:
|
||||||
|
update_listener = hass.data[DOMAIN][entry.entry_id][UPDATE_LISTENER]
|
||||||
|
update_listener()
|
||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
return unload_ok
|
return unload_ok
|
||||||
|
@ -8,13 +8,21 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant import config_entries, core, exceptions
|
from homeassistant import config_entries, core, exceptions
|
||||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers import aiohttp_client
|
from homeassistant.helpers import aiohttp_client
|
||||||
|
|
||||||
|
from .const import CONF_REVERSE
|
||||||
from .const import DOMAIN # pylint:disable=unused-import
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DATA_SCHEMA = vol.Schema({CONF_HOST: str, CONF_USERNAME: str, CONF_PASSWORD: str})
|
DATA_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_HOST): str,
|
||||||
|
vol.Required(CONF_USERNAME): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def validate_input(hass: core.HomeAssistant, data):
|
async def validate_input(hass: core.HomeAssistant, data):
|
||||||
@ -44,6 +52,12 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
VERSION = 1
|
VERSION = 1
|
||||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@callback
|
||||||
|
def async_get_options_flow(config_entry):
|
||||||
|
"""Get the options flow for this handler."""
|
||||||
|
return KMTronicOptionsFlow(config_entry)
|
||||||
|
|
||||||
async def async_step_user(self, user_input=None):
|
async def async_step_user(self, user_input=None):
|
||||||
"""Handle the initial step."""
|
"""Handle the initial step."""
|
||||||
errors = {}
|
errors = {}
|
||||||
@ -71,3 +85,28 @@ class CannotConnect(exceptions.HomeAssistantError):
|
|||||||
|
|
||||||
class InvalidAuth(exceptions.HomeAssistantError):
|
class InvalidAuth(exceptions.HomeAssistantError):
|
||||||
"""Error to indicate there is invalid auth."""
|
"""Error to indicate there is invalid auth."""
|
||||||
|
|
||||||
|
|
||||||
|
class KMTronicOptionsFlow(config_entries.OptionsFlow):
|
||||||
|
"""Handle options."""
|
||||||
|
|
||||||
|
def __init__(self, config_entry):
|
||||||
|
"""Initialize options flow."""
|
||||||
|
self.config_entry = config_entry
|
||||||
|
|
||||||
|
async def async_step_init(self, user_input=None):
|
||||||
|
"""Manage the options."""
|
||||||
|
if user_input is not None:
|
||||||
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="init",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional(
|
||||||
|
CONF_REVERSE,
|
||||||
|
default=self.config_entry.options.get(CONF_REVERSE),
|
||||||
|
): bool,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
DOMAIN = "kmtronic"
|
DOMAIN = "kmtronic"
|
||||||
|
|
||||||
|
CONF_REVERSE = "reverse"
|
||||||
|
|
||||||
DATA_HUB = "hub"
|
DATA_HUB = "hub"
|
||||||
DATA_HOST = "host"
|
|
||||||
DATA_COORDINATOR = "coordinator"
|
DATA_COORDINATOR = "coordinator"
|
||||||
|
|
||||||
MANUFACTURER = "KMtronic"
|
MANUFACTURER = "KMtronic"
|
||||||
ATTR_MANUFACTURER = "manufacturer"
|
ATTR_MANUFACTURER = "manufacturer"
|
||||||
ATTR_IDENTIFIERS = "identifiers"
|
ATTR_IDENTIFIERS = "identifiers"
|
||||||
|
|
||||||
|
UPDATE_LISTENER = "update_listener"
|
||||||
|
@ -17,5 +17,14 @@
|
|||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"reverse": "Reverse switch logic (use NC)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,19 @@
|
|||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
from .const import DATA_COORDINATOR, DATA_HOST, DATA_HUB, DOMAIN
|
from .const import CONF_REVERSE, DATA_COORDINATOR, DATA_HUB, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, entry, async_add_entities):
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
"""Config entry example."""
|
"""Config entry example."""
|
||||||
coordinator = hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR]
|
coordinator = hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR]
|
||||||
hub = hass.data[DOMAIN][entry.entry_id][DATA_HUB]
|
hub = hass.data[DOMAIN][entry.entry_id][DATA_HUB]
|
||||||
host = hass.data[DOMAIN][entry.entry_id][DATA_HOST]
|
reverse = entry.options.get(CONF_REVERSE, False)
|
||||||
await hub.async_get_relays()
|
await hub.async_get_relays()
|
||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
[
|
[
|
||||||
KMtronicSwitch(coordinator, host, relay, entry.unique_id)
|
KMtronicSwitch(coordinator, relay, reverse, entry.entry_id)
|
||||||
for relay in hub.relays
|
for relay in hub.relays
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -24,17 +24,12 @@ async def async_setup_entry(hass, entry, async_add_entities):
|
|||||||
class KMtronicSwitch(CoordinatorEntity, SwitchEntity):
|
class KMtronicSwitch(CoordinatorEntity, SwitchEntity):
|
||||||
"""KMtronic Switch Entity."""
|
"""KMtronic Switch Entity."""
|
||||||
|
|
||||||
def __init__(self, coordinator, host, relay, config_entry_id):
|
def __init__(self, coordinator, relay, reverse, config_entry_id):
|
||||||
"""Pass coordinator to CoordinatorEntity."""
|
"""Pass coordinator to CoordinatorEntity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._host = host
|
|
||||||
self._relay = relay
|
self._relay = relay
|
||||||
self._config_entry_id = config_entry_id
|
self._config_entry_id = config_entry_id
|
||||||
|
self._reverse = reverse
|
||||||
@property
|
|
||||||
def available(self) -> bool:
|
|
||||||
"""Return whether the entity is available."""
|
|
||||||
return self.coordinator.last_update_success
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
@ -46,22 +41,25 @@ class KMtronicSwitch(CoordinatorEntity, SwitchEntity):
|
|||||||
"""Return the unique ID of the entity."""
|
"""Return the unique ID of the entity."""
|
||||||
return f"{self._config_entry_id}_relay{self._relay.id}"
|
return f"{self._config_entry_id}_relay{self._relay.id}"
|
||||||
|
|
||||||
@property
|
|
||||||
def entity_registry_enabled_default(self) -> bool:
|
|
||||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return entity state."""
|
"""Return entity state."""
|
||||||
|
if self._reverse:
|
||||||
|
return not self._relay.is_on
|
||||||
return self._relay.is_on
|
return self._relay.is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs) -> None:
|
async def async_turn_on(self, **kwargs) -> None:
|
||||||
"""Turn the switch on."""
|
"""Turn the switch on."""
|
||||||
|
if self._reverse:
|
||||||
|
await self._relay.turn_off()
|
||||||
|
else:
|
||||||
await self._relay.turn_on()
|
await self._relay.turn_on()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs) -> None:
|
async def async_turn_off(self, **kwargs) -> None:
|
||||||
"""Turn the switch off."""
|
"""Turn the switch off."""
|
||||||
|
if self._reverse:
|
||||||
|
await self._relay.turn_on()
|
||||||
|
else:
|
||||||
await self._relay.turn_off()
|
await self._relay.turn_off()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -13,7 +13,17 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"host": "Host",
|
"host": "Host",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"username": "Username"
|
"username": "Username",
|
||||||
|
"reverse": "Reverse switch logic (use NC)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"reverse": "Reverse switch logic (use NC)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ from unittest.mock import Mock, patch
|
|||||||
|
|
||||||
from aiohttp import ClientConnectorError, ClientResponseError
|
from aiohttp import ClientConnectorError, ClientResponseError
|
||||||
|
|
||||||
from homeassistant import config_entries, setup
|
from homeassistant import config_entries, data_entry_flow, setup
|
||||||
from homeassistant.components.kmtronic.const import DOMAIN
|
from homeassistant.components.kmtronic.const import CONF_REVERSE, DOMAIN
|
||||||
from homeassistant.config_entries import ENTRY_STATE_LOADED, ENTRY_STATE_NOT_LOADED
|
from homeassistant.config_entries import ENTRY_STATE_LOADED
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
@ -49,6 +49,43 @@ async def test_form(hass):
|
|||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_options(hass, aioclient_mock):
|
||||||
|
"""Test that the options form."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
"host": "1.1.1.1",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "admin",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/status.xml",
|
||||||
|
text="<response><relay0>0</relay0><relay1>0</relay1></response>",
|
||||||
|
)
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.state == ENTRY_STATE_LOADED
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_REVERSE: True}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert config_entry.options == {CONF_REVERSE: True}
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.state == "loaded"
|
||||||
|
|
||||||
|
|
||||||
async def test_form_invalid_auth(hass):
|
async def test_form_invalid_auth(hass):
|
||||||
"""Test we handle invalid auth."""
|
"""Test we handle invalid auth."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -116,30 +153,3 @@ async def test_form_unknown_error(hass):
|
|||||||
|
|
||||||
assert result2["type"] == "form"
|
assert result2["type"] == "form"
|
||||||
assert result2["errors"] == {"base": "unknown"}
|
assert result2["errors"] == {"base": "unknown"}
|
||||||
|
|
||||||
|
|
||||||
async def test_unload_config_entry(hass, aioclient_mock):
|
|
||||||
"""Test entry unloading."""
|
|
||||||
|
|
||||||
config_entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN,
|
|
||||||
data={"host": "1.1.1.1", "username": "admin", "password": "admin"},
|
|
||||||
)
|
|
||||||
config_entry.add_to_hass(hass)
|
|
||||||
|
|
||||||
aioclient_mock.get(
|
|
||||||
"http://1.1.1.1/status.xml",
|
|
||||||
text="<response><relay0>0</relay0><relay1>0</relay1></response>",
|
|
||||||
)
|
|
||||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
assert len(config_entries) == 1
|
|
||||||
assert config_entries[0] is config_entry
|
|
||||||
assert config_entry.state == ENTRY_STATE_LOADED
|
|
||||||
|
|
||||||
await hass.config_entries.async_unload(config_entry.entry_id)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert config_entry.state == ENTRY_STATE_NOT_LOADED
|
|
||||||
|
62
tests/components/kmtronic/test_init.py
Normal file
62
tests/components/kmtronic/test_init.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
"""The tests for the KMtronic component."""
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from homeassistant.components.kmtronic.const import DOMAIN
|
||||||
|
from homeassistant.config_entries import (
|
||||||
|
ENTRY_STATE_LOADED,
|
||||||
|
ENTRY_STATE_NOT_LOADED,
|
||||||
|
ENTRY_STATE_SETUP_RETRY,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_unload_config_entry(hass, aioclient_mock):
|
||||||
|
"""Test entry unloading."""
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
"host": "1.1.1.1",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "admin",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/status.xml",
|
||||||
|
text="<response><relay0>0</relay0><relay1>0</relay1></response>",
|
||||||
|
)
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.state == ENTRY_STATE_LOADED
|
||||||
|
|
||||||
|
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.state == ENTRY_STATE_NOT_LOADED
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_entry_not_ready(hass, aioclient_mock):
|
||||||
|
"""Tests configuration entry not ready."""
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/status.xml",
|
||||||
|
exc=asyncio.TimeoutError(),
|
||||||
|
)
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
"host": "1.1.1.1",
|
||||||
|
"username": "foo",
|
||||||
|
"password": "bar",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert config_entry.state == ENTRY_STATE_SETUP_RETRY
|
@ -3,7 +3,6 @@ import asyncio
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant.components.kmtronic.const import DOMAIN
|
from homeassistant.components.kmtronic.const import DOMAIN
|
||||||
from homeassistant.config_entries import ENTRY_STATE_SETUP_RETRY
|
|
||||||
from homeassistant.const import STATE_UNAVAILABLE
|
from homeassistant.const import STATE_UNAVAILABLE
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
@ -88,24 +87,6 @@ async def test_update(hass, aioclient_mock):
|
|||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
|
|
||||||
|
|
||||||
async def test_config_entry_not_ready(hass, aioclient_mock):
|
|
||||||
"""Tests configuration entry not ready."""
|
|
||||||
|
|
||||||
aioclient_mock.get(
|
|
||||||
"http://1.1.1.1/status.xml",
|
|
||||||
exc=asyncio.TimeoutError(),
|
|
||||||
)
|
|
||||||
|
|
||||||
config_entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data={"host": "1.1.1.1", "username": "foo", "password": "bar"}
|
|
||||||
)
|
|
||||||
config_entry.add_to_hass(hass)
|
|
||||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert config_entry.state == ENTRY_STATE_SETUP_RETRY
|
|
||||||
|
|
||||||
|
|
||||||
async def test_failed_update(hass, aioclient_mock):
|
async def test_failed_update(hass, aioclient_mock):
|
||||||
"""Tests coordinator update fails."""
|
"""Tests coordinator update fails."""
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
@ -148,3 +129,51 @@ async def test_failed_update(hass, aioclient_mock):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get("switch.relay1")
|
state = hass.states.get("switch.relay1")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
|
async def test_relay_on_off_reversed(hass, aioclient_mock):
|
||||||
|
"""Tests the relay turns on correctly when configured as reverse."""
|
||||||
|
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/status.xml",
|
||||||
|
text="<response><relay0>0</relay0><relay1>0</relay1></response>",
|
||||||
|
)
|
||||||
|
|
||||||
|
MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={"host": "1.1.1.1", "username": "foo", "password": "bar"},
|
||||||
|
options={"reverse": True},
|
||||||
|
).add_to_hass(hass)
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Mocks the response for turning a relay1 off
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/FF0101",
|
||||||
|
text="",
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("switch.relay1")
|
||||||
|
assert state.state == "on"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch", "turn_off", {"entity_id": "switch.relay1"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("switch.relay1")
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
# Mocks the response for turning a relay1 off
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://1.1.1.1/FF0100",
|
||||||
|
text="",
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch", "turn_on", {"entity_id": "switch.relay1"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("switch.relay1")
|
||||||
|
assert state.state == "on"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user