mirror of
https://github.com/home-assistant/core
synced 2024-09-03 08:14:07 +02:00
Remove mysensors yaml (#72761)
This commit is contained in:
parent
cf27b82d2f
commit
8140ed724c
@ -7,12 +7,9 @@ from functools import partial
|
||||
import logging
|
||||
|
||||
from mysensors import BaseAsyncGateway
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.mqtt import valid_publish_topic, valid_subscribe_topic
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_OPTIMISTIC, Platform
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.device_registry import DeviceEntry
|
||||
@ -22,17 +19,6 @@ from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import (
|
||||
ATTR_DEVICES,
|
||||
CONF_BAUD_RATE,
|
||||
CONF_DEVICE,
|
||||
CONF_GATEWAYS,
|
||||
CONF_NODES,
|
||||
CONF_PERSISTENCE,
|
||||
CONF_PERSISTENCE_FILE,
|
||||
CONF_RETAIN,
|
||||
CONF_TCP_PORT,
|
||||
CONF_TOPIC_IN_PREFIX,
|
||||
CONF_TOPIC_OUT_PREFIX,
|
||||
CONF_VERSION,
|
||||
DOMAIN,
|
||||
MYSENSORS_DISCOVERY,
|
||||
MYSENSORS_GATEWAYS,
|
||||
@ -48,147 +34,17 @@ from .helpers import on_unload
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_DEBUG = "debug"
|
||||
CONF_NODE_NAME = "name"
|
||||
|
||||
DATA_HASS_CONFIG = "hass_config"
|
||||
|
||||
DEFAULT_BAUD_RATE = 115200
|
||||
DEFAULT_TCP_PORT = 5003
|
||||
DEFAULT_VERSION = "1.4"
|
||||
|
||||
|
||||
def set_default_persistence_file(value: dict) -> dict:
|
||||
"""Set default persistence file."""
|
||||
for idx, gateway in enumerate(value):
|
||||
if gateway.get(CONF_PERSISTENCE_FILE) is not None:
|
||||
continue
|
||||
new_name = f"mysensors{idx + 1}.pickle"
|
||||
gateway[CONF_PERSISTENCE_FILE] = new_name
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def has_all_unique_files(value: list[dict]) -> list[dict]:
|
||||
"""Validate that all persistence files are unique and set if any is set."""
|
||||
persistence_files = [gateway[CONF_PERSISTENCE_FILE] for gateway in value]
|
||||
schema = vol.Schema(vol.Unique())
|
||||
schema(persistence_files)
|
||||
return value
|
||||
|
||||
|
||||
def is_persistence_file(value: str) -> str:
|
||||
"""Validate that persistence file path ends in either .pickle or .json."""
|
||||
if value.endswith((".json", ".pickle")):
|
||||
return value
|
||||
raise vol.Invalid(f"{value} does not end in either `.json` or `.pickle`")
|
||||
|
||||
|
||||
def deprecated(key: str) -> Callable[[dict], dict]:
|
||||
"""Mark key as deprecated in configuration."""
|
||||
|
||||
def validator(config: dict) -> dict:
|
||||
"""Check if key is in config, log warning and remove key."""
|
||||
if key not in config:
|
||||
return config
|
||||
_LOGGER.warning(
|
||||
"%s option for %s is deprecated. Please remove %s from your "
|
||||
"configuration file",
|
||||
key,
|
||||
DOMAIN,
|
||||
key,
|
||||
)
|
||||
config.pop(key)
|
||||
return config
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
NODE_SCHEMA = vol.Schema({cv.positive_int: {vol.Required(CONF_NODE_NAME): cv.string}})
|
||||
|
||||
GATEWAY_SCHEMA = vol.Schema(
|
||||
vol.All(
|
||||
deprecated(CONF_NODES),
|
||||
{
|
||||
vol.Required(CONF_DEVICE): cv.string,
|
||||
vol.Optional(CONF_PERSISTENCE_FILE): vol.All(
|
||||
cv.string, is_persistence_file
|
||||
),
|
||||
vol.Optional(CONF_BAUD_RATE, default=DEFAULT_BAUD_RATE): cv.positive_int,
|
||||
vol.Optional(CONF_TCP_PORT, default=DEFAULT_TCP_PORT): cv.port,
|
||||
vol.Optional(CONF_TOPIC_IN_PREFIX): valid_subscribe_topic,
|
||||
vol.Optional(CONF_TOPIC_OUT_PREFIX): valid_publish_topic,
|
||||
vol.Optional(CONF_NODES, default={}): NODE_SCHEMA,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
vol.All(
|
||||
cv.deprecated(DOMAIN),
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
vol.All(
|
||||
deprecated(CONF_DEBUG),
|
||||
deprecated(CONF_OPTIMISTIC),
|
||||
deprecated(CONF_PERSISTENCE),
|
||||
{
|
||||
vol.Required(CONF_GATEWAYS): vol.All(
|
||||
cv.ensure_list,
|
||||
set_default_persistence_file,
|
||||
has_all_unique_files,
|
||||
[GATEWAY_SCHEMA],
|
||||
),
|
||||
vol.Optional(CONF_RETAIN, default=True): cv.boolean,
|
||||
vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): cv.string,
|
||||
vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
vol.Optional(CONF_PERSISTENCE, default=True): cv.boolean,
|
||||
},
|
||||
)
|
||||
)
|
||||
},
|
||||
),
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the MySensors component."""
|
||||
# This is needed to set up the notify platform via discovery.
|
||||
hass.data[DOMAIN] = {DATA_HASS_CONFIG: config}
|
||||
|
||||
if DOMAIN not in config or bool(hass.config_entries.async_entries(DOMAIN)):
|
||||
return True
|
||||
|
||||
config = config[DOMAIN]
|
||||
user_inputs = [
|
||||
{
|
||||
CONF_DEVICE: gw[CONF_DEVICE],
|
||||
CONF_BAUD_RATE: gw[CONF_BAUD_RATE],
|
||||
CONF_TCP_PORT: gw[CONF_TCP_PORT],
|
||||
CONF_TOPIC_OUT_PREFIX: gw.get(CONF_TOPIC_OUT_PREFIX, ""),
|
||||
CONF_TOPIC_IN_PREFIX: gw.get(CONF_TOPIC_IN_PREFIX, ""),
|
||||
CONF_RETAIN: config[CONF_RETAIN],
|
||||
CONF_VERSION: config[CONF_VERSION],
|
||||
CONF_PERSISTENCE_FILE: gw[CONF_PERSISTENCE_FILE]
|
||||
# nodes config ignored at this time. renaming nodes can now be done from the frontend.
|
||||
}
|
||||
for gw in config[CONF_GATEWAYS]
|
||||
]
|
||||
user_inputs = [
|
||||
{k: v for k, v in userinput.items() if v is not None}
|
||||
for userinput in user_inputs
|
||||
]
|
||||
|
||||
# there is an actual configuration in configuration.yaml, so we have to process it
|
||||
for user_input in user_inputs:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
data=user_input,
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -22,7 +22,6 @@ from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from . import DEFAULT_BAUD_RATE, DEFAULT_TCP_PORT, DEFAULT_VERSION, is_persistence_file
|
||||
from .const import (
|
||||
CONF_BAUD_RATE,
|
||||
CONF_DEVICE,
|
||||
@ -42,6 +41,17 @@ from .const import (
|
||||
)
|
||||
from .gateway import MQTT_COMPONENT, is_serial_port, is_socket_address, try_connect
|
||||
|
||||
DEFAULT_BAUD_RATE = 115200
|
||||
DEFAULT_TCP_PORT = 5003
|
||||
DEFAULT_VERSION = "1.4"
|
||||
|
||||
|
||||
def is_persistence_file(value: str) -> str:
|
||||
"""Validate that persistence file path ends in either .pickle or .json."""
|
||||
if value.endswith((".json", ".pickle")):
|
||||
return value
|
||||
raise vol.Invalid(f"{value} does not end in either `.json` or `.pickle`")
|
||||
|
||||
|
||||
def _get_schema_common(user_input: dict[str, str]) -> dict:
|
||||
"""Create a schema with options common to all gateway types."""
|
||||
@ -105,31 +115,6 @@ class MySensorsConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Set up config flow."""
|
||||
self._gw_type: str | None = None
|
||||
|
||||
async def async_step_import(self, user_input: dict[str, Any]) -> FlowResult:
|
||||
"""Import a config entry.
|
||||
|
||||
This method is called by async_setup and it has already
|
||||
prepared the dict to be compatible with what a user would have
|
||||
entered from the frontend.
|
||||
Therefore we process it as though it came from the frontend.
|
||||
"""
|
||||
if user_input[CONF_DEVICE] == MQTT_COMPONENT:
|
||||
user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_MQTT
|
||||
else:
|
||||
try:
|
||||
await self.hass.async_add_executor_job(
|
||||
is_serial_port, user_input[CONF_DEVICE]
|
||||
)
|
||||
except vol.Invalid:
|
||||
user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_TCP
|
||||
else:
|
||||
user_input[CONF_GATEWAY_TYPE] = CONF_GATEWAY_TYPE_SERIAL
|
||||
|
||||
result: FlowResult = await self.async_step_user(user_input=user_input)
|
||||
if errors := result.get("errors"):
|
||||
return self.async_abort(reason=next(iter(errors.values())))
|
||||
return result
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> FlowResult:
|
||||
@ -335,10 +320,11 @@ class MySensorsConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
errors[CONF_PERSISTENCE_FILE] = "duplicate_persistence_file"
|
||||
break
|
||||
|
||||
for other_entry in self._async_current_entries():
|
||||
if _is_same_device(gw_type, user_input, other_entry):
|
||||
errors["base"] = "already_configured"
|
||||
break
|
||||
if not errors:
|
||||
for other_entry in self._async_current_entries():
|
||||
if _is_same_device(gw_type, user_input, other_entry):
|
||||
errors["base"] = "already_configured"
|
||||
break
|
||||
|
||||
# if no errors so far, try to connect
|
||||
if not errors and not await try_connect(self.hass, gw_type, user_input):
|
||||
|
@ -11,9 +11,6 @@ ATTR_GATEWAY_ID: Final = "gateway_id"
|
||||
|
||||
CONF_BAUD_RATE: Final = "baud_rate"
|
||||
CONF_DEVICE: Final = "device"
|
||||
CONF_GATEWAYS: Final = "gateways"
|
||||
CONF_NODES: Final = "nodes"
|
||||
CONF_PERSISTENCE: Final = "persistence"
|
||||
CONF_PERSISTENCE_FILE: Final = "persistence_file"
|
||||
CONF_RETAIN: Final = "retain"
|
||||
CONF_TCP_PORT: Final = "tcp_port"
|
||||
|
@ -13,13 +13,13 @@ import pytest
|
||||
|
||||
from homeassistant.components.device_tracker.legacy import Device
|
||||
from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN
|
||||
from homeassistant.components.mysensors import CONF_VERSION, DEFAULT_BAUD_RATE
|
||||
from homeassistant.components.mysensors.config_flow import DEFAULT_BAUD_RATE
|
||||
from homeassistant.components.mysensors.const import (
|
||||
CONF_BAUD_RATE,
|
||||
CONF_DEVICE,
|
||||
CONF_GATEWAY_TYPE,
|
||||
CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_GATEWAYS,
|
||||
CONF_VERSION,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -141,8 +141,7 @@ async def integration_fixture(
|
||||
hass: HomeAssistant, transport: MagicMock, config_entry: MockConfigEntry
|
||||
) -> AsyncGenerator[MockConfigEntry, None]:
|
||||
"""Set up the mysensors integration with a config entry."""
|
||||
device = config_entry.data[CONF_DEVICE]
|
||||
config: dict[str, Any] = {DOMAIN: {CONF_GATEWAYS: [{CONF_DEVICE: device}]}}
|
||||
config: dict[str, Any] = {}
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.mysensors.device.UPDATE_DELAY", new=0):
|
||||
|
@ -14,7 +14,6 @@ from homeassistant.components.mysensors.const import (
|
||||
CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_PERSISTENCE,
|
||||
CONF_PERSISTENCE_FILE,
|
||||
CONF_RETAIN,
|
||||
CONF_TCP_PORT,
|
||||
@ -399,333 +398,268 @@ async def test_config_invalid(
|
||||
assert len(mock_setup_entry.mock_calls) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"user_input",
|
||||
[
|
||||
{
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: True,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_TOPIC_IN_PREFIX: "intopic",
|
||||
CONF_TOPIC_OUT_PREFIX: "outtopic",
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_PERSISTENCE_FILE: "blub.pickle",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
],
|
||||
)
|
||||
async def test_import(hass: HomeAssistant, mqtt: None, user_input: dict) -> None:
|
||||
"""Test importing a gateway."""
|
||||
|
||||
with patch("sys.platform", "win32"), patch(
|
||||
"homeassistant.components.mysensors.config_flow.try_connect", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.mysensors.async_setup_entry",
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, data=user_input, context={"source": config_entries.SOURCE_IMPORT}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"first_input, second_input, expected_result",
|
||||
[
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "same2",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "same2",
|
||||
},
|
||||
(CONF_TOPIC_IN_PREFIX, "duplicate_topic"),
|
||||
FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "different1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different2",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "different3",
|
||||
CONF_TOPIC_OUT_PREFIX: "different4",
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different2",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different4",
|
||||
},
|
||||
(CONF_TOPIC_IN_PREFIX, "duplicate_topic"),
|
||||
FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different2",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "different1",
|
||||
CONF_TOPIC_OUT_PREFIX: "same1",
|
||||
},
|
||||
(CONF_TOPIC_OUT_PREFIX, "duplicate_topic"),
|
||||
FlowResult(type="form", errors={CONF_TOPIC_OUT_PREFIX: "duplicate_topic"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different2",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TOPIC_IN_PREFIX: "same1",
|
||||
CONF_TOPIC_OUT_PREFIX: "different1",
|
||||
},
|
||||
(CONF_TOPIC_IN_PREFIX, "duplicate_topic"),
|
||||
FlowResult(type="form", errors={CONF_TOPIC_IN_PREFIX: "duplicate_topic"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_PERSISTENCE_FILE: "same.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "same.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
("persistence_file", "duplicate_persistence_file"),
|
||||
FlowResult(
|
||||
type="form", errors={"persistence_file": "duplicate_persistence_file"}
|
||||
),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "same.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "different1.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "different2.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
("base", "already_configured"),
|
||||
FlowResult(type="form", errors={"base": "already_configured"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "different1.json",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_PERSISTENCE_FILE: "different2.json",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.2",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "192.168.1.3",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "different1.json",
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "different2.json",
|
||||
},
|
||||
("base", "already_configured"),
|
||||
FlowResult(type="form", errors={"base": "already_configured"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "different1.json",
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "different2.json",
|
||||
},
|
||||
("base", "already_configured"),
|
||||
FlowResult(type="form", errors={"base": "already_configured"}),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "same.json",
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_RETAIN: True,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE_FILE: "same.json",
|
||||
},
|
||||
("persistence_file", "duplicate_persistence_file"),
|
||||
FlowResult(
|
||||
type="form", errors={"persistence_file": "duplicate_persistence_file"}
|
||||
),
|
||||
),
|
||||
(
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "1.4",
|
||||
},
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_PERSISTENCE_FILE: "bla2.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "1.4",
|
||||
},
|
||||
None,
|
||||
FlowResult(type="create_entry"),
|
||||
),
|
||||
],
|
||||
)
|
||||
@ -734,7 +668,7 @@ async def test_duplicate(
|
||||
mqtt: None,
|
||||
first_input: dict,
|
||||
second_input: dict,
|
||||
expected_result: tuple[str, str] | None,
|
||||
expected_result: FlowResult,
|
||||
) -> None:
|
||||
"""Test duplicate detection."""
|
||||
|
||||
@ -746,12 +680,17 @@ async def test_duplicate(
|
||||
):
|
||||
MockConfigEntry(domain=DOMAIN, data=first_input).add_to_hass(hass)
|
||||
|
||||
second_gateway_type = second_input.pop(CONF_GATEWAY_TYPE)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, data=second_input, context={"source": config_entries.SOURCE_IMPORT}
|
||||
DOMAIN,
|
||||
data={CONF_GATEWAY_TYPE: second_gateway_type},
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
second_input,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
if expected_result is None:
|
||||
assert result["type"] == "create_entry"
|
||||
else:
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == expected_result[1]
|
||||
|
||||
for key, val in expected_result.items():
|
||||
assert result[key] == val # type: ignore[literal-required]
|
||||
|
@ -2,360 +2,19 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from aiohttp import ClientWebSocketResponse
|
||||
from mysensors import BaseSyncGateway
|
||||
from mysensors.sensor import Sensor
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.mysensors import (
|
||||
CONF_BAUD_RATE,
|
||||
CONF_DEVICE,
|
||||
CONF_GATEWAYS,
|
||||
CONF_PERSISTENCE,
|
||||
CONF_PERSISTENCE_FILE,
|
||||
CONF_RETAIN,
|
||||
CONF_TCP_PORT,
|
||||
CONF_VERSION,
|
||||
DEFAULT_VERSION,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.mysensors.const import (
|
||||
CONF_GATEWAY_TYPE,
|
||||
CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_TOPIC_IN_PREFIX,
|
||||
CONF_TOPIC_OUT_PREFIX,
|
||||
)
|
||||
from homeassistant.components.mysensors import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"config, expected_calls, expected_to_succeed, expected_config_entry_data",
|
||||
[
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_TCP_PORT: 5003,
|
||||
}
|
||||
],
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
},
|
||||
1,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
CONF_DEVICE: "COM5",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 57600,
|
||||
CONF_VERSION: "2.3",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_RETAIN: True,
|
||||
}
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_PERSISTENCE_FILE: "blub.pickle",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 343,
|
||||
}
|
||||
],
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
1,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_PERSISTENCE_FILE: "blub.pickle",
|
||||
CONF_TCP_PORT: 343,
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
}
|
||||
],
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
1,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_TCP,
|
||||
CONF_DEVICE: "127.0.0.1",
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: DEFAULT_VERSION,
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_RETAIN: False,
|
||||
CONF_PERSISTENCE_FILE: "mysensors1.pickle",
|
||||
}
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_TOPIC_IN_PREFIX: "intopic",
|
||||
CONF_TOPIC_OUT_PREFIX: "outtopic",
|
||||
}
|
||||
],
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
1,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_VERSION: DEFAULT_VERSION,
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_TOPIC_OUT_PREFIX: "outtopic",
|
||||
CONF_TOPIC_IN_PREFIX: "intopic",
|
||||
CONF_RETAIN: False,
|
||||
CONF_PERSISTENCE_FILE: "mysensors1.pickle",
|
||||
}
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
}
|
||||
],
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
0,
|
||||
True,
|
||||
[{}],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_TOPIC_OUT_PREFIX: "out",
|
||||
CONF_TOPIC_IN_PREFIX: "in",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_PERSISTENCE_FILE: "bla2.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
},
|
||||
],
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
2,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_TOPIC_OUT_PREFIX: "out",
|
||||
CONF_TOPIC_IN_PREFIX: "in",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_RETAIN: False,
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_MQTT,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_PERSISTENCE_FILE: "bla2.json",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_RETAIN: False,
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
},
|
||||
],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "mqtt",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM6",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
},
|
||||
],
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
0,
|
||||
False,
|
||||
[{}],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "COMx",
|
||||
CONF_PERSISTENCE_FILE: "bla.json",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
},
|
||||
],
|
||||
CONF_VERSION: "2.4",
|
||||
CONF_PERSISTENCE: False,
|
||||
CONF_RETAIN: False,
|
||||
}
|
||||
},
|
||||
0,
|
||||
True,
|
||||
[{}],
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
CONF_GATEWAYS: [
|
||||
{
|
||||
CONF_DEVICE: "COM1",
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM2",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
2,
|
||||
True,
|
||||
[
|
||||
{
|
||||
CONF_DEVICE: "COM1",
|
||||
CONF_PERSISTENCE_FILE: "mysensors1.pickle",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "1.4",
|
||||
CONF_RETAIN: True,
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
},
|
||||
{
|
||||
CONF_DEVICE: "COM2",
|
||||
CONF_PERSISTENCE_FILE: "mysensors2.pickle",
|
||||
CONF_TOPIC_OUT_PREFIX: "",
|
||||
CONF_TOPIC_IN_PREFIX: "",
|
||||
CONF_BAUD_RATE: 115200,
|
||||
CONF_TCP_PORT: 5003,
|
||||
CONF_VERSION: "1.4",
|
||||
CONF_RETAIN: True,
|
||||
CONF_GATEWAY_TYPE: CONF_GATEWAY_TYPE_SERIAL,
|
||||
},
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_import(
|
||||
hass: HomeAssistant,
|
||||
mqtt: None,
|
||||
config: ConfigType,
|
||||
expected_calls: int,
|
||||
expected_to_succeed: bool,
|
||||
expected_config_entry_data: list[dict[str, Any]],
|
||||
) -> None:
|
||||
"""Test importing a gateway."""
|
||||
|
||||
with patch("sys.platform", "win32"), patch(
|
||||
"homeassistant.components.mysensors.config_flow.try_connect", return_value=True
|
||||
), patch(
|
||||
"homeassistant.components.mysensors.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await async_setup_component(hass, DOMAIN, config)
|
||||
assert result == expected_to_succeed
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == expected_calls
|
||||
|
||||
for idx in range(expected_calls):
|
||||
config_entry = mock_setup_entry.mock_calls[idx][1][1]
|
||||
expected_persistence_file = expected_config_entry_data[idx].pop(
|
||||
CONF_PERSISTENCE_FILE
|
||||
)
|
||||
expected_persistence_path = hass.config.path(expected_persistence_file)
|
||||
config_entry_data = dict(config_entry.data)
|
||||
persistence_path = config_entry_data.pop(CONF_PERSISTENCE_FILE)
|
||||
assert persistence_path == expected_persistence_path
|
||||
assert config_entry_data == expected_config_entry_data[idx]
|
||||
|
||||
|
||||
async def test_remove_config_entry_device(
|
||||
hass: HomeAssistant,
|
||||
gps_sensor: Sensor,
|
||||
|
Loading…
Reference in New Issue
Block a user