Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config flow for the Flux integration #94394

Closed
wants to merge 75 commits into from
Closed
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
23f4252
flux integration config flow
schelv Jun 4, 2023
058499c
small changes to settings
schelv Jun 10, 2023
8c65780
adapted tests for config flow
schelv Jun 10, 2023
e40ac1b
Merge branch 'home-assistant:dev' into flux-config-flow
schelv Jun 10, 2023
283b5a7
tiny cleanup
schelv Jun 10, 2023
075db45
remove commented code
schelv Jun 10, 2023
b1390f2
update manifest and codeowners
schelv Jun 10, 2023
2064689
add requirements and dependencies to manifest
schelv Jun 10, 2023
4f4faf1
re-added yaml config code
schelv Jun 10, 2023
6836656
removed another piece of code in comments
schelv Jun 10, 2023
1abe7e3
Tried to improve the UI text
schelv Jun 10, 2023
0afee68
Converted test case written by @JakeHillion
schelv Jun 10, 2023
a29cba4
rename file
schelv Jun 10, 2023
26046a5
remove commented code
schelv Jun 10, 2023
5196465
remove UNDEFINED values in config flow
schelv Jun 10, 2023
f064c7f
add config_flow.py tests
schelv Jun 10, 2023
0bbd0a2
Merge branch 'dev' into flux-config-flow
schelv Jun 11, 2023
40f31b0
Merge branch 'dev' into flux-config-flow
schelv Jun 19, 2023
70f1b65
Merge branch 'dev' into flux-config-flow
schelv Jun 25, 2023
60c9ade
Merge branch 'home-assistant:dev' into flux-config-flow
schelv Jun 27, 2023
57076af
Merge branch 'home-assistant:dev' into flux-config-flow
schelv Jun 28, 2023
cec22e9
Merge branch 'dev' into flux-config-flow
schelv Jun 30, 2023
a57a147
Merge branch 'dev' into flux-config-flow
schelv Jul 6, 2023
91f60c0
Merge branch 'dev' into flux-config-flow
schelv Jul 6, 2023
4681a33
Update homeassistant/components/flux/__init__.py
schelv Jul 6, 2023
20d3bf8
Merge branch 'dev' into flux-config-flow
schelv Jul 11, 2023
3cdb8f3
Update homeassistant/components/flux/manifest.json
schelv Jul 11, 2023
89cc458
support multiple flux config entries
schelv Jul 11, 2023
9525e94
remove unneeded test
schelv Jul 11, 2023
aa36dcc
Not adding new feature to yaml config
schelv Jul 11, 2023
e7fd785
Adding warning about yaml config
schelv Jul 11, 2023
088363e
Merge branch 'dev' into flux-config-flow
schelv Jul 11, 2023
222d5cd
Merge branch 'dev' into flux-config-flow
schelv Jul 19, 2023
293c28e
Merge branch 'dev' into flux-config-flow
schelv Jul 21, 2023
60bce27
Merge branch 'dev' into flux-config-flow
schelv Jul 21, 2023
97d45ae
Merge branch 'dev' into flux-config-flow
schelv Jul 22, 2023
f936663
Merge branch 'dev' into flux-config-flow
schelv Jul 22, 2023
fc8fd50
Merge branch 'dev' into flux-config-flow
schelv Jul 23, 2023
fca4c4d
Merge branch 'dev' into flux-config-flow
schelv Jul 29, 2023
fec83d4
remove introduction of new option
schelv Jul 29, 2023
42f5a41
Merge branch 'dev' into flux-config-flow
schelv Jul 29, 2023
a7fe9c1
fix yaml to config entry migration
schelv Jul 29, 2023
c80af29
remove unreachable statement
schelv Jul 29, 2023
7df7e0a
add test for migration of option
schelv Jul 29, 2023
ee23c8e
Merge branch 'dev' into flux-config-flow
schelv Jul 29, 2023
15c05f2
Merge branch 'dev' into flux-config-flow
schelv Aug 6, 2023
964fe03
Merge branch 'dev' into flux-config-flow
schelv Aug 8, 2023
b98bd27
Merge branch 'dev' into flux-config-flow
schelv Aug 12, 2023
b443170
Merge branch 'dev' into flux-config-flow
schelv Sep 18, 2023
2339239
Merge branch 'dev' into flux-config-flow
schelv Sep 19, 2023
c8a0b65
Apply suggestions from code review
schelv Sep 24, 2023
885c79d
Merge branch 'dev' into flux-config-flow
schelv Sep 24, 2023
bf6c3c0
make two defaults constant
schelv Sep 24, 2023
e7eaf7c
apply suggestions
schelv Sep 24, 2023
7df667e
Merge branch 'dev' into flux-config-flow
schelv Sep 24, 2023
e5e53d1
Merge branch 'dev' into flux-config-flow
schelv Sep 24, 2023
a34a8b7
Merge branch 'dev' into flux-config-flow
schelv Sep 27, 2023
a795d54
Merge branch 'dev' into flux-config-flow
schelv Oct 2, 2023
173c258
Merge branch 'dev' into flux-config-flow
schelv Nov 1, 2023
5e870c6
fix
schelv Nov 1, 2023
d4127da
Merge branch 'dev' into flux-config-flow
schelv Nov 5, 2023
295a92f
start and stop time can now be cleared
schelv Nov 9, 2023
f6fc62b
Merge branch 'dev' into flux-config-flow
schelv Nov 9, 2023
eb690b9
Merge branch 'dev' into flux-config-flow
schelv Nov 23, 2023
c5079ee
config entry tests not needed because of migration
schelv Nov 23, 2023
7ac9bf2
Apply suggestions from code review
schelv Nov 27, 2023
0078613
Merge branch 'dev' into flux-config-flow
schelv Nov 27, 2023
3e8cfaa
apply emontnemery's suggestions
schelv Nov 27, 2023
f3972f2
add some data descriptions
schelv Nov 27, 2023
e9c1084
not using get
schelv Nov 29, 2023
b4978bf
Merge branch 'dev' into flux-config-flow
schelv Nov 29, 2023
2cea103
Merge branch 'dev' into flux-config-flow
schelv Dec 2, 2023
bb87af4
use new color temp selector
schelv Dec 2, 2023
4e9537f
Merge branch 'dev' into flux-config-flow
schelv May 17, 2024
ceff06c
attempt to fix checks
schelv May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ build.json @home-assistant/supervisor
/tests/components/flo/ @dmulcahey
/homeassistant/components/flume/ @ChrisMandich @bdraco @jeeftor
/tests/components/flume/ @ChrisMandich @bdraco @jeeftor
/homeassistant/components/flux/ @schelv
/tests/components/flux/ @schelv
/homeassistant/components/flux_led/ @icemanch
/tests/components/flux_led/ @icemanch
/homeassistant/components/forecast_solar/ @klaasnicolaas @frenck
Expand Down
28 changes: 27 additions & 1 deletion homeassistant/components/flux/__init__.py
schelv marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
"""The flux component."""
"""The Flux integration."""
from __future__ import annotations

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

PLATFORMS: list[Platform] = [Platform.SWITCH]


async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)

Check warning on line 13 in homeassistant/components/flux/__init__.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/components/flux/__init__.py#L13

Added line #L13 was not covered by tests


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

entry.async_on_unload(entry.add_update_listener(_async_update_listener))

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)
255 changes: 255 additions & 0 deletions homeassistant/components/flux/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
"""Config flow for Flux integration."""
from __future__ import annotations

import logging
from typing import Any

import voluptuous as vol

from homeassistant import config_entries
from homeassistant.components.light import ATTR_TRANSITION
from homeassistant.config_entries import (
ConfigEntry,
OptionsFlow,
OptionsFlowWithConfigEntry,
)
from homeassistant.const import (
CONF_BRIGHTNESS,
CONF_LIGHTS,
CONF_MODE,
CONF_NAME,
Platform,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.selector import (
BooleanSelector,
ColorTempSelector,
DurationSelector,
EntitySelector,
EntitySelectorConfig,
SelectOptionDict,
SelectSelector,
SelectSelectorConfig,
SelectSelectorMode,
TimeSelector,
)
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.color import (
color_temperature_kelvin_to_mired,
color_temperature_mired_to_kelvin,
)

from .const import (
CONF_ADJUST_BRIGHTNESS,
CONF_INTERVAL,
CONF_START_CT,
CONF_START_TIME,
CONF_STOP_CT,
CONF_STOP_TIME,
CONF_SUNSET_CT,
DEFAULT_INTERVAL_DURATION,
DEFAULT_MODE,
DEFAULT_NAME,
DEFAULT_START_COLOR_TEMP_KELVIN,
DEFAULT_STOP_COLOR_TEMP_KELVIN,
DEFAULT_SUNSET_COLOR_TEMP_KELVIN,
DEFAULT_TRANSITION_DURATION,
DOMAIN,
MODE_MIRED,
MODE_RGB,
MODE_XY,
)
from .switch import CONF_DISABLE_BRIGHTNESS_ADJUST

_LOGGER = logging.getLogger(__name__)

MINIMAL_FLUX_SCHEMA = vol.Schema(
schelv marked this conversation as resolved.
Show resolved Hide resolved
{
vol.Required(CONF_NAME, default=DEFAULT_NAME): str,
vol.Required(CONF_LIGHTS): EntitySelector(
EntitySelectorConfig(domain=Platform.LIGHT, multiple=True)
),
}
)


def default_settings():
"""Return object with the default settings for the Flux integration."""
settings_dict = {}
settings_dict[CONF_START_CT] = DEFAULT_START_COLOR_TEMP_KELVIN
settings_dict[CONF_SUNSET_CT] = DEFAULT_SUNSET_COLOR_TEMP_KELVIN
settings_dict[CONF_STOP_CT] = DEFAULT_STOP_COLOR_TEMP_KELVIN
settings_dict[CONF_ADJUST_BRIGHTNESS] = True
settings_dict[CONF_MODE] = DEFAULT_MODE
settings_dict[CONF_INTERVAL] = DEFAULT_INTERVAL_DURATION
settings_dict[ATTR_TRANSITION] = DEFAULT_TRANSITION_DURATION
return settings_dict
schelv marked this conversation as resolved.
Show resolved Hide resolved


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Flux."""
schelv marked this conversation as resolved.
Show resolved Hide resolved

VERSION = 1

@staticmethod
@callback
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow:
"""Get the options flow for the Flux component."""
return FluxOptionsFlow(config_entry)

async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""

if user_input is not None:
user_input.update(default_settings())
return self.async_create_entry(
title=user_input[CONF_NAME], data={}, options=user_input
)

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

async def async_step_import(self, yaml_config: ConfigType) -> FlowResult:
"""Handle import from configuration.yaml."""
# start with the same default settings as in the UI
entry_options = default_settings()

# remove the old two very similar options
brightness = yaml_config.get(CONF_BRIGHTNESS, False)
disable_brightness_adjust = yaml_config.get(
CONF_DISABLE_BRIGHTNESS_ADJUST, False
)

# combine them into the "new" option
if brightness or disable_brightness_adjust:
entry_options[CONF_ADJUST_BRIGHTNESS] = False

if CONF_INTERVAL in yaml_config:
entry_options[CONF_INTERVAL] = {"seconds": yaml_config[CONF_INTERVAL]}
if ATTR_TRANSITION in yaml_config:
entry_options[ATTR_TRANSITION] = {"seconds": yaml_config[ATTR_TRANSITION]}

if CONF_START_TIME in yaml_config:
entry_options[CONF_START_TIME] = str(yaml_config[CONF_START_TIME])

if CONF_STOP_TIME in yaml_config:
entry_options[CONF_STOP_TIME] = str(yaml_config[CONF_STOP_TIME])

# apply the rest of the remaining options
entry_options[CONF_LIGHTS] = yaml_config[CONF_LIGHTS]
if CONF_MODE in yaml_config:
entry_options[CONF_MODE] = yaml_config[CONF_MODE]
if CONF_START_CT in yaml_config:
entry_options[CONF_START_CT] = yaml_config[CONF_START_CT]
if CONF_SUNSET_CT in yaml_config:
entry_options[CONF_SUNSET_CT] = yaml_config[CONF_SUNSET_CT]
if CONF_STOP_CT in yaml_config:
entry_options[CONF_STOP_CT] = yaml_config[CONF_STOP_CT]
if CONF_NAME in yaml_config:
entry_options[CONF_NAME] = yaml_config[CONF_NAME]

self._async_abort_entries_match(entry_options)
schelv marked this conversation as resolved.
Show resolved Hide resolved

return self.async_create_entry(
title=entry_options.get(CONF_NAME, DEFAULT_NAME),
data={},
options=entry_options,
)


class FluxOptionsFlow(OptionsFlowWithConfigEntry):
"""Handle flux options."""

def convert_mired_to_kelvin(self, user_input):
"""Convert between mireds and kelvins because I can't find the kelvin option for ColorTempSelector."""
schelv marked this conversation as resolved.
Show resolved Hide resolved
user_input[CONF_START_CT] = color_temperature_mired_to_kelvin(
user_input[CONF_START_CT]
)
user_input[CONF_SUNSET_CT] = color_temperature_mired_to_kelvin(
user_input[CONF_SUNSET_CT]
)
user_input[CONF_STOP_CT] = color_temperature_mired_to_kelvin(
user_input[CONF_STOP_CT]
)

return user_input

async def async_step_init(self, user_input=None) -> FlowResult:
"""Configure the options."""
if user_input is not None:
user_input = self.convert_mired_to_kelvin(user_input)

return self.async_create_entry(title=user_input[CONF_NAME], data=user_input)

settings = self._config_entry.options

return self.async_show_form(
step_id="init",
data_schema=vol.Schema(
{
vol.Required(CONF_NAME, default=settings.get(CONF_NAME)): str,
vol.Required(
CONF_LIGHTS, default=settings.get(CONF_LIGHTS)
): EntitySelector(
EntitySelectorConfig(domain=Platform.LIGHT, multiple=True)
),
# times
vol.Optional(
CONF_START_TIME,
description={"suggested_value": settings.get(CONF_START_TIME)},
): TimeSelector(),
vol.Optional(
CONF_STOP_TIME,
description={"suggested_value": settings.get(CONF_STOP_TIME)},
): TimeSelector(),
# colors
vol.Optional(
CONF_START_CT,
default=color_temperature_kelvin_to_mired(
float(settings.get(CONF_START_CT)) # type: ignore[arg-type]
),
): ColorTempSelector(),
vol.Optional(
CONF_SUNSET_CT,
default=color_temperature_kelvin_to_mired(
float(settings.get(CONF_SUNSET_CT)) # type: ignore[arg-type]
),
): ColorTempSelector(),
vol.Optional(
CONF_STOP_CT,
default=color_temperature_kelvin_to_mired(
float(settings.get(CONF_STOP_CT)) # type: ignore[arg-type]
),
): ColorTempSelector(),
# adjust_brightness
vol.Optional(
CONF_ADJUST_BRIGHTNESS,
default=settings.get(CONF_ADJUST_BRIGHTNESS),
): BooleanSelector(),
vol.Optional(
CONF_MODE, default=settings.get(CONF_MODE)
): SelectSelector(
SelectSelectorConfig(
options=[
SelectOptionDict(value=MODE_XY, label=MODE_XY),
SelectOptionDict(value=MODE_MIRED, label=MODE_MIRED),
SelectOptionDict(value=MODE_RGB, label=MODE_RGB),
],
mode=SelectSelectorMode.DROPDOWN,
)
),
# update settings
vol.Optional(
ATTR_TRANSITION, default=settings.get(ATTR_TRANSITION)
): DurationSelector(),
vol.Optional(
CONF_INTERVAL, default=settings.get(CONF_INTERVAL)
): DurationSelector(),
}
),
)
22 changes: 22 additions & 0 deletions homeassistant/components/flux/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Constants for the Flux integration."""

DOMAIN = "flux"
CONF_START_TIME = "start_time"
CONF_STOP_TIME = "stop_time"
CONF_START_CT = "start_colortemp"
CONF_SUNSET_CT = "sunset_colortemp"
CONF_STOP_CT = "stop_colortemp"
CONF_ADJUST_BRIGHTNESS = "adjust_brightness"
CONF_INTERVAL = "interval"

MODE_XY = "xy"
MODE_MIRED = "mired"
MODE_RGB = "rgb"

DEFAULT_NAME = "Flux"
DEFAULT_START_COLOR_TEMP_KELVIN = 4000
DEFAULT_SUNSET_COLOR_TEMP_KELVIN = 3000
DEFAULT_STOP_COLOR_TEMP_KELVIN = 1900
DEFAULT_MODE = MODE_XY
DEFAULT_INTERVAL_DURATION = {"seconds": 30}
DEFAULT_TRANSITION_DURATION = {"seconds": 30}
4 changes: 3 additions & 1 deletion homeassistant/components/flux/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"domain": "flux",
"name": "Flux",
"after_dependencies": ["light"],
"codeowners": [],
"codeowners": ["@schelv"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/flux",
"integration_type": "service",
"iot_class": "calculated",
"quality_scale": "internal"
}
37 changes: 37 additions & 0 deletions homeassistant/components/flux/strings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"config": {
"step": {
"user": {
"description": "Flux will update the temperature and brightness of your lights based on the time of day. During the day they will be bright, and they will gradually dim and fade to a red/orange at night. It will only affect lights that are turned on and listed below.",
"data": {
"name": "A name for your flux configuration",
"lights": "Select the lights you want controlled by Flux"
}
}
},
"error": {
"unknown": "[%key:common::config_flow::error::unknown%]"
}
},
"options": {
"flow_title": "Flux Options",
"step": {
"init": {
"description": "Flux will update the temperature and brightness of your lights based on the time of day. During the day they will be bright, and they will gradually dim and fade to a red/orange at night. It will only affect lights that are turned on and listed below.",
"data": {
"name": "A name for your flux configuration",
"lights": "Select the lights you want controlled by Flux",
"start_time": "Start time. If left empty this will be automatically calculated based on the location.",
schelv marked this conversation as resolved.
Show resolved Hide resolved
"stop_time": "Stop time. If left empty this will be automatically calculated based on the location.",
"start_colortemp": "Start color temperature",
"sunset_colortemp": "Sunset color temperature",
"stop_colortemp": "Stop color temperature",
"adjust_brightness": "Adjust brightness",
"mode": "Select how color temperature is passed to lights",
"transition": "Transition time for the light changes",
"interval": "Time between between consecutive light updates"
}
}
}
}
}
Loading