1
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:
Martin Hjelmare 2022-05-31 15:22:31 +02:00 committed by GitHub
parent cf27b82d2f
commit 8140ed724c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 651 deletions

View File

@ -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

View File

@ -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):

View File

@ -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"

View File

@ -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):

View File

@ -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]

View File

@ -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,