Skip to content

Commit

Permalink
Obihai: Config Flow Only
Browse files Browse the repository at this point in the history
  • Loading branch information
ejpenney committed Feb 22, 2023
1 parent d41facf commit 0620082
Show file tree
Hide file tree
Showing 10 changed files with 469 additions and 133 deletions.
4 changes: 3 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,9 @@ omit =
homeassistant/components/nuki/sensor.py
homeassistant/components/nx584/alarm_control_panel.py
homeassistant/components/oasa_telematics/sensor.py
homeassistant/components/obihai/*
homeassistant/components/obihai/const.py
homeassistant/components/obihai/obihai_api.py
homeassistant/components/obihai/sensor.py
homeassistant/components/octoprint/__init__.py
homeassistant/components/oem/climate.py
homeassistant/components/ohmconnect/sensor.py
Expand Down
35 changes: 35 additions & 0 deletions homeassistant/components/obihai/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
"""The Obihai integration."""

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType

from .const import CONF_OBIHAI_HOST, PLATFORMS

__all__ = [
"CONF_OBIHAI_HOST",
]


def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Obihai integration."""
return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up from a config entry."""
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

# Reload entry when its updated.
entry.async_on_unload(entry.add_update_listener(async_reload_entry))

return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload the config entry when it changed."""
await hass.config_entries.async_reload(entry.entry_id)
169 changes: 169 additions & 0 deletions homeassistant/components/obihai/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
"""Config flow to configure the Obihai integration."""
from __future__ import annotations

from types import MappingProxyType
from typing import Any

import voluptuous as vol

from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult

from .const import CONF_OBIHAI_HOST, DEFAULT_PASSWORD, DEFAULT_USERNAME, DOMAIN
from .obihai_api import validate_auth


@callback
def async_get_schema(
defaults: dict[str, Any] | MappingProxyType[str, Any]
) -> vol.Schema:
"""Return Obihai schema."""
schema = {
vol.Required(CONF_HOST, default=defaults.get(CONF_OBIHAI_HOST, "")): str,
vol.Optional(
CONF_USERNAME,
description={
"suggested_value": defaults.get(CONF_USERNAME, DEFAULT_USERNAME)
},
): str,
vol.Optional(
CONF_PASSWORD,
default=defaults.get(CONF_PASSWORD, DEFAULT_PASSWORD),
): str,
}

return vol.Schema(schema)


async def async_validate_credentials(
hass: HomeAssistant, user_input: dict[str, Any]
) -> dict[str, str]:
"""Manage Obihai options."""
errors = {}
result = await hass.async_add_executor_job(
validate_auth,
user_input.get(CONF_OBIHAI_HOST),
user_input.get(CONF_USERNAME),
user_input[CONF_PASSWORD],
)

if not result:
errors["base"] = "cannot_connect"

return errors


class ObihaiFlowHandler(ConfigFlow, domain=DOMAIN):
"""Config flow for Obihai."""

VERSION = 1

def __init__(self) -> None:
"""Initialize."""
self._host: str | None = None

@staticmethod
@callback
def async_get_options_flow(
config_entry: ConfigEntry,
) -> ObihaiOptionsFlowHandler:
"""Get the options flow for this handler."""
return ObihaiOptionsFlowHandler(config_entry)

async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle a flow initialized by the user."""
if user_input is not None:
return await self.async_validate_input(user_input)

user_input = {CONF_OBIHAI_HOST: self._host or ""}
return self.async_show_form(
step_id="user",
data_schema=async_get_schema(user_input),
)

async def async_validate_input(self, user_input: dict[str, Any]) -> FlowResult:
"""Check form inputs for errors."""
errors = await async_validate_credentials(self.hass, user_input)
if not errors:
self._async_abort_entries_match(
{CONF_OBIHAI_HOST: user_input[CONF_OBIHAI_HOST]}
)

# Storing data in option, to allow for changing them later
# using an options flow.
return self.async_create_entry(
title=user_input.get(CONF_NAME, user_input[CONF_OBIHAI_HOST]),
data={},
options={
CONF_OBIHAI_HOST: user_input[CONF_OBIHAI_HOST],
CONF_PASSWORD: user_input[CONF_PASSWORD],
CONF_USERNAME: user_input.get(CONF_USERNAME),
},
)

return self.async_show_form(
step_id="user",
data_schema=async_get_schema(user_input),
errors=errors,
)

# DEPRECATED
async def async_step_import(self, config: dict[str, Any]) -> FlowResult:
"""Handle a flow initialized by importing a config."""
self._async_abort_entries_match({CONF_OBIHAI_HOST: config[CONF_OBIHAI_HOST]})
return self.async_create_entry(
title=config.get(CONF_NAME, config[CONF_OBIHAI_HOST]),
data={},
options={
CONF_OBIHAI_HOST: config[CONF_OBIHAI_HOST],
CONF_PASSWORD: config[CONF_PASSWORD],
CONF_USERNAME: config.get(CONF_USERNAME),
},
)


class ObihaiOptionsFlowHandler(OptionsFlow):
"""Handle Obihai options."""

def __init__(self, config_entry: ConfigEntry) -> None:
"""Initialize Obihai options flow."""
self.config_entry = config_entry

async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Manage Obihai options."""
errors: dict[str, str] = {}

if user_input is not None:
errors = await async_validate_credentials(self.hass, user_input)
if not errors:
for entry in self.hass.config_entries.async_entries(DOMAIN):
if (
entry.entry_id != self.config_entry.entry_id
and entry.options[CONF_OBIHAI_HOST]
== user_input[CONF_OBIHAI_HOST]
):
errors = {CONF_OBIHAI_HOST: "already_configured"}

if not errors:
return self.async_create_entry(
title=user_input.get(CONF_NAME, user_input[CONF_OBIHAI_HOST]),
data={
CONF_OBIHAI_HOST: user_input[CONF_OBIHAI_HOST],
CONF_PASSWORD: user_input[CONF_PASSWORD],
CONF_USERNAME: user_input.get(CONF_USERNAME),
},
)
else:
user_input = {}

return self.async_show_form(
step_id="init",
data_schema=async_get_schema(user_input or self.config_entry.options),
errors=errors,
)
16 changes: 16 additions & 0 deletions homeassistant/components/obihai/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Constants for the Obihai integration."""

import logging
from typing import Final

from homeassistant.const import Platform

DOMAIN: Final = "obihai"
DEFAULT_USERNAME = "admin"
DEFAULT_PASSWORD = "admin"
OBIHAI = "Obihai"

LOGGER = logging.getLogger(__package__)

CONF_OBIHAI_HOST: Final = "host"
PLATFORMS: Final = [Platform.SENSOR]
1 change: 1 addition & 0 deletions homeassistant/components/obihai/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"domain": "obihai",
"name": "Obihai",
"codeowners": ["@dshokouhi"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/obihai",
"iot_class": "local_polling",
"loggers": ["pyobihai"],
Expand Down
Loading

0 comments on commit 0620082

Please sign in to comment.