mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Allow manual scan and add delay in switch verify. (#50974)
This commit is contained in:
parent
2583e4bdc9
commit
be13a73db8
@ -140,6 +140,8 @@ def control_scan_interval(config: dict) -> dict:
|
|||||||
for entry in hub[conf_key]:
|
for entry in hub[conf_key]:
|
||||||
scan_interval = entry.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
scan_interval = entry.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||||
if scan_interval < MINIMUM_SCAN_INTERVAL:
|
if scan_interval < MINIMUM_SCAN_INTERVAL:
|
||||||
|
if scan_interval == 0:
|
||||||
|
continue
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"%s %s scan_interval(%d) is adjusted to minimum(%d)",
|
"%s %s scan_interval(%d) is adjusted to minimum(%d)",
|
||||||
component,
|
component,
|
||||||
@ -236,6 +238,7 @@ SWITCH_SCHEMA = BASE_COMPONENT_SCHEMA.extend(
|
|||||||
),
|
),
|
||||||
vol.Optional(CONF_STATE_OFF): cv.positive_int,
|
vol.Optional(CONF_STATE_OFF): cv.positive_int,
|
||||||
vol.Optional(CONF_STATE_ON): cv.positive_int,
|
vol.Optional(CONF_STATE_ON): cv.positive_int,
|
||||||
|
vol.Optional(CONF_DELAY, default=0): cv.positive_int,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ class BasePlatform(Entity):
|
|||||||
self._input_type = entry[CONF_INPUT_TYPE]
|
self._input_type = entry[CONF_INPUT_TYPE]
|
||||||
self._value = None
|
self._value = None
|
||||||
self._available = True
|
self._available = True
|
||||||
self._scan_interval = timedelta(seconds=entry[CONF_SCAN_INTERVAL])
|
self._scan_interval = int(entry[CONF_SCAN_INTERVAL])
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def async_update(self, now=None):
|
async def async_update(self, now=None):
|
||||||
@ -44,7 +44,10 @@ class BasePlatform(Entity):
|
|||||||
|
|
||||||
async def async_base_added_to_hass(self):
|
async def async_base_added_to_hass(self):
|
||||||
"""Handle entity which will be added."""
|
"""Handle entity which will be added."""
|
||||||
async_track_time_interval(self.hass, self.async_update, self._scan_interval)
|
if self._scan_interval > 0:
|
||||||
|
async_track_time_interval(
|
||||||
|
self.hass, self.async_update, timedelta(seconds=self._scan_interval)
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -8,11 +8,13 @@ from homeassistant.const import (
|
|||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
CONF_COMMAND_OFF,
|
CONF_COMMAND_OFF,
|
||||||
CONF_COMMAND_ON,
|
CONF_COMMAND_ON,
|
||||||
|
CONF_DELAY,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.event import async_call_later
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
@ -64,6 +66,7 @@ class ModbusSwitch(BasePlatform, SwitchEntity, RestoreEntity):
|
|||||||
if config[CONF_VERIFY] is None:
|
if config[CONF_VERIFY] is None:
|
||||||
config[CONF_VERIFY] = {}
|
config[CONF_VERIFY] = {}
|
||||||
self._verify_active = True
|
self._verify_active = True
|
||||||
|
self._verify_delay = config[CONF_VERIFY].get(CONF_DELAY, 0)
|
||||||
self._verify_address = config[CONF_VERIFY].get(
|
self._verify_address = config[CONF_VERIFY].get(
|
||||||
CONF_ADDRESS, config[CONF_ADDRESS]
|
CONF_ADDRESS, config[CONF_ADDRESS]
|
||||||
)
|
)
|
||||||
@ -87,38 +90,34 @@ class ModbusSwitch(BasePlatform, SwitchEntity, RestoreEntity):
|
|||||||
"""Return true if switch is on."""
|
"""Return true if switch is on."""
|
||||||
return self._is_on
|
return self._is_on
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def _async_turn(self, command):
|
||||||
"""Set switch on."""
|
"""Evaluate switch result."""
|
||||||
|
|
||||||
result = await self._hub.async_pymodbus_call(
|
result = await self._hub.async_pymodbus_call(
|
||||||
self._slave, self._address, self._command_on, self._write_type
|
self._slave, self._address, command, self._write_type
|
||||||
)
|
)
|
||||||
if result is None:
|
if result is None:
|
||||||
self._available = False
|
self._available = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
else:
|
return
|
||||||
|
|
||||||
self._available = True
|
self._available = True
|
||||||
if self._verify_active:
|
if not self._verify_active:
|
||||||
await self.async_update()
|
self._is_on = command == self._command_on
|
||||||
else:
|
|
||||||
self._is_on = True
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._verify_delay:
|
||||||
|
async_call_later(self.hass, self._verify_delay, self.async_update)
|
||||||
|
else:
|
||||||
|
await self.async_update()
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs):
|
||||||
|
"""Set switch on."""
|
||||||
|
await self._async_turn(self._command_on)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs):
|
||||||
"""Set switch off."""
|
"""Set switch off."""
|
||||||
result = await self._hub.async_pymodbus_call(
|
await self._async_turn(self._command_off)
|
||||||
self._slave, self._address, self._command_off, self._write_type
|
|
||||||
)
|
|
||||||
if result is None:
|
|
||||||
self._available = False
|
|
||||||
self.async_write_ha_state()
|
|
||||||
else:
|
|
||||||
self._available = True
|
|
||||||
if self._verify_active:
|
|
||||||
await self.async_update()
|
|
||||||
else:
|
|
||||||
self._is_on = False
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
async def async_update(self, now=None):
|
async def async_update(self, now=None):
|
||||||
"""Update the entity state."""
|
"""Update the entity state."""
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
"""The tests for the Modbus switch component."""
|
"""The tests for the Modbus switch component."""
|
||||||
|
from datetime import timedelta
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
from pymodbus.exceptions import ModbusException
|
from pymodbus.exceptions import ModbusException
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -19,10 +22,12 @@ from homeassistant.const import (
|
|||||||
CONF_ADDRESS,
|
CONF_ADDRESS,
|
||||||
CONF_COMMAND_OFF,
|
CONF_COMMAND_OFF,
|
||||||
CONF_COMMAND_ON,
|
CONF_COMMAND_ON,
|
||||||
|
CONF_DELAY,
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
|
CONF_SCAN_INTERVAL,
|
||||||
CONF_SLAVE,
|
CONF_SLAVE,
|
||||||
CONF_SWITCHES,
|
CONF_SWITCHES,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
@ -32,10 +37,11 @@ from homeassistant.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.core import State
|
from homeassistant.core import State
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from .conftest import ReadResult, base_config_test, base_test, prepare_service_update
|
from .conftest import ReadResult, base_config_test, base_test, prepare_service_update
|
||||||
|
|
||||||
from tests.common import mock_restore_cache
|
from tests.common import async_fire_time_changed, mock_restore_cache
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@ -72,6 +78,7 @@ from tests.common import mock_restore_cache
|
|||||||
CONF_ADDRESS: 1235,
|
CONF_ADDRESS: 1235,
|
||||||
CONF_STATE_OFF: 0,
|
CONF_STATE_OFF: 0,
|
||||||
CONF_STATE_ON: 1,
|
CONF_STATE_ON: 1,
|
||||||
|
CONF_DELAY: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -93,6 +100,7 @@ from tests.common import mock_restore_cache
|
|||||||
CONF_COMMAND_OFF: 0x00,
|
CONF_COMMAND_OFF: 0x00,
|
||||||
CONF_COMMAND_ON: 0x01,
|
CONF_COMMAND_ON: 0x01,
|
||||||
CONF_DEVICE_CLASS: "switch",
|
CONF_DEVICE_CLASS: "switch",
|
||||||
|
CONF_SCAN_INTERVAL: 0,
|
||||||
CONF_VERIFY: None,
|
CONF_VERIFY: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -292,3 +300,46 @@ async def test_service_switch_update(hass, mock_pymodbus):
|
|||||||
"homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True
|
"homeassistant", "update_entity", {"entity_id": entity_id}, blocking=True
|
||||||
)
|
)
|
||||||
assert hass.states.get(entity_id).state == STATE_OFF
|
assert hass.states.get(entity_id).state == STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
|
async def test_delay_switch(hass, mock_pymodbus):
|
||||||
|
"""Run test for switch verify delay."""
|
||||||
|
|
||||||
|
switch_name = "test_switch"
|
||||||
|
entity_id = f"{SWITCH_DOMAIN}.{switch_name}"
|
||||||
|
|
||||||
|
config = {
|
||||||
|
MODBUS_DOMAIN: [
|
||||||
|
{
|
||||||
|
CONF_TYPE: "tcp",
|
||||||
|
CONF_HOST: "modbusTestHost",
|
||||||
|
CONF_PORT: 5501,
|
||||||
|
CONF_SWITCHES: [
|
||||||
|
{
|
||||||
|
CONF_NAME: switch_name,
|
||||||
|
CONF_ADDRESS: 51,
|
||||||
|
CONF_SCAN_INTERVAL: 0,
|
||||||
|
CONF_VERIFY: {
|
||||||
|
CONF_DELAY: 1,
|
||||||
|
CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
mock_pymodbus.read_holding_registers.return_value = ReadResult([0x01])
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||||
|
assert await async_setup_component(hass, MODBUS_DOMAIN, config) is True
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch", "turn_on", service_data={"entity_id": entity_id}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(entity_id).state == STATE_OFF
|
||||||
|
now = now + timedelta(seconds=2)
|
||||||
|
with mock.patch("homeassistant.helpers.event.dt_util.utcnow", return_value=now):
|
||||||
|
async_fire_time_changed(hass, now)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert hass.states.get(entity_id).state == STATE_ON
|
Loading…
x
Reference in New Issue
Block a user