From 24c45bfd847fd492fa50c41422067984f9780a33 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 11 Apr 2020 19:37:34 -0500 Subject: [PATCH] Restore ability to change the scan interval in the NUT (#33996) * Support changing the scan interval in the NUT options flow * use dict.items() --- .../components/nut/.translations/en.json | 91 +++++++++---------- homeassistant/components/nut/__init__.py | 5 +- homeassistant/components/nut/config_flow.py | 45 ++++++--- homeassistant/components/nut/const.py | 1 + homeassistant/components/nut/strings.json | 3 +- tests/components/nut/test_config_flow.py | 26 +++++- 6 files changed, 106 insertions(+), 65 deletions(-) diff --git a/homeassistant/components/nut/.translations/en.json b/homeassistant/components/nut/.translations/en.json index 939fa7c9cbe..206a1ec299a 100644 --- a/homeassistant/components/nut/.translations/en.json +++ b/homeassistant/components/nut/.translations/en.json @@ -1,50 +1,47 @@ { - "config": { - "abort": { - "already_configured": "Device is already configured" - }, - "error": { - "cannot_connect": "Failed to connect, please try again", - "unknown": "Unexpected error" - }, - "step": { - "resources": { - "data": { - "resources": "Resources" - }, - "title": "Choose the Resources to Monitor" - }, - "ups": { - "data": { - "alias": "Alias", - "resources": "Resources" - }, - "title": "Choose the UPS to Monitor" - }, - "user": { - "data": { - "alias": "Alias", - "host": "Host", - "name": "Name", - "password": "Password", - "port": "Port", - "resources": "Resources", - "username": "Username" - }, - "description": "If there are multiple UPSs attached to the NUT server, enter the name UPS to query in the 'Alias' field.", - "title": "Connect to the NUT server" - } - }, - "title": "Network UPS Tools (NUT)" - }, - "options": { - "step": { - "init": { - "data": { - "resources": "Resources" - }, - "description": "Choose Sensor Resources." - } + "config": { + "title": "Network UPS Tools (NUT)", + "step": { + "user": { + "title": "Connect to the NUT server", + "data": { + "host": "Host", + "port": "Port", + "username": "Username", + "password": "Password" } + }, + "ups": { + "title": "Choose the UPS to Monitor", + "data": { + "alias": "Alias", + "resources": "Resources" + } + }, + "resources": { + "title": "Choose the Resources to Monitor", + "data": { + "resources": "Resources" + } + } + }, + "error": { + "cannot_connect": "Failed to connect, please try again", + "unknown": "Unexpected error" + }, + "abort": { + "already_configured": "Device is already configured" } -} \ No newline at end of file + }, + "options": { + "step": { + "init": { + "description": "Choose Sensor Resources.", + "data": { + "resources": "Resources", + "scan_interval": "Scan Interval (seconds)" + } + } + } + } +} diff --git a/homeassistant/components/nut/__init__.py b/homeassistant/components/nut/__init__.py index 82fc3063693..45c5474f27e 100644 --- a/homeassistant/components/nut/__init__.py +++ b/homeassistant/components/nut/__init__.py @@ -13,6 +13,7 @@ from homeassistant.const import ( CONF_PASSWORD, CONF_PORT, CONF_RESOURCES, + CONF_SCAN_INTERVAL, CONF_USERNAME, ) from homeassistant.core import HomeAssistant @@ -21,6 +22,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import ( COORDINATOR, + DEFAULT_SCAN_INTERVAL, DOMAIN, PLATFORMS, PYNUT_DATA, @@ -52,6 +54,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): alias = config.get(CONF_ALIAS) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) + scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) data = PyNUTData(host, port, alias, username, password) @@ -65,7 +68,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): _LOGGER, name="NUT resource status", update_method=async_update_data, - update_interval=timedelta(seconds=60), + update_interval=timedelta(seconds=scan_interval), ) # Fetch initial data so we have data when entities subscribe diff --git a/homeassistant/components/nut/config_flow.py b/homeassistant/components/nut/config_flow.py index 505fd2a5e4f..f1066fe2899 100644 --- a/homeassistant/components/nut/config_flow.py +++ b/homeassistant/components/nut/config_flow.py @@ -10,19 +10,29 @@ from homeassistant.const import ( CONF_PASSWORD, CONF_PORT, CONF_RESOURCES, + CONF_SCAN_INTERVAL, CONF_USERNAME, ) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from . import PyNUTData, find_resources_in_config_entry -from .const import DEFAULT_HOST, DEFAULT_PORT, SENSOR_TYPES +from .const import ( + DEFAULT_HOST, + DEFAULT_PORT, + DEFAULT_SCAN_INTERVAL, + SENSOR_NAME, + SENSOR_TYPES, +) from .const import DOMAIN # pylint:disable=unused-import _LOGGER = logging.getLogger(__name__) -SENSOR_DICT = {sensor_id: SENSOR_TYPES[sensor_id][0] for sensor_id in SENSOR_TYPES} +SENSOR_DICT = { + sensor_id: sensor_spec[SENSOR_NAME] + for sensor_id, sensor_spec in SENSOR_TYPES.items() +} DATA_SCHEMA = vol.Schema( { @@ -34,22 +44,20 @@ DATA_SCHEMA = vol.Schema( ) -def _resource_schema(available_resources, selected_resources): +def _resource_schema_base(available_resources, selected_resources): """Resource selection schema.""" known_available_resources = { - sensor_id: sensor[0] + sensor_id: sensor[SENSOR_NAME] for sensor_id, sensor in SENSOR_TYPES.items() if sensor_id in available_resources } - return vol.Schema( - { - vol.Required(CONF_RESOURCES, default=selected_resources): cv.multi_select( - known_available_resources - ) - } - ) + return { + vol.Required(CONF_RESOURCES, default=selected_resources): cv.multi_select( + known_available_resources + ) + } def _ups_schema(ups_list): @@ -160,7 +168,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): if user_input is None: return self.async_show_form( step_id="resources", - data_schema=_resource_schema(self.available_resources, []), + data_schema=vol.Schema( + _resource_schema_base(self.available_resources, []) + ), ) self.nut_config.update(user_input) @@ -207,12 +217,19 @@ class OptionsFlowHandler(config_entries.OptionsFlow): return self.async_create_entry(title="", data=user_input) resources = find_resources_in_config_entry(self.config_entry) + scan_interval = self.config_entry.options.get( + CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL + ) info = await validate_input(self.hass, self.config_entry.data) + base_schema = _resource_schema_base(info["available_resources"], resources) + base_schema[ + vol.Optional(CONF_SCAN_INTERVAL, default=scan_interval) + ] = cv.positive_int + return self.async_show_form( - step_id="init", - data_schema=_resource_schema(info["available_resources"], resources), + step_id="init", data_schema=vol.Schema(base_schema), ) diff --git a/homeassistant/components/nut/const.py b/homeassistant/components/nut/const.py index 50217e4b598..b62a413e82b 100644 --- a/homeassistant/components/nut/const.py +++ b/homeassistant/components/nut/const.py @@ -26,6 +26,7 @@ KEY_STATUS = "ups.status" KEY_STATUS_DISPLAY = "ups.status.display" COORDINATOR = "coordinator" +DEFAULT_SCAN_INTERVAL = 60 PYNUT_DATA = "data" PYNUT_UNIQUE_ID = "unique_id" diff --git a/homeassistant/components/nut/strings.json b/homeassistant/components/nut/strings.json index 6519d914df2..206a1ec299a 100644 --- a/homeassistant/components/nut/strings.json +++ b/homeassistant/components/nut/strings.json @@ -38,7 +38,8 @@ "init": { "description": "Choose Sensor Resources.", "data": { - "resources": "Resources" + "resources": "Resources", + "scan_interval": "Scan Interval (seconds)" } } } diff --git a/tests/components/nut/test_config_flow.py b/tests/components/nut/test_config_flow.py index 360d97d13c4..5833d06c8a9 100644 --- a/tests/components/nut/test_config_flow.py +++ b/tests/components/nut/test_config_flow.py @@ -3,7 +3,7 @@ from asynctest import patch from homeassistant import config_entries, data_entry_flow, setup from homeassistant.components.nut.const import DOMAIN -from homeassistant.const import CONF_RESOURCES +from homeassistant.const import CONF_RESOURCES, CONF_SCAN_INTERVAL from .util import _get_mock_pynutclient @@ -244,4 +244,26 @@ async def test_options_flow(hass): ) assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert config_entry.options == {CONF_RESOURCES: ["battery.voltage"]} + assert config_entry.options == { + CONF_RESOURCES: ["battery.voltage"], + CONF_SCAN_INTERVAL: 60, + } + + with patch( + "homeassistant.components.nut.PyNUTClient", return_value=mock_pynut, + ), patch("homeassistant.components.nut.async_setup_entry", return_value=True): + result2 = await hass.config_entries.options.async_init(config_entry.entry_id) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM + assert result2["step_id"] == "init" + + result2 = await hass.config_entries.options.async_configure( + result2["flow_id"], + user_input={CONF_RESOURCES: ["battery.voltage"], CONF_SCAN_INTERVAL: 12}, + ) + + assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + assert config_entry.options == { + CONF_RESOURCES: ["battery.voltage"], + CONF_SCAN_INTERVAL: 12, + }