Add reconfiguration to slide_local (#133182)

Co-authored-by: Joostlek <joostlek@outlook.com>
pull/133141/head^2
dontinelli 2024-12-14 12:10:28 +01:00 committed by GitHub
parent ca1bcbf5d5
commit 06391d4635
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 85 additions and 6 deletions

View File

@ -25,9 +25,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: SlideConfigEntry) -> boo
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener))
return True
async def update_listener(hass: HomeAssistant, entry: SlideConfigEntry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)
async def async_unload_entry(hass: HomeAssistant, entry: SlideConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -15,10 +15,12 @@ from goslideapi.goslideapi import (
import voluptuous as vol
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult, OptionsFlow
from homeassistant.const import CONF_API_VERSION, CONF_HOST, CONF_MAC, CONF_PASSWORD
from homeassistant.core import callback
from homeassistant.helpers.device_registry import format_mac
from . import SlideConfigEntry
from .const import CONF_INVERT_POSITION, DOMAIN
_LOGGER = logging.getLogger(__name__)
@ -34,6 +36,14 @@ class SlideConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1
MINOR_VERSION = 1
@staticmethod
@callback
def async_get_options_flow(
config_entry: SlideConfigEntry,
) -> SlideOptionsFlowHandler:
"""Get the options flow for this handler."""
return SlideOptionsFlowHandler()
async def async_test_connection(
self, user_input: dict[str, str | int]
) -> dict[str, str]:
@ -181,3 +191,26 @@ class SlideConfigFlow(ConfigFlow, domain=DOMAIN):
"host": self._host,
},
)
class SlideOptionsFlowHandler(OptionsFlow):
"""Handle a options flow for slide_local."""
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Manage the options."""
if user_input is not None:
return self.async_create_entry(data=user_input)
return self.async_show_form(
step_id="init",
data_schema=self.add_suggested_values_to_schema(
vol.Schema(
{
vol.Required(CONF_INVERT_POSITION): bool,
}
),
{CONF_INVERT_POSITION: self.config_entry.options[CONF_INVERT_POSITION]},
),
)

View File

@ -54,7 +54,7 @@ class SlideCoverLocal(SlideEntity, CoverEntity):
super().__init__(coordinator)
self._attr_name = None
self._invert = entry.options[CONF_INVERT_POSITION]
self.invert = entry.options[CONF_INVERT_POSITION]
self._attr_unique_id = coordinator.data["mac"]
@property
@ -79,7 +79,7 @@ class SlideCoverLocal(SlideEntity, CoverEntity):
if pos is not None:
if (1 - pos) <= DEFAULT_OFFSET or pos <= DEFAULT_OFFSET:
pos = round(pos)
if not self._invert:
if not self.invert:
pos = 1 - pos
pos = int(pos * 100)
return pos
@ -101,7 +101,7 @@ class SlideCoverLocal(SlideEntity, CoverEntity):
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
position = kwargs[ATTR_POSITION] / 100
if not self._invert:
if not self.invert:
position = 1 - position
if self.coordinator.data["pos"] is not None:

View File

@ -33,7 +33,7 @@ rules:
test-coverage: todo
integration-owner: done
docs-installation-parameters: done
docs-configuration-parameters: todo
docs-configuration-parameters: done
# Gold
entity-translations: todo

View File

@ -27,6 +27,20 @@
"unknown": "[%key:common::config_flow::error::unknown%]"
}
},
"options": {
"step": {
"init": {
"title": "Configure Slide",
"description": "Reconfigure the Slide device",
"data": {
"invert_position": "Invert position"
},
"data_description": {
"invert_position": "Invert the position of your slide cover."
}
}
}
},
"exceptions": {
"update_error": {
"message": "Error while updating data from the API."

View File

@ -14,10 +14,11 @@ import pytest
from homeassistant.components.slide_local.const import CONF_INVERT_POSITION, DOMAIN
from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
from homeassistant.const import CONF_API_VERSION, CONF_HOST, CONF_PASSWORD
from homeassistant.const import CONF_API_VERSION, CONF_HOST, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from . import setup_platform
from .const import HOST, SLIDE_INFO_DATA
from tests.common import MockConfigEntry
@ -371,3 +372,27 @@ async def test_zeroconf_connection_error(
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "discovery_connection_failed"
async def test_options_flow(
hass: HomeAssistant, mock_slide_api: AsyncMock, mock_config_entry: MockConfigEntry
) -> None:
"""Test options flow works correctly."""
await setup_platform(hass, mock_config_entry, [Platform.COVER])
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "init"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_INVERT_POSITION: True,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert mock_config_entry.options == {
CONF_INVERT_POSITION: True,
}