mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 01:11:51 -04:00
Use SerialPortSelector for DSMR serial port configuration (#171103)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
a1e6a6f9a2
commit
266fccf0cf
@@ -13,7 +13,6 @@ from dsmr_parser.clients.rfxtrx_protocol import (
|
||||
from dsmr_parser.objects import DSMRObject
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import usb
|
||||
from homeassistant.config_entries import (
|
||||
ConfigEntry,
|
||||
ConfigFlow,
|
||||
@@ -23,6 +22,7 @@ from homeassistant.config_entries import (
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_PROTOCOL, CONF_TYPE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.selector import SerialPortSelector
|
||||
|
||||
from .const import (
|
||||
CONF_DSMR_VERSION,
|
||||
@@ -37,8 +37,6 @@ from .const import (
|
||||
RFXTRX_DSMR_PROTOCOL,
|
||||
)
|
||||
|
||||
CONF_MANUAL_PATH = "Enter Manually"
|
||||
|
||||
|
||||
class DSMRConnection:
|
||||
"""Test the connection to DSMR and receive telegram to read serial ids."""
|
||||
@@ -165,8 +163,6 @@ class DSMRFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
VERSION = 1
|
||||
|
||||
_dsmr_version: str | None = None
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(
|
||||
@@ -222,34 +218,13 @@ class DSMRFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Step when setting up serial configuration."""
|
||||
errors: dict[str, str] = {}
|
||||
if user_input is not None:
|
||||
user_selection = user_input[CONF_PORT]
|
||||
if user_selection == CONF_MANUAL_PATH:
|
||||
self._dsmr_version = user_input[CONF_DSMR_VERSION]
|
||||
return await self.async_step_setup_serial_manual_path()
|
||||
|
||||
dev_path = user_selection
|
||||
|
||||
validate_data = {
|
||||
CONF_PORT: dev_path,
|
||||
CONF_DSMR_VERSION: user_input[CONF_DSMR_VERSION],
|
||||
}
|
||||
|
||||
data = await self.async_validate_dsmr(validate_data, errors)
|
||||
data = await self.async_validate_dsmr(user_input, errors)
|
||||
if not errors:
|
||||
return self.async_create_entry(title=data[CONF_PORT], data=data)
|
||||
|
||||
ports = await usb.async_scan_serial_ports(self.hass)
|
||||
list_of_ports = {
|
||||
port.device: f"{port.device} - {port.description or 'n/a'}"
|
||||
f", s/n: {port.serial_number or 'n/a'}"
|
||||
+ (f" - {port.manufacturer}" if port.manufacturer else "")
|
||||
for port in ports
|
||||
}
|
||||
list_of_ports[CONF_MANUAL_PATH] = CONF_MANUAL_PATH
|
||||
|
||||
schema = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_PORT): vol.In(list_of_ports),
|
||||
vol.Required(CONF_PORT): SerialPortSelector(),
|
||||
vol.Required(CONF_DSMR_VERSION): vol.In(DSMR_VERSIONS),
|
||||
}
|
||||
)
|
||||
@@ -259,27 +234,6 @@ class DSMRFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_setup_serial_manual_path(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Select path manually."""
|
||||
if user_input is not None:
|
||||
validate_data = {
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
CONF_DSMR_VERSION: self._dsmr_version,
|
||||
}
|
||||
|
||||
errors: dict[str, str] = {}
|
||||
data = await self.async_validate_dsmr(validate_data, errors)
|
||||
if not errors:
|
||||
return self.async_create_entry(title=data[CONF_PORT], data=data)
|
||||
|
||||
schema = vol.Schema({vol.Required(CONF_PORT): str})
|
||||
return self.async_show_form(
|
||||
step_id="setup_serial_manual_path",
|
||||
data_schema=schema,
|
||||
)
|
||||
|
||||
async def async_validate_dsmr(
|
||||
self, input_data: dict[str, Any], errors: dict[str, str]
|
||||
) -> dict[str, Any]:
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
},
|
||||
"title": "[%key:common::config_flow::data::device%]"
|
||||
},
|
||||
"setup_serial_manual_path": {
|
||||
"data": {
|
||||
"port": "[%key:common::config_flow::data::usb_path%]"
|
||||
},
|
||||
"title": "[%key:common::config_flow::data::path%]"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"type": "Connection type"
|
||||
|
||||
@@ -192,12 +192,7 @@ async def test_setup_network_rfxtrx(
|
||||
),
|
||||
],
|
||||
)
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
version: str,
|
||||
@@ -235,12 +230,7 @@ async def test_setup_serial(
|
||||
assert result["data"] == entry_data
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial_rfxtrx(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
rfxtrx_dsmr_connection_send_validate_fixture: tuple[
|
||||
@@ -291,65 +281,7 @@ async def test_setup_serial_rfxtrx(
|
||||
assert result["data"] == {**entry_data, **SERIAL_DATA}
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial_manual(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
) -> None:
|
||||
"""Test we can setup serial with manual entry."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] is None
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"type": "Serial"},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "setup_serial"
|
||||
assert result["errors"] == {}
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"port": "Enter Manually", "dsmr_version": "2.2"},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "setup_serial_manual_path"
|
||||
assert result["errors"] is None
|
||||
|
||||
with patch("homeassistant.components.dsmr.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"port": "/dev/ttyUSB0"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entry_data = {
|
||||
"port": "/dev/ttyUSB0",
|
||||
"dsmr_version": "2.2",
|
||||
"protocol": "dsmr_protocol",
|
||||
}
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "/dev/ttyUSB0"
|
||||
assert result["data"] == {**entry_data, **SERIAL_DATA}
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial_fail(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
) -> None:
|
||||
@@ -395,12 +327,7 @@ async def test_setup_serial_fail(
|
||||
assert result["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial_timeout(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
rfxtrx_dsmr_connection_send_validate_fixture: tuple[
|
||||
@@ -456,12 +383,7 @@ async def test_setup_serial_timeout(
|
||||
assert result["errors"] == {"base": "cannot_communicate"}
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.dsmr.config_flow.usb.async_scan_serial_ports",
|
||||
return_value=[com_port()],
|
||||
)
|
||||
async def test_setup_serial_wrong_telegram(
|
||||
com_mock,
|
||||
hass: HomeAssistant,
|
||||
dsmr_connection_send_validate_fixture: tuple[MagicMock, MagicMock, MagicMock],
|
||||
rfxtrx_dsmr_connection_send_validate_fixture: tuple[
|
||||
|
||||
Reference in New Issue
Block a user