Add RainMachine config option to use default run times from app (#80984)

pull/81062/head
shbatm 2022-10-26 23:27:08 -05:00 committed by GitHub
parent f9c16fab1a
commit e785d04abf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 24 deletions

View File

@ -38,7 +38,9 @@ from homeassistant.util.network import is_ip_address
from .config_flow import get_client_controller
from .const import (
CONF_ZONE_RUN_TIME,
CONF_DEFAULT_ZONE_RUN_TIME,
CONF_DURATION,
CONF_USE_APP_RUN_TIMES,
DATA_API_VERSIONS,
DATA_MACHINE_FIRMWARE_UPDATE_STATUS,
DATA_PROGRAMS,
@ -67,7 +69,6 @@ PLATFORMS = [
CONF_CONDITION = "condition"
CONF_DEWPOINT = "dewpoint"
CONF_DURATION = "duration"
CONF_ET = "et"
CONF_MAXRH = "maxrh"
CONF_MAXTEMP = "maxtemp"
@ -237,15 +238,17 @@ async def async_setup_entry( # noqa: C901
if not entry.unique_id or is_ip_address(entry.unique_id):
# If the config entry doesn't already have a unique ID, set one:
entry_updates["unique_id"] = controller.mac
if CONF_ZONE_RUN_TIME in entry.data:
if CONF_DEFAULT_ZONE_RUN_TIME in entry.data:
# If a zone run time exists in the config entry's data, pop it and move it to
# options:
data = {**entry.data}
entry_updates["data"] = data
entry_updates["options"] = {
**entry.options,
CONF_ZONE_RUN_TIME: data.pop(CONF_ZONE_RUN_TIME),
CONF_DEFAULT_ZONE_RUN_TIME: data.pop(CONF_DEFAULT_ZONE_RUN_TIME),
}
if CONF_USE_APP_RUN_TIMES not in entry.options:
entry_updates["options"] = {**entry.options, CONF_USE_APP_RUN_TIMES: False}
if entry_updates:
hass.config_entries.async_update_entry(entry, **entry_updates)

View File

@ -16,7 +16,13 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import aiohttp_client, config_validation as cv
from .const import CONF_ZONE_RUN_TIME, DEFAULT_PORT, DEFAULT_ZONE_RUN, DOMAIN
from .const import (
CONF_DEFAULT_ZONE_RUN_TIME,
CONF_USE_APP_RUN_TIMES,
DEFAULT_PORT,
DEFAULT_ZONE_RUN,
DOMAIN,
)
@callback
@ -138,8 +144,8 @@ class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
CONF_PASSWORD: user_input[CONF_PASSWORD],
CONF_PORT: user_input[CONF_PORT],
CONF_SSL: user_input.get(CONF_SSL, True),
CONF_ZONE_RUN_TIME: user_input.get(
CONF_ZONE_RUN_TIME, DEFAULT_ZONE_RUN
CONF_DEFAULT_ZONE_RUN_TIME: user_input.get(
CONF_DEFAULT_ZONE_RUN_TIME, DEFAULT_ZONE_RUN
),
},
)
@ -173,9 +179,15 @@ class RainMachineOptionsFlowHandler(config_entries.OptionsFlow):
data_schema=vol.Schema(
{
vol.Optional(
CONF_ZONE_RUN_TIME,
default=self.config_entry.options.get(CONF_ZONE_RUN_TIME),
): cv.positive_int
CONF_DEFAULT_ZONE_RUN_TIME,
default=self.config_entry.options.get(
CONF_DEFAULT_ZONE_RUN_TIME
),
): cv.positive_int,
vol.Optional(
CONF_USE_APP_RUN_TIMES,
default=self.config_entry.options.get(CONF_USE_APP_RUN_TIMES),
): bool,
}
),
)

View File

@ -5,7 +5,9 @@ LOGGER = logging.getLogger(__package__)
DOMAIN = "rainmachine"
CONF_ZONE_RUN_TIME = "zone_run_time"
CONF_DURATION = "duration"
CONF_DEFAULT_ZONE_RUN_TIME = "zone_run_time"
CONF_USE_APP_RUN_TIMES = "use_app_run_times"
DATA_API_VERSIONS = "api.versions"
DATA_MACHINE_FIRMWARE_UPDATE_STATUS = "machine.firmware_update_status"

View File

@ -23,7 +23,8 @@
"init": {
"title": "Configure RainMachine",
"data": {
"zone_run_time": "Default zone run time (in seconds)"
"zone_run_time": "Default zone run time (in seconds)",
"use_app_run_times": "Use zone run times from RainMachine app"
}
}
}

View File

@ -22,8 +22,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import RainMachineData, RainMachineEntity, async_update_programs_and_zones
from .const import (
CONF_ZONE_RUN_TIME,
CONF_DEFAULT_ZONE_RUN_TIME,
CONF_DURATION,
CONF_USE_APP_RUN_TIMES,
DATA_PROGRAMS,
DATA_PROVISION_SETTINGS,
DATA_RESTRICTIONS_UNIVERSAL,
DATA_ZONES,
DEFAULT_ZONE_RUN,
@ -40,6 +43,7 @@ ATTR_AREA = "area"
ATTR_CS_ON = "cs_on"
ATTR_CURRENT_CYCLE = "current_cycle"
ATTR_CYCLES = "cycles"
ATTR_ZONE_RUN_TIME = "zone_run_time_from_app"
ATTR_DELAY = "delay"
ATTR_DELAY_ON = "delay_on"
ATTR_FIELD_CAPACITY = "field_capacity"
@ -186,7 +190,7 @@ async def async_setup_entry(
"start_zone",
{
vol.Optional(
CONF_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN
CONF_DEFAULT_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN
): cv.positive_int
},
"async_start_zone",
@ -459,9 +463,21 @@ class RainMachineZone(RainMachineActivitySwitch):
@raise_on_request_error
async def async_turn_on_when_active(self, **kwargs: Any) -> None:
"""Turn the switch on when its associated activity is active."""
# 1. Use duration parameter if provided from service call
duration = kwargs.get(CONF_DURATION)
if not duration:
if (
self._entry.options[CONF_USE_APP_RUN_TIMES]
and ATTR_ZONE_RUN_TIME in self._attr_extra_state_attributes
):
# 2. Use app's zone-specific default, if enabled and available
duration = self._attr_extra_state_attributes[ATTR_ZONE_RUN_TIME]
else:
# 3. Fall back to global zone default duration
duration = self._entry.options[CONF_DEFAULT_ZONE_RUN_TIME]
await self._data.controller.zones.start(
self.entity_description.uid,
kwargs.get("duration", self._entry.options[CONF_ZONE_RUN_TIME]),
duration,
)
self._update_activities()
@ -497,6 +513,13 @@ class RainMachineZone(RainMachineActivitySwitch):
data["waterSense"]["precipitationRate"], 2
)
if self._entry.options[CONF_USE_APP_RUN_TIMES]:
provision_data = self._data.coordinators[DATA_PROVISION_SETTINGS].data
if zone_durations := provision_data.get("system", {}).get("zoneDuration"):
attrs[ATTR_ZONE_RUN_TIME] = zone_durations[
list(self.coordinator.data).index(self.entity_description.uid)
]
self._attr_extra_state_attributes.update(attrs)

View File

@ -35,10 +35,11 @@
"step": {
"init": {
"data": {
"zone_run_time": "Default zone run time (in seconds)"
"zone_run_time": "Default zone run time (in seconds)",
"use_app_run_times": "Use zone run times from RainMachine app"
},
"title": "Configure RainMachine"
}
}
}
}
}

View File

@ -6,7 +6,11 @@ from regenmaschine.errors import RainMachineError
from homeassistant import config_entries, data_entry_flow, setup
from homeassistant.components import zeroconf
from homeassistant.components.rainmachine import CONF_ZONE_RUN_TIME, DOMAIN
from homeassistant.components.rainmachine import (
CONF_DEFAULT_ZONE_RUN_TIME,
CONF_USE_APP_RUN_TIMES,
DOMAIN,
)
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, CONF_PORT, CONF_SSL
from homeassistant.helpers import entity_registry as er
@ -99,10 +103,14 @@ async def test_options_flow(hass, config, config_entry):
assert result["step_id"] == "init"
result = await hass.config_entries.options.async_configure(
result["flow_id"], user_input={CONF_ZONE_RUN_TIME: 600}
result["flow_id"],
user_input={CONF_DEFAULT_ZONE_RUN_TIME: 600, CONF_USE_APP_RUN_TIMES: False},
)
assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY
assert config_entry.options == {CONF_ZONE_RUN_TIME: 600}
assert config_entry.options == {
CONF_DEFAULT_ZONE_RUN_TIME: 600,
CONF_USE_APP_RUN_TIMES: False,
}
async def test_show_form(hass):
@ -130,7 +138,7 @@ async def test_step_user(hass, config, setup_rainmachine):
CONF_PASSWORD: "password",
CONF_PORT: 8080,
CONF_SSL: True,
CONF_ZONE_RUN_TIME: 600,
CONF_DEFAULT_ZONE_RUN_TIME: 600,
}
@ -238,7 +246,7 @@ async def test_step_homekit_zeroconf_new_controller_when_some_exist(
CONF_PASSWORD: "password",
CONF_PORT: 8080,
CONF_SSL: True,
CONF_ZONE_RUN_TIME: 600,
CONF_DEFAULT_ZONE_RUN_TIME: 600,
}

View File

@ -20,7 +20,7 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach
"port": 8080,
"ssl": True,
},
"options": {},
"options": {"use_app_run_times": False},
"pref_disable_new_entities": False,
"pref_disable_polling": False,
"source": "user",
@ -642,7 +642,7 @@ async def test_entry_diagnostics_failed_controller_diagnostics(
"port": 8080,
"ssl": True,
},
"options": {},
"options": {"use_app_run_times": False},
"pref_disable_new_entities": False,
"pref_disable_polling": False,
"source": "user",