Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor config flow and config entries for IamMeter device #49735

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Expand Up @@ -424,6 +424,7 @@ tests/components/hyperion/* @dermotduffy
homeassistant/components/ialarm/* @RyuzakiKK
tests/components/ialarm/* @RyuzakiKK
homeassistant/components/iammeter/* @lewei50
tests/components/iammeter/* @lewei50
homeassistant/components/iaqualink/* @flz
tests/components/iaqualink/* @flz
homeassistant/components/icloud/* @Quentame @nzapponi
Expand Down
15 changes: 15 additions & 0 deletions homeassistant/components/iammeter/__init__.py
@@ -1 +1,16 @@
"""Support for IamMeter Devices."""
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

PLATFORMS = ["sensor"]


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up a config entry for iammeter."""
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
return await hass.config_entries.async_forward_entry_unload(entry, "sensor")
114 changes: 114 additions & 0 deletions homeassistant/components/iammeter/config_flow.py
@@ -0,0 +1,114 @@
"""Config flow for iammeter integration."""
import asyncio
import logging
from urllib.parse import ParseResult, urlparse

import async_timeout
import iammeter
from iammeter.power_meter import IamMeterError
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT

from .const import DEFAULT_HOST, DEFAULT_NAME, DEFAULT_PORT, DOMAIN

_LOGGER = logging.getLogger(__name__)

PLATFORM_TIMEOUT = 8


class IammeterConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Iammeter."""

VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

def __init__(self) -> None:
"""Initialize the config flow."""
self.host = None
self.api = None

async def _test_connection(self, host, port):
with async_timeout.timeout(PLATFORM_TIMEOUT):
try:
self.api = await iammeter.real_time_api(host, port)
except (IamMeterError, asyncio.TimeoutError):
return False
return True

async def async_step_user(self, user_input=None):
"""Step when user initializes a integration."""
errors = {}
if user_input is not None:
# set some defaults in case we need to return to the form
name = user_input.get(CONF_NAME, DEFAULT_NAME)
port = user_input.get(CONF_PORT, DEFAULT_PORT)
host_entry = user_input.get(CONF_HOST)
url = urlparse(host_entry, "http")
netloc = url.netloc or url.path
path = url.path if url.netloc else ""
url = ParseResult("http", netloc, path, *url[3:])
host = netloc

connect_ok = False
connect_ok = await self._test_connection(host, port)
if not connect_ok:
errors[CONF_NAME] = "cannot_connect"
else:
if self.api:
dev_sn = self.api.iammeter.serial_number
await self.async_set_unique_id(dev_sn)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=name,
data={
CONF_NAME: dev_sn,
CONF_HOST: host,
CONF_PORT: port,
},
)

else:
user_input = {}
user_input[CONF_NAME] = DEFAULT_NAME
user_input[CONF_PORT] = DEFAULT_PORT
user_input[CONF_HOST] = DEFAULT_HOST

return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_NAME, default=DEFAULT_NAME): str,
vol.Required(
CONF_HOST, default=user_input.get(CONF_HOST, DEFAULT_HOST)
): str,
vol.Required(
CONF_PORT, default=user_input.get(CONF_PORT, DEFAULT_PORT)
): str,
}
),
errors=errors,
)

async def async_step_import(self, user_input=None):
"""Import a config entry."""
host_entry = user_input.get(CONF_HOST, DEFAULT_HOST)
name = user_input.get(CONF_NAME, DEFAULT_NAME)
port = user_input.get(CONF_PORT, DEFAULT_PORT)

url = urlparse(host_entry, "http")
netloc = url.netloc or url.path
path = url.path if url.netloc else ""
url = ParseResult("http", netloc, path, *url[3:])
host = url.geturl()
user_input[CONF_NAME] = name
user_input[CONF_PORT] = port
user_input[CONF_HOST] = host

connect_ok = False
connect_ok = await self._test_connection(host, port)
if connect_ok and self.api:
await self.async_set_unique_id(self.api.iammeter.serial_number)
self._abort_if_unique_id_configured()
return await self.async_step_user(user_input)
7 changes: 7 additions & 0 deletions homeassistant/components/iammeter/const.py
@@ -0,0 +1,7 @@
"""Constants for the Iammeter API."""

DOMAIN = "iammeter"
DATA_DISCOVERED_HOSTS = "iammter_discovered_hosts"
DEFAULT_PORT = "80"
DEFAULT_HOST = "192.168.2.15"
DEFAULT_NAME = "IamMeter"
1 change: 1 addition & 0 deletions homeassistant/components/iammeter/manifest.json
@@ -1,6 +1,7 @@
{
"domain": "iammeter",
"name": "IamMeter",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/iammeter",
"codeowners": ["@lewei50"],
"requirements": ["iammeter==0.1.7"],
Expand Down
23 changes: 22 additions & 1 deletion homeassistant/components/iammeter/sensor.py
Expand Up @@ -11,6 +11,7 @@
import voluptuous as vol

from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
Expand All @@ -24,6 +25,8 @@
UpdateFailed,
)

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

DEFAULT_PORT = 80
Expand All @@ -47,7 +50,25 @@ async def async_setup_platform(
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Platform setup."""
"""Import the yaml config to a config flow."""
data = {
CONF_NAME: config[CONF_NAME],
CONF_HOST: config[CONF_HOST],
CONF_PORT: config[CONF_PORT],
}
# Create a config entry with the config data
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=data
)
)


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
):
"""Add an IamMeter entry."""
config = entry.data
config_host = config[CONF_HOST]
lewei50 marked this conversation as resolved.
Show resolved Hide resolved
config_port = config[CONF_PORT]
config_name = config[CONF_NAME]
Expand Down
19 changes: 19 additions & 0 deletions homeassistant/components/iammeter/strings.json
@@ -0,0 +1,19 @@
{
"config": {
"flow_title": "IamMeter {sn}",
"step": {
"user": {
"title": "Define your IamMeter connection",
"data": {
"host": "[%key:common::config_flow::data::host%]",
"port": "[%key:common::config_flow::data::port%]"
}
}
},
"error": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
},
"abort": {"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"}
}
}
21 changes: 21 additions & 0 deletions homeassistant/components/iammeter/translations/en.json
@@ -0,0 +1,21 @@
{
"config": {
"abort": {
"already_configured": "Device is already configured"
},
"error": {
"already_configured": "Device is already configured",
"cannot_connect": "Failed to connect"
},
"flow_title": "IamMeter {sn}",
"step": {
"user": {
"data": {
"host": "Host",
"port": "Port"
},
"title": "Define your IamMeter connection"
}
}
}
}
1 change: 1 addition & 0 deletions homeassistant/generated/config_flows.py
Expand Up @@ -149,6 +149,7 @@
"hvv_departures",
"hyperion",
"ialarm",
"iammeter",
"iaqualink",
"icloud",
"ifttt",
Expand Down
3 changes: 3 additions & 0 deletions requirements_test_all.txt
Expand Up @@ -576,6 +576,9 @@ huisbaasje-client==0.1.0
# homeassistant.components.hyperion
hyperion-py==0.7.4

# homeassistant.components.iammeter
iammeter==0.1.7

# homeassistant.components.iaqualink
iaqualink==0.4.1

Expand Down
1 change: 1 addition & 0 deletions tests/components/iammeter/__init__.py
@@ -0,0 +1 @@
"""Tests for the IamMeter integration."""
5 changes: 5 additions & 0 deletions tests/components/iammeter/const.py
@@ -0,0 +1,5 @@
"""Constants for the Iammeter API."""

NAME = "IamMeterTestDevice"
HOST = "192.168.2.15"
PORT = "80"