mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Add ability to edit sensors in scrape config flow (#82926)
* Add ability to edit sensors in scrape config flow * Fix docstring * Update homeassistant/components/scrape/config_flow.py Co-authored-by: Erik Montnemery <erik@montnemery.com> * docstring Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
92fef0f2ba
commit
cbf8a41eed
@ -87,7 +87,6 @@ RESOURCE_SETUP = {
|
||||
}
|
||||
|
||||
SENSOR_SETUP = {
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): TextSelector(),
|
||||
vol.Required(CONF_SELECT): TextSelector(),
|
||||
vol.Optional(CONF_INDEX, default=0): NumberSelector(
|
||||
NumberSelectorConfig(min=0, step=1, mode=NumberSelectorMode.BOX)
|
||||
@ -146,6 +145,49 @@ async def validate_sensor_setup(
|
||||
return {}
|
||||
|
||||
|
||||
async def validate_select_sensor(
|
||||
handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Store sensor index in flow state."""
|
||||
handler.flow_state["_idx"] = int(user_input[CONF_INDEX])
|
||||
return {}
|
||||
|
||||
|
||||
async def get_select_sensor_schema(handler: SchemaCommonFlowHandler) -> vol.Schema:
|
||||
"""Return schema for selecting a sensor."""
|
||||
return vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_INDEX): vol.In(
|
||||
{
|
||||
str(index): config[CONF_NAME]
|
||||
for index, config in enumerate(handler.options[SENSOR_DOMAIN])
|
||||
},
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def get_edit_sensor_suggested_values(
|
||||
handler: SchemaCommonFlowHandler,
|
||||
) -> dict[str, Any]:
|
||||
"""Return suggested values for sensor editing."""
|
||||
idx: int = handler.flow_state["_idx"]
|
||||
return handler.options[SENSOR_DOMAIN][idx]
|
||||
|
||||
|
||||
async def validate_sensor_edit(
|
||||
handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Update edited sensor."""
|
||||
user_input[CONF_INDEX] = int(user_input[CONF_INDEX])
|
||||
|
||||
# Standard behavior is to merge the result with the options.
|
||||
# In this case, we want to add a sub-item so we update the options directly.
|
||||
idx: int = handler.flow_state["_idx"]
|
||||
handler.options[SENSOR_DOMAIN][idx].update(user_input)
|
||||
return {}
|
||||
|
||||
|
||||
async def get_remove_sensor_schema(handler: SchemaCommonFlowHandler) -> vol.Schema:
|
||||
"""Return schema for sensor removal."""
|
||||
return vol.Schema(
|
||||
@ -183,7 +225,13 @@ async def validate_remove_sensor(
|
||||
|
||||
|
||||
DATA_SCHEMA_RESOURCE = vol.Schema(RESOURCE_SETUP)
|
||||
DATA_SCHEMA_SENSOR = vol.Schema(SENSOR_SETUP)
|
||||
DATA_SCHEMA_EDIT_SENSOR = vol.Schema(SENSOR_SETUP)
|
||||
DATA_SCHEMA_SENSOR = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): TextSelector(),
|
||||
**SENSOR_SETUP,
|
||||
}
|
||||
)
|
||||
|
||||
CONFIG_FLOW = {
|
||||
"user": SchemaFlowFormStep(
|
||||
@ -197,7 +245,9 @@ CONFIG_FLOW = {
|
||||
),
|
||||
}
|
||||
OPTIONS_FLOW = {
|
||||
"init": SchemaFlowMenuStep(["resource", "add_sensor", "remove_sensor"]),
|
||||
"init": SchemaFlowMenuStep(
|
||||
["resource", "add_sensor", "select_edit_sensor", "remove_sensor"]
|
||||
),
|
||||
"resource": SchemaFlowFormStep(
|
||||
DATA_SCHEMA_RESOURCE,
|
||||
validate_user_input=validate_rest_setup,
|
||||
@ -207,6 +257,17 @@ OPTIONS_FLOW = {
|
||||
suggested_values=None,
|
||||
validate_user_input=validate_sensor_setup,
|
||||
),
|
||||
"select_edit_sensor": SchemaFlowFormStep(
|
||||
get_select_sensor_schema,
|
||||
suggested_values=None,
|
||||
validate_user_input=validate_select_sensor,
|
||||
next_step="edit_sensor",
|
||||
),
|
||||
"edit_sensor": SchemaFlowFormStep(
|
||||
DATA_SCHEMA_EDIT_SENSOR,
|
||||
suggested_values=get_edit_sensor_suggested_values,
|
||||
validate_user_input=validate_sensor_edit,
|
||||
),
|
||||
"remove_sensor": SchemaFlowFormStep(
|
||||
get_remove_sensor_schema,
|
||||
suggested_values=None,
|
||||
|
@ -54,6 +54,7 @@
|
||||
"init": {
|
||||
"menu_options": {
|
||||
"add_sensor": "Add sensor",
|
||||
"select_edit_sensor": "Configure sensor",
|
||||
"remove_sensor": "Remove sensor",
|
||||
"resource": "Configure resource"
|
||||
}
|
||||
@ -79,6 +80,27 @@
|
||||
"unit_of_measurement": "[%key:component::scrape::config::step::sensor::data_description::unit_of_measurement%]"
|
||||
}
|
||||
},
|
||||
"edit_sensor": {
|
||||
"data": {
|
||||
"name": "[%key:component::scrape::config::step::sensor::data::name%]",
|
||||
"attribute": "[%key:component::scrape::config::step::sensor::data::attribute%]",
|
||||
"index": "[%key:component::scrape::config::step::sensor::data::index%]",
|
||||
"select": "[%key:component::scrape::config::step::sensor::data::select%]",
|
||||
"value_template": "[%key:component::scrape::config::step::sensor::data::value_template%]",
|
||||
"device_class": "[%key:component::scrape::config::step::sensor::data::device_class%]",
|
||||
"state_class": "[%key:component::scrape::config::step::sensor::data::state_class%]",
|
||||
"unit_of_measurement": "[%key:component::scrape::config::step::sensor::data::unit_of_measurement%]"
|
||||
},
|
||||
"data_description": {
|
||||
"select": "[%key:component::scrape::config::step::sensor::data_description::select%]",
|
||||
"attribute": "[%key:component::scrape::config::step::sensor::data_description::attribute%]",
|
||||
"index": "[%key:component::scrape::config::step::sensor::data_description::index%]",
|
||||
"value_template": "[%key:component::scrape::config::step::sensor::data_description::value_template%]",
|
||||
"device_class": "[%key:component::scrape::config::step::sensor::data_description::device_class%]",
|
||||
"state_class": "[%key:component::scrape::config::step::sensor::data_description::state_class%]",
|
||||
"unit_of_measurement": "[%key:component::scrape::config::step::sensor::data_description::unit_of_measurement%]"
|
||||
}
|
||||
},
|
||||
"resource": {
|
||||
"data": {
|
||||
"resource": "[%key:component::scrape::config::step::user::data::resource%]",
|
||||
|
@ -78,26 +78,31 @@
|
||||
"value_template": "Defines a template to get the state of the sensor"
|
||||
}
|
||||
},
|
||||
"init": {
|
||||
"edit_sensor": {
|
||||
"data": {
|
||||
"authentication": "Select authentication method",
|
||||
"headers": "Headers",
|
||||
"method": "Method",
|
||||
"password": "Password",
|
||||
"resource": "Resource",
|
||||
"timeout": "Timeout",
|
||||
"username": "Username",
|
||||
"verify_ssl": "Verify SSL certificate"
|
||||
"attribute": "Attribute",
|
||||
"device_class": "Device Class",
|
||||
"index": "Index",
|
||||
"name": "Name",
|
||||
"select": "Select",
|
||||
"state_class": "State Class",
|
||||
"unit_of_measurement": "Unit of Measurement",
|
||||
"value_template": "Value Template"
|
||||
},
|
||||
"data_description": {
|
||||
"authentication": "Type of the HTTP authentication. Either basic or digest",
|
||||
"headers": "Headers to use for the web request",
|
||||
"resource": "The URL to the website that contains the value",
|
||||
"timeout": "Timeout for connection to website",
|
||||
"verify_ssl": "Enables/disables verification of SSL/TLS certificate, for example if it is self-signed"
|
||||
},
|
||||
"attribute": "Get value of an attribute on the selected tag",
|
||||
"device_class": "The type/class of the sensor to set the icon in the frontend",
|
||||
"index": "Defines which of the elements returned by the CSS selector to use",
|
||||
"select": "Defines what tag to search for. Check Beautifulsoup CSS selectors for details",
|
||||
"state_class": "The state_class of the sensor",
|
||||
"unit_of_measurement": "Choose temperature measurement or create your own",
|
||||
"value_template": "Defines a template to get the state of the sensor"
|
||||
}
|
||||
},
|
||||
"init": {
|
||||
"menu_options": {
|
||||
"add_sensor": "Add sensor",
|
||||
"select_edit_sensor": "Configure sensor",
|
||||
"remove_sensor": "Remove sensor",
|
||||
"resource": "Configure resource"
|
||||
}
|
||||
|
@ -356,3 +356,69 @@ async def test_options_add_remove_sensor_flow(
|
||||
# Check the state of the new entity
|
||||
state = hass.states.get("sensor.template")
|
||||
assert state.state == "Trying to get"
|
||||
|
||||
|
||||
async def test_options_edit_sensor_flow(
|
||||
hass: HomeAssistant, loaded_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test options flow to edit a sensor."""
|
||||
|
||||
state = hass.states.get("sensor.current_version")
|
||||
assert state.state == "Current Version: 2021.12.10"
|
||||
|
||||
result = await hass.config_entries.options.async_init(loaded_entry.entry_id)
|
||||
|
||||
assert result["type"] == FlowResultType.MENU
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
{"next_step_id": "select_edit_sensor"},
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "select_edit_sensor"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
{"index": "0"},
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["step_id"] == "edit_sensor"
|
||||
|
||||
mocker = MockRestData("test_scrape_sensor2")
|
||||
with patch("homeassistant.components.rest.RestData", return_value=mocker):
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_SELECT: "template",
|
||||
CONF_INDEX: 0.0,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["data"] == {
|
||||
CONF_RESOURCE: "https://www.home-assistant.io",
|
||||
CONF_METHOD: "GET",
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_TIMEOUT: 10,
|
||||
"sensor": [
|
||||
{
|
||||
CONF_NAME: "Current version",
|
||||
CONF_SELECT: "template",
|
||||
CONF_INDEX: 0,
|
||||
CONF_UNIQUE_ID: "3699ef88-69e6-11ed-a1eb-0242ac120002",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check the entity was updated
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# Check the state of the entity has changed as expected
|
||||
state = hass.states.get("sensor.current_version")
|
||||
assert state.state == "Trying to get"
|
||||
|
Loading…
x
Reference in New Issue
Block a user