Skip to content

Commit

Permalink
Move configuration to config_flow (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
zpieslak authored Nov 12, 2024
1 parent c385ba5 commit 03caba3
Show file tree
Hide file tree
Showing 14 changed files with 531 additions and 237 deletions.
21 changes: 6 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This integration allows you to control Mobilus Cosmo GTW devices from Home Assis

## Prerequisites

- Home Assistant installation.
- Local access to the Mobilus Cosmo GTW IP address and valid login credentials.
- Home Assistant installation version `2024.4.0` or later (earlier versions are available in older releases - see `hacs.json` for details).
- Local access to the Mobilus Cosmo GTW IP address and valid login credentials. Internet access is not required and can be disabled on the Mobilus Cosmo GTW device.

## Installation

Expand All @@ -31,25 +31,16 @@ cp -r custom_components/mobilus /var/lib/home_assistant/custom_components/

## Configuration

Add the following to your `configuration.yaml` file:
Once installed, add the integration to your Home Assistant instance through UI (Settings -> Devices & Services -> Add Integration -> Mobilus COSMO GTW) and follow the UI configure setup.

```yaml
cover:
- platform: mobilus
host: MOBILUS_COSMO_GTW_IP
username: MOBILUS_COSMO_GTW_USERNAME
password: MOBILUS_COSMO_GTW_PASSWORD
```
If needed the setup can be reconfigured through "Reconfigure" in the integration settings.

Example:
Example configuration:

```yaml
cover:
- platform: mobilus
host: 192.168.2.1
username: admin
password: mypassword
```


## Caveats

Expand Down
73 changes: 73 additions & 0 deletions custom_components/mobilus/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from __future__ import annotations

import json
import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from mobilus_client.app import App as MobilusClientApp
from mobilus_client.config import Config as MobilusClientConfig

from .const import DOMAIN, PLATFORMS, SUPPORTED_DEVICES
from .coordinator import MobilusCoordinator

_LOGGER = logging.getLogger(__name__)

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})

client_config = MobilusClientConfig(
gateway_host=entry.data["host"],
user_login=entry.data["username"],
user_password=entry.data["password"],
)
client = MobilusClientApp(client_config)

# Retrieve devices list
response = await hass.async_add_executor_job(
lambda: json.loads(client.call([("devices_list", {})])),
)

if not response:
_LOGGER.warning("No devices found in response.")
return False

devices = response[0].get("devices", [])

if not devices:
_LOGGER.warning("No devices found in the devices list.")
return False

# Currently non cover devices are not supported
supported_devices = [
device for device in devices
if device["type"] in SUPPORTED_DEVICES
]

if not supported_devices:
_LOGGER.warning("No supported devices found in the devices list.")
return False

coordinator = MobilusCoordinator(hass, client)

hass.data[DOMAIN][entry.entry_id] = {
"client": client,
"coordinator": coordinator,
"devices": supported_devices,
}

await coordinator.async_config_entry_first_refresh()
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)

return unload_ok
53 changes: 53 additions & 0 deletions custom_components/mobilus/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from __future__ import annotations

from typing import Any

import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult

from .const import DOMAIN


class MobilusConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1

async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
if user_input is not None:
return self.async_create_entry(
title=user_input["host"],
data=user_input,
)

return self.async_show_form(
step_id="user",
data_schema=self._data_schema(),
)

async def async_step_reconfigure(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult:
reconfigure_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"],
)

if reconfigure_entry is None:
return self.async_abort(reason="entry_not_found")

if user_input is not None:
return self.async_update_reload_and_abort(
entry=reconfigure_entry,
data=user_input,
reason="reconfigure_successful",
)

return self.async_show_form(
step_id="reconfigure",
data_schema=self._data_schema(dict(reconfigure_entry.data)),
)

def _data_schema(self, defaults: dict[str, Any] | None = None) -> vol.Schema:
defaults = defaults or {}

return vol.Schema({
vol.Required("host", default=defaults.get("host", None)): str,
vol.Required("username", default=defaults.get("username", None)): str,
vol.Required("password", default=defaults.get("password", None)): str,
})
4 changes: 4 additions & 0 deletions custom_components/mobilus/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from homeassistant.const import Platform

from .device import MobilusDevice

DOMAIN = "mobilus"

PLATFORMS = [Platform.COVER]

NOT_SUPPORTED_DEVICES = (
MobilusDevice.CGR,
MobilusDevice.SWITCH,
Expand Down
73 changes: 14 additions & 59 deletions custom_components/mobilus/cover.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,34 @@
from __future__ import annotations

import asyncio
import json
import logging
from typing import TYPE_CHECKING, Any

import voluptuous
from homeassistant.components.cover import CoverDeviceClass, CoverEntity, CoverEntityFeature
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import config_validation
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from mobilus_client.app import App as MobilusClientApp
from mobilus_client.config import Config as MobilusClientConfig

from .const import DOMAIN, POSITION_SUPPORTED_DEVICES, SUPPORTED_DEVICES
from .const import DOMAIN, POSITION_SUPPORTED_DEVICES
from .coordinator import MobilusCoordinator

if TYPE_CHECKING:
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from mobilus_client.app import App as MobilusClientApp

_LOGGER = logging.getLogger(__name__)

PLATFORM_SCHEMA = voluptuous.Schema(
{
voluptuous.Required(CONF_HOST): config_validation.string,
voluptuous.Required(CONF_USERNAME): config_validation.string,
voluptuous.Required(CONF_PASSWORD): config_validation.string,
},
extra=voluptuous.ALLOW_EXTRA,
)

async def async_setup_platform(
async def async_setup_entry(
hass: HomeAssistant,
config: ConfigType,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
_discovery_info: DiscoveryInfoType | None = None,
) -> None:

client_config = MobilusClientConfig(
gateway_host=config[CONF_HOST],
user_login=config[CONF_USERNAME],
user_password=config[CONF_PASSWORD],
)
client = MobilusClientApp(client_config)

# Retrieve devices list
response = await hass.async_add_executor_job(
lambda: json.loads(client.call([("devices_list", {})])),
)

if not response:
_LOGGER.warning("No devices found in response. Exiting platform setup.")
return

devices = response[0].get("devices", [])

if not devices:
_LOGGER.warning("No devices found in the devices list.")
return

# Currently non cover devices are not supported
supported_devices = [
device for device in devices
if device["type"] in SUPPORTED_DEVICES
]

if not supported_devices:
_LOGGER.warning("No supported devices found in the devices list.")
return

coordinator = MobilusCoordinator(hass, client)
await coordinator.async_config_entry_first_refresh()
client = hass.data[DOMAIN][entry.entry_id]["client"]
devices = hass.data[DOMAIN][entry.entry_id]["devices"]
coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]

async_add_entities(
[MobilusCover(device, client, coordinator) for device in supported_devices],
[MobilusCover(device, client, coordinator) for device in devices],
)

class MobilusCover(CoordinatorEntity[MobilusCoordinator], CoverEntity):
Expand Down Expand Up @@ -168,6 +121,8 @@ async def async_set_cover_position(self, **kwargs: Any) -> None: # noqa: ANN401
await self.coordinator.async_request_refresh()

async def async_added_to_hass(self) -> None:
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state),
)
# Add a listener to the coordinator to update the entity's state on data changes
coordinator_listener = self.coordinator.async_add_listener(self.async_write_ha_state)

# Register the listener for cleanup when the entity is removed from Home Assistant
self.async_on_remove(coordinator_listener)
3 changes: 2 additions & 1 deletion custom_components/mobilus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
"codeowners": [
"@zpieslak"
],
"config_flow": true,
"dependencies": [],
"documentation": "https://github.com/zpieslak/mobilus-client-home-assistant",
"integration_type": "hub",
"iot_class": "local_polling",
"issue_tracker": "https://github.com/zpieslak/mobilus-client-home-assistant/issues",
"requirements": [
"mobilus-client==0.1.5"
"mobilus-client>=0.1.5"
],
"version": "0.1.0"
}
28 changes: 28 additions & 0 deletions custom_components/mobilus/strings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"config": {
"step": {
"user": {
"title": "Connect to Mobilus COSMO GTW",
"description": "Please enter your Mobilus COSMO GTW host and credentials.",
"data": {
"host": "IP Address / Host",
"username": "Username",
"password": "Password"
}
},
"reconfigure": {
"title": "Reconfigure Mobilus COSMO GTW",
"description": "Please enter your Mobilus COSMO GTW host and credentials.",
"data": {
"host": "IP Address / Host",
"username": "Username",
"password": "Password"
}
}
},
"error": {
"entry_not_found": "Configuration entry not found.",
"reconfigure_successful": "Reconfiguration has been saved. If the data is incorrect, please enter the correct data again."
}
}
}
28 changes: 28 additions & 0 deletions custom_components/mobilus/translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"config": {
"step": {
"user": {
"title": "Connect to Mobilus COSMO GTW",
"description": "Please enter your Mobilus COSMO GTW host and credentials.",
"data": {
"host": "IP Address / Host",
"username": "Username",
"password": "Password"
}
},
"reconfigure": {
"title": "Reconfigure Mobilus COSMO GTW",
"description": "Please enter your Mobilus COSMO GTW host and credentials.",
"data": {
"host": "IP Address / Host",
"username": "Username",
"password": "Password"
}
}
},
"error": {
"entry_not_found": "Configuration entry not found.",
"reconfigure_successful": "Reconfiguration has been saved. If the data is incorrect, please enter the correct data again."
}
}
}
28 changes: 28 additions & 0 deletions custom_components/mobilus/translations/pl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"config": {
"step": {
"user": {
"title": "Podaj dane połączenia",
"description": "Proszę podać dane do połączenia z bramką Mobilus COSMO GTW.",
"data": {
"host": "Adres IP / Host",
"username": "Nazwa użytkownika",
"password": "Hasło"
}
},
"reconfigure": {
"title": "Zmień dane połączenia",
"description": "Proszę podać dane do połączenia z bramką Mobilus COSMO GTW.",
"data": {
"host": "Adres IP / Host",
"username": "Nazwa użytkownika",
"password": "Hasło"
}
}
},
"error": {
"entry_not_found": "Konfiguracja nie została znaleziona.",
"reconfigure_successful": "Ponowna konfiguracja została zapisana. W przypadku błędnych danych, proszę ponownie wprowadzić poprawne dane."
}
}
}
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "Mobilus Cosmo GTW",
"homeassistant": "2022.5.0"
"homeassistant": "2024.4.0"
}
Loading

0 comments on commit 03caba3

Please sign in to comment.