mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Fix vera config ids not being converted to integers (#35070)
This commit is contained in:
parent
88b7aba1c8
commit
ab08c1bef8
@ -25,7 +25,7 @@ from homeassistant.util import convert, slugify
|
|||||||
from homeassistant.util.dt import utc_from_timestamp
|
from homeassistant.util.dt import utc_from_timestamp
|
||||||
|
|
||||||
from .common import ControllerData, get_configured_platforms
|
from .common import ControllerData, get_configured_platforms
|
||||||
from .config_flow import new_options
|
from .config_flow import fix_device_id_list, new_options
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_CURRENT_ENERGY_KWH,
|
ATTR_CURRENT_ENERGY_KWH,
|
||||||
ATTR_CURRENT_POWER_W,
|
ATTR_CURRENT_POWER_W,
|
||||||
@ -81,9 +81,18 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
saved_light_ids = config_entry.options.get(CONF_LIGHTS, [])
|
||||||
|
saved_exclude_ids = config_entry.options.get(CONF_EXCLUDE, [])
|
||||||
|
|
||||||
base_url = config_entry.data[CONF_CONTROLLER]
|
base_url = config_entry.data[CONF_CONTROLLER]
|
||||||
light_ids = config_entry.options.get(CONF_LIGHTS, [])
|
light_ids = fix_device_id_list(saved_light_ids)
|
||||||
exclude_ids = config_entry.options.get(CONF_EXCLUDE, [])
|
exclude_ids = fix_device_id_list(saved_exclude_ids)
|
||||||
|
|
||||||
|
# If the ids were corrected. Update the config entry.
|
||||||
|
if light_ids != saved_light_ids or exclude_ids != saved_exclude_ids:
|
||||||
|
hass.config_entries.async_update_entry(
|
||||||
|
entry=config_entry, options=new_options(light_ids, exclude_ids)
|
||||||
|
)
|
||||||
|
|
||||||
# Initialize the Vera controller.
|
# Initialize the Vera controller.
|
||||||
controller = veraApi.VeraController(base_url)
|
controller = veraApi.VeraController(base_url)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Config flow for Vera."""
|
"""Config flow for Vera."""
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from typing import List, cast
|
from typing import Any, List
|
||||||
|
|
||||||
import pyvera as pv
|
import pyvera as pv
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
@ -17,20 +17,22 @@ LIST_REGEX = re.compile("[^0-9]+")
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def str_to_int_list(data: str) -> List[str]:
|
def fix_device_id_list(data: List[Any]) -> List[int]:
|
||||||
|
"""Fix the id list by converting it to a supported int list."""
|
||||||
|
return str_to_int_list(list_to_str(data))
|
||||||
|
|
||||||
|
|
||||||
|
def str_to_int_list(data: str) -> List[int]:
|
||||||
"""Convert a string to an int list."""
|
"""Convert a string to an int list."""
|
||||||
if isinstance(str, list):
|
return [int(s) for s in LIST_REGEX.split(data) if len(s) > 0]
|
||||||
return cast(List[str], data)
|
|
||||||
|
|
||||||
return [s for s in LIST_REGEX.split(data) if len(s) > 0]
|
|
||||||
|
|
||||||
|
|
||||||
def int_list_to_str(data: List[str]) -> str:
|
def list_to_str(data: List[Any]) -> str:
|
||||||
"""Convert an int list to a string."""
|
"""Convert an int list to a string."""
|
||||||
return " ".join([str(i) for i in data])
|
return " ".join([str(i) for i in data])
|
||||||
|
|
||||||
|
|
||||||
def new_options(lights: List[str], exclude: List[str]) -> dict:
|
def new_options(lights: List[int], exclude: List[int]) -> dict:
|
||||||
"""Create a standard options object."""
|
"""Create a standard options object."""
|
||||||
return {CONF_LIGHTS: lights, CONF_EXCLUDE: exclude}
|
return {CONF_LIGHTS: lights, CONF_EXCLUDE: exclude}
|
||||||
|
|
||||||
@ -40,10 +42,10 @@ def options_schema(options: dict = None) -> dict:
|
|||||||
options = options or {}
|
options = options or {}
|
||||||
return {
|
return {
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_LIGHTS, default=int_list_to_str(options.get(CONF_LIGHTS, [])),
|
CONF_LIGHTS, default=list_to_str(options.get(CONF_LIGHTS, [])),
|
||||||
): str,
|
): str,
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_EXCLUDE, default=int_list_to_str(options.get(CONF_EXCLUDE, [])),
|
CONF_EXCLUDE, default=list_to_str(options.get(CONF_EXCLUDE, [])),
|
||||||
): str,
|
): str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ async def test_async_step_user_success(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_CONTROLLER: "http://127.0.0.1:123",
|
CONF_CONTROLLER: "http://127.0.0.1:123",
|
||||||
CONF_SOURCE: config_entries.SOURCE_USER,
|
CONF_SOURCE: config_entries.SOURCE_USER,
|
||||||
CONF_LIGHTS: ["12", "13"],
|
CONF_LIGHTS: [12, 13],
|
||||||
CONF_EXCLUDE: ["14", "15"],
|
CONF_EXCLUDE: [14, 15],
|
||||||
}
|
}
|
||||||
assert result["result"].unique_id == controller.serial_number
|
assert result["result"].unique_id == controller.serial_number
|
||||||
|
|
||||||
@ -154,6 +154,6 @@ async def test_options(hass):
|
|||||||
)
|
)
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_LIGHTS: ["1", "2", "3", "4", "5", "6", "7"],
|
CONF_LIGHTS: [1, 2, 3, 4, 5, 6, 7],
|
||||||
CONF_EXCLUDE: ["8", "9", "10", "11", "12", "13", "14"],
|
CONF_EXCLUDE: [8, 9, 10, 11, 12, 13, 14],
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
"""Vera tests."""
|
"""Vera tests."""
|
||||||
|
import pytest
|
||||||
import pyvera as pv
|
import pyvera as pv
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
from homeassistant.components.vera import CONF_CONTROLLER, DOMAIN
|
from homeassistant.components.vera import (
|
||||||
|
CONF_CONTROLLER,
|
||||||
|
CONF_EXCLUDE,
|
||||||
|
CONF_LIGHTS,
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ENTRY_STATE_NOT_LOADED
|
from homeassistant.config_entries import ENTRY_STATE_NOT_LOADED
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
@ -110,3 +116,71 @@ async def test_async_setup_entry_error(
|
|||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
assert not await hass.config_entries.async_setup(entry.entry_id)
|
assert not await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
["options"],
|
||||||
|
[
|
||||||
|
[{CONF_LIGHTS: [4, 10, 12, "AAA"], CONF_EXCLUDE: [1, "BBB"]}],
|
||||||
|
[{CONF_LIGHTS: ["4", "10", "12", "AAA"], CONF_EXCLUDE: ["1", "BBB"]}],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_exclude_and_light_ids(
|
||||||
|
hass: HomeAssistant, vera_component_factory: ComponentFactory, options
|
||||||
|
) -> None:
|
||||||
|
"""Test device exclusion, marking switches as lights and fixing the data type."""
|
||||||
|
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor
|
||||||
|
vera_device1.device_id = 1
|
||||||
|
vera_device1.vera_device_id = 1
|
||||||
|
vera_device1.name = "dev1"
|
||||||
|
vera_device1.is_tripped = False
|
||||||
|
entity_id1 = "binary_sensor.dev1_1"
|
||||||
|
|
||||||
|
vera_device2 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor
|
||||||
|
vera_device2.device_id = 2
|
||||||
|
vera_device2.vera_device_id = 2
|
||||||
|
vera_device2.name = "dev2"
|
||||||
|
vera_device2.is_tripped = False
|
||||||
|
entity_id2 = "binary_sensor.dev2_2"
|
||||||
|
|
||||||
|
vera_device3 = MagicMock(spec=pv.VeraSwitch) # type: pv.VeraSwitch
|
||||||
|
vera_device3.device_id = 3
|
||||||
|
vera_device3.name = "dev3"
|
||||||
|
vera_device3.category = pv.CATEGORY_SWITCH
|
||||||
|
vera_device3.is_switched_on = MagicMock(return_value=False)
|
||||||
|
entity_id3 = "switch.dev3_3"
|
||||||
|
|
||||||
|
vera_device4 = MagicMock(spec=pv.VeraSwitch) # type: pv.VeraSwitch
|
||||||
|
vera_device4.device_id = 4
|
||||||
|
vera_device4.name = "dev4"
|
||||||
|
vera_device4.category = pv.CATEGORY_SWITCH
|
||||||
|
vera_device4.is_switched_on = MagicMock(return_value=False)
|
||||||
|
entity_id4 = "light.dev4_4"
|
||||||
|
|
||||||
|
component_data = await vera_component_factory.configure_component(
|
||||||
|
hass=hass,
|
||||||
|
controller_config=new_simple_controller_config(
|
||||||
|
devices=(vera_device1, vera_device2, vera_device3, vera_device4),
|
||||||
|
config={**{CONF_CONTROLLER: "http://127.0.0.1:123"}, **options},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Assert the entries were setup correctly.
|
||||||
|
config_entry = next(iter(hass.config_entries.async_entries(DOMAIN)))
|
||||||
|
assert config_entry.options == {
|
||||||
|
CONF_LIGHTS: [4, 10, 12],
|
||||||
|
CONF_EXCLUDE: [1],
|
||||||
|
}
|
||||||
|
|
||||||
|
update_callback = component_data.controller_data.update_callback
|
||||||
|
|
||||||
|
update_callback(vera_device1)
|
||||||
|
update_callback(vera_device2)
|
||||||
|
update_callback(vera_device3)
|
||||||
|
update_callback(vera_device4)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.states.get(entity_id1) is None
|
||||||
|
assert hass.states.get(entity_id2) is not None
|
||||||
|
assert hass.states.get(entity_id3) is not None
|
||||||
|
assert hass.states.get(entity_id4) is not None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user