Add config flow and MQTT autodiscover to dsmr_reader integration (#71617)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: G Johansson <goran.johansson@shiftit.se> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
f26fadbdfc
commit
7aa53feff4
13 changed files with 185 additions and 6 deletions
|
@ -238,7 +238,9 @@ omit =
|
|||
homeassistant/components/doorbird/util.py
|
||||
homeassistant/components/dovado/*
|
||||
homeassistant/components/downloader/*
|
||||
homeassistant/components/dsmr_reader/*
|
||||
homeassistant/components/dsmr_reader/__init__.py
|
||||
homeassistant/components/dsmr_reader/definitions.py
|
||||
homeassistant/components/dsmr_reader/sensor.py
|
||||
homeassistant/components/dte_energy_bridge/sensor.py
|
||||
homeassistant/components/dublin_bus_transport/sensor.py
|
||||
homeassistant/components/dunehd/__init__.py
|
||||
|
|
|
@ -263,7 +263,8 @@ build.json @home-assistant/supervisor
|
|||
/tests/components/doorbird/ @oblogic7 @bdraco @flacjacket
|
||||
/homeassistant/components/dsmr/ @Robbie1221 @frenck
|
||||
/tests/components/dsmr/ @Robbie1221 @frenck
|
||||
/homeassistant/components/dsmr_reader/ @depl0y
|
||||
/homeassistant/components/dsmr_reader/ @depl0y @glodenox
|
||||
/tests/components/dsmr_reader/ @depl0y @glodenox
|
||||
/homeassistant/components/dunehd/ @bieniu
|
||||
/tests/components/dunehd/ @bieniu
|
||||
/homeassistant/components/dwd_weather_warnings/ @runningman84 @stephan192 @Hummel95
|
||||
|
|
|
@ -1 +1,19 @@
|
|||
"""The DSMR Reader component."""
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up the DSMR Reader integration."""
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload the DSMR Reader integration."""
|
||||
# no data stored in hass.data
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
|
40
homeassistant/components/dsmr_reader/config_flow.py
Normal file
40
homeassistant/components/dsmr_reader/config_flow.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
"""Config flow to configure DSMR Reader."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Awaitable
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers.config_entry_flow import DiscoveryFlowHandler
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def _async_has_devices(_: HomeAssistant) -> bool:
|
||||
"""MQTT is set as dependency, so that should be sufficient."""
|
||||
return True
|
||||
|
||||
|
||||
class DsmrReaderFlowHandler(DiscoveryFlowHandler[Awaitable[bool]], domain=DOMAIN):
|
||||
"""Handle DSMR Reader config flow. The MQTT step is inherited from the parent class."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Set up the config flow."""
|
||||
super().__init__(DOMAIN, "DSMR Reader", _async_has_devices)
|
||||
|
||||
async def async_step_confirm(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Confirm setup."""
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="confirm",
|
||||
)
|
||||
|
||||
return await super().async_step_confirm(user_input)
|
3
homeassistant/components/dsmr_reader/const.py
Normal file
3
homeassistant/components/dsmr_reader/const.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""Constant values for DSMR Reader."""
|
||||
|
||||
DOMAIN = "dsmr_reader"
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"domain": "dsmr_reader",
|
||||
"name": "DSMR Reader",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/dsmr_reader",
|
||||
"dependencies": ["mqtt"],
|
||||
"codeowners": ["@depl0y"],
|
||||
"mqtt": ["dsmr/#"],
|
||||
"codeowners": ["@depl0y", "@glodenox"],
|
||||
"iot_class": "local_push"
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@ from __future__ import annotations
|
|||
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import DOMAIN
|
||||
from .definitions import SENSORS, DSMRReaderSensorEntityDescription
|
||||
|
||||
DOMAIN = "dsmr_reader"
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
|
@ -19,7 +20,31 @@ async def async_setup_platform(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up DSMR Reader sensors."""
|
||||
"""Set up DSMR Reader sensors via configuration.yaml and show deprecation warning."""
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecated_yaml",
|
||||
breaks_in_ha_version="2022.12.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_yaml",
|
||||
)
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
data=config,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up DSMR Reader sensors from config entry."""
|
||||
async_add_entities(DSMRSensor(description) for description in SENSORS)
|
||||
|
||||
|
||||
|
|
18
homeassistant/components/dsmr_reader/strings.json
Normal file
18
homeassistant/components/dsmr_reader/strings.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Make sure to configure the 'split topic' data sources in DSMR Reader."
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_yaml": {
|
||||
"title": "The DSMR Reader configuration is being removed",
|
||||
"description": "Configuring DSMR Reader using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically.\n\nRemove the DSMR Reader YAML configuration from your configuration.yaml file and restart Home Assistant to fix this issue."
|
||||
}
|
||||
}
|
||||
}
|
18
homeassistant/components/dsmr_reader/translations/en.json
Normal file
18
homeassistant/components/dsmr_reader/translations/en.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Make sure to configure the 'split topic' data sources in DSMR Reader."
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_yaml": {
|
||||
"description": "Configuring DSMR Reader using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically.\n\nRemove the DSMR Reader YAML configuration from your configuration.yaml file and restart Home Assistant to fix this issue.",
|
||||
"title": "The DSMR Reader configuration is being removed"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,6 +83,7 @@ FLOWS = {
|
|||
"dnsip",
|
||||
"doorbird",
|
||||
"dsmr",
|
||||
"dsmr_reader",
|
||||
"dunehd",
|
||||
"dynalite",
|
||||
"eafm",
|
||||
|
|
|
@ -4,6 +4,9 @@ To update, run python3 -m script.hassfest
|
|||
"""
|
||||
|
||||
MQTT = {
|
||||
"dsmr_reader": [
|
||||
"dsmr/#",
|
||||
],
|
||||
"tasmota": [
|
||||
"tasmota/discovery/#",
|
||||
],
|
||||
|
|
1
tests/components/dsmr_reader/__init__.py
Normal file
1
tests/components/dsmr_reader/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
"""Tests for the dsmr_reader component."""
|
47
tests/components/dsmr_reader/test_config_flow.py
Normal file
47
tests/components/dsmr_reader/test_config_flow.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
"""Tests for the config flow."""
|
||||
from homeassistant.components.dsmr_reader.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
|
||||
async def test_import_step(hass: HomeAssistant):
|
||||
"""Test the import step."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
)
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "DSMR Reader"
|
||||
|
||||
second_result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
)
|
||||
assert second_result["type"] == FlowResultType.ABORT
|
||||
assert second_result["reason"] == "single_instance_allowed"
|
||||
|
||||
|
||||
async def test_user_step(hass: HomeAssistant):
|
||||
"""Test the user step call."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "confirm"
|
||||
assert result["errors"] is None
|
||||
|
||||
config_result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert config_result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert config_result["title"] == "DSMR Reader"
|
||||
|
||||
duplicate_result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
||||
assert duplicate_result["type"] == FlowResultType.ABORT
|
||||
assert duplicate_result["reason"] == "single_instance_allowed"
|
Loading…
Add table
Reference in a new issue