mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 09:47:52 +00:00
New methods for input_select component (#42968)
This adds a `cycle` attribute to select_previous/next, and select_first and select_last services. This is quite useful for streamlining using input_select via automations, such as when they represent a list of states to step through; if the first option is the dimmest and the last the brightest, one may not want to accidentally cycle from the first to the last, for example. Similarly, being able to directly select the first or last removes adjustment in related automations.
This commit is contained in:
parent
122a4e03f8
commit
34194da1b6
@ -29,10 +29,13 @@ CONF_OPTIONS = "options"
|
||||
|
||||
ATTR_OPTION = "option"
|
||||
ATTR_OPTIONS = "options"
|
||||
ATTR_CYCLE = "cycle"
|
||||
|
||||
SERVICE_SELECT_OPTION = "select_option"
|
||||
SERVICE_SELECT_NEXT = "select_next"
|
||||
SERVICE_SELECT_PREVIOUS = "select_previous"
|
||||
SERVICE_SELECT_FIRST = "select_first"
|
||||
SERVICE_SELECT_LAST = "select_last"
|
||||
SERVICE_SET_OPTIONS = "set_options"
|
||||
STORAGE_KEY = DOMAIN
|
||||
STORAGE_VERSION = 1
|
||||
@ -141,14 +144,26 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_NEXT,
|
||||
{},
|
||||
callback(lambda entity, call: entity.async_offset_index(1)),
|
||||
{vol.Optional(ATTR_CYCLE, default=True): bool},
|
||||
"async_next",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_PREVIOUS,
|
||||
{vol.Optional(ATTR_CYCLE, default=True): bool},
|
||||
"async_previous",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_FIRST,
|
||||
{},
|
||||
callback(lambda entity, call: entity.async_offset_index(-1)),
|
||||
callback(lambda entity, call: entity.async_select_index(0)),
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_LAST,
|
||||
{},
|
||||
callback(lambda entity, call: entity.async_select_index(-1)),
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
@ -263,13 +278,37 @@ class InputSelect(RestoreEntity):
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def async_offset_index(self, offset):
|
||||
"""Offset current index."""
|
||||
current_index = self._options.index(self._current_option)
|
||||
new_index = (current_index + offset) % len(self._options)
|
||||
def async_select_index(self, idx):
|
||||
"""Select new option by index."""
|
||||
new_index = idx % len(self._options)
|
||||
self._current_option = self._options[new_index]
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def async_offset_index(self, offset, cycle):
|
||||
"""Offset current index."""
|
||||
current_index = self._options.index(self._current_option)
|
||||
new_index = current_index + offset
|
||||
if cycle:
|
||||
new_index = new_index % len(self._options)
|
||||
else:
|
||||
if new_index < 0:
|
||||
new_index = 0
|
||||
elif new_index >= len(self._options):
|
||||
new_index = len(self._options) - 1
|
||||
self._current_option = self._options[new_index]
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def async_next(self, cycle):
|
||||
"""Select next option."""
|
||||
self.async_offset_index(1, cycle)
|
||||
|
||||
@callback
|
||||
def async_previous(self, cycle):
|
||||
"""Select previous option."""
|
||||
self.async_offset_index(-1, cycle)
|
||||
|
||||
@callback
|
||||
def async_set_options(self, options):
|
||||
"""Set options."""
|
||||
|
@ -4,6 +4,9 @@ select_next:
|
||||
entity_id:
|
||||
description: Entity id of the input select to select the next value for.
|
||||
example: input_select.my_select
|
||||
cycle:
|
||||
description: If the option should cycle from the last to the first (defaults to true).
|
||||
example: true
|
||||
select_option:
|
||||
description: Select an option of an input select entity.
|
||||
fields:
|
||||
@ -19,6 +22,21 @@ select_previous:
|
||||
entity_id:
|
||||
description: Entity id of the input select to select the previous value for.
|
||||
example: input_select.my_select
|
||||
cycle:
|
||||
description: If the option should cycle from the first to the last (defaults to true).
|
||||
example: true
|
||||
select_first:
|
||||
description: Select the first option of an input select entity.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Entity id of the input select to select the first value for.
|
||||
example: input_select.my_select
|
||||
select_last:
|
||||
description: Select the last option of an input select entity.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Entity id of the input select to select the last value for.
|
||||
example: input_select.my_select
|
||||
set_options:
|
||||
description: Set the options of an input select entity.
|
||||
fields:
|
||||
|
@ -9,6 +9,8 @@ from homeassistant.components.input_select import (
|
||||
ATTR_OPTIONS,
|
||||
CONF_INITIAL,
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_FIRST,
|
||||
SERVICE_SELECT_LAST,
|
||||
SERVICE_SELECT_NEXT,
|
||||
SERVICE_SELECT_OPTION,
|
||||
SERVICE_SELECT_PREVIOUS,
|
||||
@ -104,6 +106,32 @@ def select_previous(hass, entity_id):
|
||||
)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def select_first(hass, entity_id):
|
||||
"""Set first value of input_select.
|
||||
|
||||
This is a legacy helper method. Do not use it for new tests.
|
||||
"""
|
||||
hass.async_create_task(
|
||||
hass.services.async_call(
|
||||
DOMAIN, SERVICE_SELECT_FIRST, {ATTR_ENTITY_ID: entity_id}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def select_last(hass, entity_id):
|
||||
"""Set last value of input_select.
|
||||
|
||||
This is a legacy helper method. Do not use it for new tests.
|
||||
"""
|
||||
hass.async_create_task(
|
||||
hass.services.async_call(
|
||||
DOMAIN, SERVICE_SELECT_LAST, {ATTR_ENTITY_ID: entity_id}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def test_config(hass):
|
||||
"""Test config."""
|
||||
invalid_configs = [
|
||||
@ -207,6 +235,38 @@ async def test_select_previous(hass):
|
||||
assert "last option" == state.state
|
||||
|
||||
|
||||
async def test_select_first_last(hass):
|
||||
"""Test select_first and _last methods."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
DOMAIN,
|
||||
{
|
||||
DOMAIN: {
|
||||
"test_1": {
|
||||
"options": ["first option", "middle option", "last option"],
|
||||
"initial": "middle option",
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
entity_id = "input_select.test_1"
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert "middle option" == state.state
|
||||
|
||||
select_first(hass, entity_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert "first option" == state.state
|
||||
|
||||
select_last(hass, entity_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert "last option" == state.state
|
||||
|
||||
|
||||
async def test_config_options(hass):
|
||||
"""Test configuration options."""
|
||||
count_start = len(hass.states.async_entity_ids())
|
||||
|
Loading…
x
Reference in New Issue
Block a user