* First cut of Rollease Acmeda Pulse Hub integration. * Acmeda integration improvements: - Moved common code into a base entity - Battery level sensor added - Localisation now working * Added requirement for aiopulse now that it has been uploaded to PyPI. * Exclude acmeda integration from coverage check as it relies on a hub being present. * Fix Travis CI build issues. * Remove unused constants. * Remove unused group logic from cover.py * Removed commented code from base.py * Remove sensors (battery entities) on removal of hub. * Remove unused groups from sensor.py * Acmeda device and entity update made fully asynchronous using subscriptions to remove need for config polling. * Updated aiopulse version dependency. Removed non-functional battery charging indication. * Rationalised common code to update entities into helpers.py * Fix linting issue. * Correct additional CI pylint errors. * Index config_entries by entry_id. Move entity loading and unloading to __init__.py Add entry_id to dispatcher signal Removed now unused polling code hub Added config_flow unit tests * Tweak to integration config_entry title. * Bumped aiopulse module to 0.3.2. Reduced verbosity of aiopulse module. * Changed to using direct write of device state. Removed old style async_step_init config_flow step. * Remove superfluous battery_level and device_state_attributes from battery entity. * Removal of unused strings. Removal of unused create_config_flow helper. Removal of stale comment. * Remove use of shared container to track existing enities. Moved removal and deregistration of entities to base class through use of dispatch helper. * Fixed strings.json * Fix incorrect use of remove instead of pop on dict. * Add support for tilting covers, bump aiopulse version number. * Bump aiopulse version to v0.3.4. Fixed bug in cover supported_features. * Bumped aiopulse version to 0.4.0 Update acmeda .coveragerc exclusions * Removed already configured hub check from __init__.py async_setup_entry Removed passing in hass reference to base entity class Renamed entity async_reset to async_will_remove_from_hass Changed device_info and properties Migrated to CoveEntity from CoverDevice Added dispatched_connect cleanup on hub removal Removed unused entries from manifest Removed override of battery icon Renamed translations folder * Reversed unintended change to .coveragerc * Fixed config flow for multi-hub discovery. * Acmeda enhancements as requested by MartinHjelmare * Force import to connect to hub to retrieve id prior to creating entry * Remove YAML configuration support. * Tidied up config_flow and tests: - removed unnecessary steps - fixed typos * Removed storage of hub in config_flow.
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Config flow for Rollease Acmeda Automate Pulse Hub."""
|
|
import asyncio
|
|
from typing import Dict, Optional
|
|
|
|
import aiopulse
|
|
import async_timeout
|
|
import voluptuous as vol
|
|
|
|
from homeassistant import config_entries
|
|
|
|
from .const import DOMAIN # pylint: disable=unused-import
|
|
|
|
|
|
class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|
"""Handle a Acmeda config flow."""
|
|
|
|
VERSION = 1
|
|
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
|
|
|
def __init__(self):
|
|
"""Initialize the config flow."""
|
|
self.discovered_hubs: Optional[Dict[str, aiopulse.Hub]] = None
|
|
|
|
async def async_step_user(self, user_input=None):
|
|
"""Handle a flow initialized by the user."""
|
|
if (
|
|
user_input is not None
|
|
and self.discovered_hubs is not None
|
|
# pylint: disable=unsupported-membership-test
|
|
and user_input["id"] in self.discovered_hubs
|
|
):
|
|
# pylint: disable=unsubscriptable-object
|
|
return await self.async_create(self.discovered_hubs[user_input["id"]])
|
|
|
|
# Already configured hosts
|
|
already_configured = {
|
|
entry.unique_id for entry in self._async_current_entries()
|
|
}
|
|
|
|
hubs = []
|
|
try:
|
|
with async_timeout.timeout(5):
|
|
async for hub in aiopulse.Hub.discover():
|
|
if hub.id not in already_configured:
|
|
hubs.append(hub)
|
|
except asyncio.TimeoutError:
|
|
pass
|
|
|
|
if len(hubs) == 0:
|
|
return self.async_abort(reason="all_configured")
|
|
|
|
if len(hubs) == 1:
|
|
return await self.async_create(hubs[0])
|
|
|
|
self.discovered_hubs = {hub.id: hub for hub in hubs}
|
|
|
|
return self.async_show_form(
|
|
step_id="user",
|
|
data_schema=vol.Schema(
|
|
{
|
|
vol.Required("id"): vol.In(
|
|
{hub.id: f"{hub.id} {hub.host}" for hub in hubs}
|
|
)
|
|
}
|
|
),
|
|
)
|
|
|
|
async def async_create(self, hub):
|
|
"""Create the Acmeda Hub entry."""
|
|
await self.async_set_unique_id(hub.id, raise_on_progress=False)
|
|
return self.async_create_entry(title=hub.id, data={"host": hub.host})
|