Skip to content

Commit

Permalink
integration setup features, refactor config-flow and password encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
elad-bar committed Jul 27, 2023
1 parent 090e1d2 commit d77f23f
Show file tree
Hide file tree
Showing 17 changed files with 523 additions and 244 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
## v1.0.3

- Improve AWS client connection recovery process (unsubscribe topics and disconnect before trying to connect again)
- Refactor password encryption flow
- Refactor integration loading (will be loaded only after HA is loaded, re-load will be performed immediately)
- Integration setup
- Add support for edit integration details
- Add title to the form (Add / Edit), will set the integration name

## v1.0.2

Expand Down
23 changes: 14 additions & 9 deletions custom_components/mydolphin_plus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
import sys

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.core import HomeAssistant

from .common.consts import DEFAULT_NAME, DOMAIN, PLATFORMS
from .common.exceptions import LoginError
from .managers.config_manager import ConfigManager
from .managers.coordinator import MyDolphinPlusCoordinator
from .managers.password_manager import PasswordManager
from .models.exceptions import LoginError

_LOGGER = logging.getLogger(__name__)

Expand All @@ -26,24 +28,27 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
initialized = False

try:
entry_config = {key: entry.data[key] for key in entry.data}

await PasswordManager.decrypt(hass, entry_config, entry.entry_id)

config_manager = ConfigManager(hass, entry)
await config_manager.initialize()
await config_manager.initialize(entry_config)

is_initialized = config_manager.is_initialized

if is_initialized:
coordinator = MyDolphinPlusCoordinator(hass, config_manager)
await coordinator.initialize()

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

_LOGGER.info(
f"Start loading {DOMAIN} integration, Entry ID: {entry.entry_id}"
)
if hass.is_running:
await coordinator.initialize()

await coordinator.async_config_entry_first_refresh()
else:
hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, coordinator.on_home_assistant_start
)

_LOGGER.info("Finished loading integration")

Expand Down
15 changes: 5 additions & 10 deletions custom_components/mydolphin_plus/common/base_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@
import sys
from typing import Any

from custom_components.mydolphin_plus import (
DOMAIN,
ConfigManager,
MyDolphinPlusCoordinator,
)
from custom_components.mydolphin_plus.common.consts import DATA_ROBOT_FAMILY
from custom_components.mydolphin_plus.common.entity_descriptions import (
MyDolphinPlusEntityDescription,
get_entity_descriptions,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import slugify

from ..managers.config_manager import ConfigManager
from ..managers.coordinator import MyDolphinPlusCoordinator
from .consts import DATA_ROBOT_FAMILY, DOMAIN
from .entity_descriptions import MyDolphinPlusEntityDescription, get_entity_descriptions

_LOGGER = logging.getLogger(__name__)


Expand Down
1 change: 1 addition & 0 deletions custom_components/mydolphin_plus/common/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
INVALID_TOKEN_SECTION = "https://github.com/sh00t2kill/dolphin-robot#invalid-token"

ENTRY_ID_CONFIG = "config"
CONF_TITLE = "title"

SIGNAL_DEVICE_NEW = f"{DOMAIN}_NEW_DEVICE_SIGNAL"
SIGNAL_AWS_CLIENT_STATUS = f"{DOMAIN}_AWS_CLIENT_STATUS_SIGNAL"
Expand Down
57 changes: 29 additions & 28 deletions custom_components/mydolphin_plus/common/entity_descriptions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
from dataclasses import dataclass

from custom_components.mydolphin_plus.common.clean_modes import (
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntityDescription,
)
from homeassistant.components.light import LightEntityDescription
from homeassistant.components.number import NumberDeviceClass, NumberEntityDescription
from homeassistant.components.select import SelectEntityDescription
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.components.vacuum import (
StateVacuumEntityDescription,
VacuumEntityFeature,
)
from homeassistant.const import (
SIGNAL_STRENGTH_DECIBELS,
EntityCategory,
Platform,
UnitOfTemperature,
UnitOfTime,
)
from homeassistant.helpers.entity import EntityDescription
from homeassistant.util import slugify

from .clean_modes import (
CleanModes,
get_clean_mode_cycle_time_key,
get_clean_mode_cycle_time_name,
)
from custom_components.mydolphin_plus.common.consts import (
from .consts import (
DATA_KEY_AWS_BROKER,
DATA_KEY_CLEAN_MODE,
DATA_KEY_CYCLE_COUNT,
Expand All @@ -28,32 +54,7 @@
ICON_LED_MODES,
VACUUM_FEATURES,
)
from custom_components.mydolphin_plus.common.robot_family import RobotFamily
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntityDescription,
)
from homeassistant.components.light import LightEntityDescription
from homeassistant.components.number import NumberDeviceClass, NumberEntityDescription
from homeassistant.components.select import SelectEntityDescription
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.components.vacuum import (
StateVacuumEntityDescription,
VacuumEntityFeature,
)
from homeassistant.const import (
SIGNAL_STRENGTH_DECIBELS,
EntityCategory,
Platform,
UnitOfTemperature,
UnitOfTime,
)
from homeassistant.helpers.entity import EntityDescription
from homeassistant.util import slugify
from .robot_family import RobotFamily


@dataclass(slots=True)
Expand Down
54 changes: 23 additions & 31 deletions custom_components/mydolphin_plus/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@

import logging

import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback

from .common.connectivity_status import ConnectivityStatus
from .common.consts import DEFAULT_NAME, DOMAIN
from .managers.config_manager import ConfigManager
from .managers.rest_api import RestAPI
from .common.consts import DOMAIN
from .managers.flow_manager import IntegrationFlowManager

_LOGGER = logging.getLogger(__name__)

Expand All @@ -26,37 +23,32 @@ class DomainFlowHandler(config_entries.ConfigFlow):
def __init__(self):
super().__init__()

@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return DomainOptionsFlowHandler(config_entry)

async def async_step_user(self, user_input=None):
"""Handle a flow start."""
_LOGGER.debug(f"Starting async_step_user of {DEFAULT_NAME}")

errors = None

if user_input is not None:
config_manager = ConfigManager(self.hass, None)
config_manager.update_credentials(user_input)
flow_manager = IntegrationFlowManager(self.hass, self)

await config_manager.initialize()
return await flow_manager.async_step(user_input)

api = RestAPI(self.hass, config_manager)

await api.validate()
class DomainOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle domain options."""

if api.status == ConnectivityStatus.TemporaryConnected:
_LOGGER.debug("User inputs are valid")
_config_entry: ConfigEntry

user_input[CONF_PASSWORD] = config_manager.password_hashed

return self.async_create_entry(title=DEFAULT_NAME, data=user_input)

else:
_LOGGER.warning("Failed to create integration")
def __init__(self, config_entry: ConfigEntry):
"""Initialize domain options flow."""
super().__init__()

new_user_input = {
vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
}
self._config_entry = config_entry

schema = vol.Schema(new_user_input)
async def async_step_init(self, user_input=None):
"""Manage the domain options."""
flow_manager = IntegrationFlowManager(self.hass, self, self._config_entry)

return self.async_show_form(step_id="user", data_schema=schema, errors=errors)
return await flow_manager.async_step(user_input)
2 changes: 1 addition & 1 deletion custom_components/mydolphin_plus/managers/aws_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
WS_DATA_VERSION,
WS_LAST_UPDATE,
)
from ..common.topic_data import TopicData
from ..models.topic_data import TopicData
from .config_manager import ConfigManager

_LOGGER = logging.getLogger(__name__)
Expand Down
Loading

0 comments on commit d77f23f

Please sign in to comment.