Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions homeassistant/components/plugwise/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,50 @@
from homeassistant import config_entries, core, exceptions
from homeassistant.const import CONF_HOST, CONF_PASSWORD
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import DiscoveryInfoType

from .const import DOMAIN # pylint:disable=unused-import

_LOGGER = logging.getLogger(__name__)

DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_HOST): str, vol.Required(CONF_PASSWORD): str}
)
ZEROCONF_MAP = {
"smile": "P1 DSMR",
"smile_thermo": "Climate (Anna)",
"smile_open_therm": "Climate (Adam)",
}


def _base_schema(discovery_info):
"""Generate base schema."""
base_schema = {}

if not discovery_info:
base_schema[vol.Required(CONF_HOST)] = str

base_schema[vol.Required(CONF_PASSWORD)] = str

return vol.Schema(base_schema)


async def validate_input(hass: core.HomeAssistant, data):
"""
Validate the user input allows us to connect.

Data has the keys from DATA_SCHEMA with values provided by the user.
Data has the keys from _base_schema() with values provided by the user.
"""
websession = async_get_clientsession(hass, verify_ssl=False)
api = Smile(
host=data["host"], password=data["password"], timeout=30, websession=websession
host=data[CONF_HOST],
password=data[CONF_PASSWORD],
timeout=30,
websession=websession,
)

try:
await api.connect()
except Smile.InvalidAuthentication:
raise InvalidAuth
except Smile.ConnectionFailedError:
except Smile.PlugwiseError:
raise CannotConnect

return api
Expand All @@ -44,12 +62,39 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

def __init__(self):
"""Initialize the Plugwise config flow."""
self.discovery_info = {}

async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
"""Prepare configuration for a discovered Plugwise Smile."""
self.discovery_info = discovery_info
_properties = self.discovery_info.get("properties")

unique_id = self.discovery_info.get("hostname").split(".")[0]
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured()

_product = _properties.get("product", None)
_version = _properties.get("version", "n/a")
_name = f"{ZEROCONF_MAP.get(_product,_product)} v{_version}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a missing space after the comma. Didn't CI black catch this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently neither did pre-commit then ... let me check

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess because it's inside the format that it doesn't trigger ... running black manually with/without space doesn't yield different results

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll quickly rescan as well, but opened #37457 in the meantime


# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
self.context["title_placeholders"] = {
CONF_HOST: discovery_info[CONF_HOST],
"name": _name,
}
return await self.async_step_user()

async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}

if user_input is not None:

if self.discovery_info:
user_input[CONF_HOST] = self.discovery_info[CONF_HOST]

try:
api = await validate_input(self.hass, user_input)

Expand All @@ -64,12 +109,11 @@ async def async_step_user(self, user_input=None):

if not errors:
await self.async_set_unique_id(api.gateway_id)
self._abort_if_unique_id_configured()

return self.async_create_entry(title=api.smile_name, data=user_input)

return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors
step_id="user", data_schema=_base_schema(self.discovery_info), errors=errors
)


Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/plugwise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/plugwise",
"requirements": ["Plugwise_Smile==1.1.0"],
"codeowners": ["@CoMPaTech", "@bouwew"],
"zeroconf": ["_plugwise._tcp.local."],
"config_flow": true
}
3 changes: 2 additions & 1 deletion homeassistant/components/plugwise/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"abort": {
"already_configured": "This Smile is already configured"
}
},
"flow_title": "Smile: {name}"
}
}
3 changes: 3 additions & 0 deletions homeassistant/generated/zeroconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
"_nut._tcp.local.": [
"nut"
],
"_plugwise._tcp.local.": [
"plugwise"
],
"_printer._tcp.local.": [
"brother"
],
Expand Down
1 change: 1 addition & 0 deletions tests/components/plugwise/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
def mock_smile():
"""Create a Mock Smile for testing exceptions."""
with patch("homeassistant.components.plugwise.config_flow.Smile",) as smile_mock:
smile_mock.PlugwiseError = Smile.PlugwiseError
smile_mock.InvalidAuthentication = Smile.InvalidAuthentication
smile_mock.ConnectionFailedError = Smile.ConnectionFailedError
smile_mock.return_value.connect.return_value = True
Expand Down