mirror of
https://github.com/home-assistant/core.git
synced 2025-07-11 15:27:08 +00:00
Add port to config flow of P1 Monitor integration (#128324)
This commit is contained in:
parent
5497697cf2
commit
a0637a6ff8
@ -3,11 +3,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN, LOGGER
|
||||||
from .coordinator import P1MonitorDataUpdateCoordinator
|
from .coordinator import P1MonitorDataUpdateCoordinator
|
||||||
|
|
||||||
PLATFORMS = [Platform.SENSOR]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
@ -30,6 +30,29 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||||
|
"""Migrate old entry."""
|
||||||
|
LOGGER.debug("Migrating from version %s", config_entry.version)
|
||||||
|
|
||||||
|
if config_entry.version == 1:
|
||||||
|
# Migrate to split host and port
|
||||||
|
host = config_entry.data[CONF_HOST]
|
||||||
|
if ":" in host:
|
||||||
|
host, port = host.split(":")
|
||||||
|
else:
|
||||||
|
port = 80
|
||||||
|
|
||||||
|
new_data = {
|
||||||
|
**config_entry.data,
|
||||||
|
CONF_HOST: host,
|
||||||
|
CONF_PORT: int(port),
|
||||||
|
}
|
||||||
|
|
||||||
|
hass.config_entries.async_update_entry(config_entry, data=new_data, version=2)
|
||||||
|
LOGGER.debug("Migration to version %s successful", config_entry.version)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Unload P1 Monitor config entry."""
|
"""Unload P1 Monitor config entry."""
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
@ -8,7 +8,7 @@ from p1monitor import P1Monitor, P1MonitorError
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.selector import TextSelector
|
from homeassistant.helpers.selector import TextSelector
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ from .const import DOMAIN
|
|||||||
class P1MonitorFlowHandler(ConfigFlow, domain=DOMAIN):
|
class P1MonitorFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||||
"""Config flow for P1 Monitor."""
|
"""Config flow for P1 Monitor."""
|
||||||
|
|
||||||
VERSION = 1
|
VERSION = 2
|
||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
@ -31,7 +31,9 @@ class P1MonitorFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
session = async_get_clientsession(self.hass)
|
session = async_get_clientsession(self.hass)
|
||||||
try:
|
try:
|
||||||
async with P1Monitor(
|
async with P1Monitor(
|
||||||
host=user_input[CONF_HOST], session=session
|
host=user_input[CONF_HOST],
|
||||||
|
port=user_input[CONF_PORT],
|
||||||
|
session=session,
|
||||||
) as client:
|
) as client:
|
||||||
await client.smartmeter()
|
await client.smartmeter()
|
||||||
except P1MonitorError:
|
except P1MonitorError:
|
||||||
@ -41,6 +43,7 @@ class P1MonitorFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
title="P1 Monitor",
|
title="P1 Monitor",
|
||||||
data={
|
data={
|
||||||
CONF_HOST: user_input[CONF_HOST],
|
CONF_HOST: user_input[CONF_HOST],
|
||||||
|
CONF_PORT: user_input[CONF_PORT],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,6 +52,7 @@ class P1MonitorFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_HOST): TextSelector(),
|
vol.Required(CONF_HOST): TextSelector(),
|
||||||
|
vol.Required(CONF_PORT, default=80): int,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
errors=errors,
|
errors=errors,
|
||||||
|
@ -15,7 +15,7 @@ from p1monitor import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
@ -59,7 +59,9 @@ class P1MonitorDataUpdateCoordinator(DataUpdateCoordinator[P1MonitorData]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.p1monitor = P1Monitor(
|
self.p1monitor = P1Monitor(
|
||||||
self.config_entry.data[CONF_HOST], session=async_get_clientsession(hass)
|
host=self.config_entry.data[CONF_HOST],
|
||||||
|
port=self.config_entry.data[CONF_PORT],
|
||||||
|
session=async_get_clientsession(hass),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> P1MonitorData:
|
async def _async_update_data(self) -> P1MonitorData:
|
||||||
|
@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Any, cast
|
|||||||
|
|
||||||
from homeassistant.components.diagnostics import async_redact_data
|
from homeassistant.components.diagnostics import async_redact_data
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -22,9 +22,7 @@ from .coordinator import P1MonitorDataUpdateCoordinator
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _typeshed import DataclassInstance
|
from _typeshed import DataclassInstance
|
||||||
|
|
||||||
TO_REDACT = {
|
TO_REDACT = {CONF_HOST, CONF_PORT}
|
||||||
CONF_HOST,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async def async_get_config_entry_diagnostics(
|
async def async_get_config_entry_diagnostics(
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"description": "Set up P1 Monitor to integrate with Home Assistant.",
|
"description": "Set up P1 Monitor to integrate with Home Assistant.",
|
||||||
"data": {
|
"data": {
|
||||||
"host": "[%key:common::config_flow::data::host%]"
|
"host": "[%key:common::config_flow::data::host%]",
|
||||||
|
"port": "[%key:common::config_flow::data::port%]"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"host": "The IP address or hostname of your P1 Monitor installation."
|
"host": "The IP address or hostname of your P1 Monitor installation.",
|
||||||
|
"port": "The port of your P1 Monitor installation."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,7 @@ from p1monitor import Phases, Settings, SmartMeter, WaterMeter
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.p1_monitor.const import DOMAIN
|
from homeassistant.components.p1_monitor.const import DOMAIN
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, load_fixture
|
from tests.common import MockConfigEntry, load_fixture
|
||||||
@ -19,8 +19,9 @@ def mock_config_entry() -> MockConfigEntry:
|
|||||||
return MockConfigEntry(
|
return MockConfigEntry(
|
||||||
title="monitor",
|
title="monitor",
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
data={CONF_HOST: "example"},
|
data={CONF_HOST: "example", CONF_PORT: 80},
|
||||||
unique_id="unique_thingy",
|
unique_id="unique_thingy",
|
||||||
|
version=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
45
tests/components/p1_monitor/snapshots/test_init.ambr
Normal file
45
tests/components/p1_monitor/snapshots/test_init.ambr
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_migration
|
||||||
|
ConfigEntrySnapshot({
|
||||||
|
'data': dict({
|
||||||
|
'host': 'example',
|
||||||
|
'port': 80,
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'discovery_keys': dict({
|
||||||
|
}),
|
||||||
|
'domain': 'p1_monitor',
|
||||||
|
'entry_id': <ANY>,
|
||||||
|
'minor_version': 1,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'pref_disable_new_entities': False,
|
||||||
|
'pref_disable_polling': False,
|
||||||
|
'source': 'user',
|
||||||
|
'title': 'Mock Title',
|
||||||
|
'unique_id': 'unique_thingy',
|
||||||
|
'version': 2,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_port_migration
|
||||||
|
ConfigEntrySnapshot({
|
||||||
|
'data': dict({
|
||||||
|
'host': 'example',
|
||||||
|
'port': 80,
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'discovery_keys': dict({
|
||||||
|
}),
|
||||||
|
'domain': 'p1_monitor',
|
||||||
|
'entry_id': <ANY>,
|
||||||
|
'minor_version': 1,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'pref_disable_new_entities': False,
|
||||||
|
'pref_disable_polling': False,
|
||||||
|
'source': 'user',
|
||||||
|
'title': 'Mock Title',
|
||||||
|
'unique_id': 'unique_thingy',
|
||||||
|
'version': 2,
|
||||||
|
})
|
||||||
|
# ---
|
@ -6,7 +6,7 @@ from p1monitor import P1MonitorError
|
|||||||
|
|
||||||
from homeassistant.components.p1_monitor.const import DOMAIN
|
from homeassistant.components.p1_monitor.const import DOMAIN
|
||||||
from homeassistant.config_entries import SOURCE_USER
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
|
||||||
@ -30,12 +30,12 @@ async def test_full_user_flow(hass: HomeAssistant) -> None:
|
|||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={CONF_HOST: "example.com"},
|
user_input={CONF_HOST: "example.com", CONF_PORT: 80},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result2.get("type") is FlowResultType.CREATE_ENTRY
|
assert result2.get("type") is FlowResultType.CREATE_ENTRY
|
||||||
assert result2.get("title") == "P1 Monitor"
|
assert result2.get("title") == "P1 Monitor"
|
||||||
assert result2.get("data") == {CONF_HOST: "example.com"}
|
assert result2.get("data") == {CONF_HOST: "example.com", CONF_PORT: 80}
|
||||||
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
assert len(mock_p1monitor.mock_calls) == 1
|
assert len(mock_p1monitor.mock_calls) == 1
|
||||||
@ -50,7 +50,7 @@ async def test_api_error(hass: HomeAssistant) -> None:
|
|||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
context={"source": SOURCE_USER},
|
context={"source": SOURCE_USER},
|
||||||
data={CONF_HOST: "example.com"},
|
data={CONF_HOST: "example.com", CONF_PORT: 80},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result.get("type") is FlowResultType.FORM
|
assert result.get("type") is FlowResultType.FORM
|
||||||
|
@ -21,6 +21,7 @@ async def test_diagnostics(
|
|||||||
"title": "monitor",
|
"title": "monitor",
|
||||||
"data": {
|
"data": {
|
||||||
"host": REDACTED,
|
"host": REDACTED,
|
||||||
|
"port": REDACTED,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
from p1monitor import P1MonitorConnectionError
|
from p1monitor import P1MonitorConnectionError
|
||||||
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.p1_monitor.const import DOMAIN
|
from homeassistant.components.p1_monitor.const import DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import CONF_HOST
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
@ -44,3 +46,35 @@ async def test_config_entry_not_ready(
|
|||||||
|
|
||||||
assert mock_request.call_count == 1
|
assert mock_request.call_count == 1
|
||||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
|
||||||
|
|
||||||
|
async def test_migration(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||||
|
"""Test config entry version 1 -> 2 migration."""
|
||||||
|
mock_config_entry = MockConfigEntry(
|
||||||
|
unique_id="unique_thingy",
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={CONF_HOST: "example"},
|
||||||
|
version=1,
|
||||||
|
)
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.config_entries.async_get_entry(mock_config_entry.entry_id) == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_port_migration(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||||
|
"""Test migration of host:port to separate host and port."""
|
||||||
|
mock_config_entry = MockConfigEntry(
|
||||||
|
unique_id="unique_thingy",
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={CONF_HOST: "example:80"},
|
||||||
|
version=1,
|
||||||
|
)
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.config_entries.async_get_entry(mock_config_entry.entry_id) == snapshot
|
||||||
|
Loading…
x
Reference in New Issue
Block a user