mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Fix import on File config entry and other improvements (#117210)
* Address comments * Remove Name option for File based sensor * Make sure platform schema is applied
This commit is contained in:
parent
c971d08454
commit
606a2848db
@ -12,6 +12,13 @@ from homeassistant.helpers import (
|
|||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
from .notify import PLATFORM_SCHEMA as NOTIFY_PLATFORM_SCHEMA
|
||||||
|
from .sensor import PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA
|
||||||
|
|
||||||
|
IMPORT_SCHEMA = {
|
||||||
|
Platform.SENSOR: SENSOR_PLATFORM_SCHEMA,
|
||||||
|
Platform.NOTIFY: NOTIFY_PLATFORM_SCHEMA,
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
||||||
|
|
||||||
@ -23,6 +30,7 @@ YAML_PLATFORMS = [Platform.NOTIFY, Platform.SENSOR]
|
|||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up the file integration."""
|
"""Set up the file integration."""
|
||||||
|
|
||||||
|
hass.data[DOMAIN] = config
|
||||||
if hass.config_entries.async_entries(DOMAIN):
|
if hass.config_entries.async_entries(DOMAIN):
|
||||||
# We skip import in case we already have config entries
|
# We skip import in case we already have config entries
|
||||||
return True
|
return True
|
||||||
@ -51,12 +59,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
for domain, items in platforms_config.items():
|
for domain, items in platforms_config.items():
|
||||||
for item in items:
|
for item in items:
|
||||||
if item[CONF_PLATFORM] == DOMAIN:
|
if item[CONF_PLATFORM] == DOMAIN:
|
||||||
item[CONF_PLATFORM] = domain
|
file_config_item = IMPORT_SCHEMA[domain](item)
|
||||||
|
file_config_item[CONF_PLATFORM] = domain
|
||||||
hass.async_create_task(
|
hass.async_create_task(
|
||||||
hass.config_entries.flow.async_init(
|
hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
context={"source": SOURCE_IMPORT},
|
context={"source": SOURCE_IMPORT},
|
||||||
data=item,
|
data=file_config_item,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -90,7 +99,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
Platform.NOTIFY,
|
Platform.NOTIFY,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
config,
|
config,
|
||||||
{},
|
hass.data[DOMAIN],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ TEXT_SELECTOR = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT))
|
|||||||
|
|
||||||
FILE_SENSOR_SCHEMA = vol.Schema(
|
FILE_SENSOR_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): TEXT_SELECTOR,
|
|
||||||
vol.Required(CONF_FILE_PATH): TEXT_SELECTOR,
|
vol.Required(CONF_FILE_PATH): TEXT_SELECTOR,
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): TEMPLATE_SELECTOR,
|
vol.Optional(CONF_VALUE_TEMPLATE): TEMPLATE_SELECTOR,
|
||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): TEXT_SELECTOR,
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): TEXT_SELECTOR,
|
||||||
@ -99,8 +98,7 @@ class FileConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
if not await self.validate_file_path(user_input[CONF_FILE_PATH]):
|
if not await self.validate_file_path(user_input[CONF_FILE_PATH]):
|
||||||
errors[CONF_FILE_PATH] = "not_allowed"
|
errors[CONF_FILE_PATH] = "not_allowed"
|
||||||
else:
|
else:
|
||||||
name: str = user_input.get(CONF_NAME, DEFAULT_NAME)
|
title = f"{DEFAULT_NAME} [{user_input[CONF_FILE_PATH]}]"
|
||||||
title = f"{name} [{user_input[CONF_FILE_PATH]}]"
|
|
||||||
return self.async_create_entry(data=user_input, title=title)
|
return self.async_create_entry(data=user_input, title=title)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
|
@ -76,7 +76,7 @@ class FileNotificationService(BaseNotificationService):
|
|||||||
else:
|
else:
|
||||||
text = f"{message}\n"
|
text = f"{message}\n"
|
||||||
file.write(text)
|
file.write(text)
|
||||||
except Exception as exc:
|
except OSError as exc:
|
||||||
raise ServiceValidationError(
|
raise ServiceValidationError(
|
||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key="write_access_failed",
|
translation_key="write_access_failed",
|
||||||
|
@ -21,7 +21,6 @@ from homeassistant.helpers import config_validation as cv
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.template import Template
|
from homeassistant.helpers.template import Template
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.util import slugify
|
|
||||||
|
|
||||||
from .const import DEFAULT_NAME, FILE_ICON
|
from .const import DEFAULT_NAME, FILE_ICON
|
||||||
|
|
||||||
@ -59,14 +58,17 @@ async def async_setup_entry(
|
|||||||
"""Set up the file sensor."""
|
"""Set up the file sensor."""
|
||||||
config = dict(entry.data)
|
config = dict(entry.data)
|
||||||
file_path: str = config[CONF_FILE_PATH]
|
file_path: str = config[CONF_FILE_PATH]
|
||||||
name: str = config[CONF_NAME]
|
unique_id: str = entry.entry_id
|
||||||
|
name: str = config.get(CONF_NAME, DEFAULT_NAME)
|
||||||
unit: str | None = config.get(CONF_UNIT_OF_MEASUREMENT)
|
unit: str | None = config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||||
value_template: Template | None = None
|
value_template: Template | None = None
|
||||||
|
|
||||||
if CONF_VALUE_TEMPLATE in config:
|
if CONF_VALUE_TEMPLATE in config:
|
||||||
value_template = Template(config[CONF_VALUE_TEMPLATE], hass)
|
value_template = Template(config[CONF_VALUE_TEMPLATE], hass)
|
||||||
|
|
||||||
async_add_entities([FileSensor(name, file_path, unit, value_template)], True)
|
async_add_entities(
|
||||||
|
[FileSensor(unique_id, name, file_path, unit, value_template)], True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FileSensor(SensorEntity):
|
class FileSensor(SensorEntity):
|
||||||
@ -76,6 +78,7 @@ class FileSensor(SensorEntity):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
unique_id: str,
|
||||||
name: str,
|
name: str,
|
||||||
file_path: str,
|
file_path: str,
|
||||||
unit_of_measurement: str | None,
|
unit_of_measurement: str | None,
|
||||||
@ -86,7 +89,7 @@ class FileSensor(SensorEntity):
|
|||||||
self._file_path = file_path
|
self._file_path = file_path
|
||||||
self._attr_native_unit_of_measurement = unit_of_measurement
|
self._attr_native_unit_of_measurement = unit_of_measurement
|
||||||
self._val_tpl = value_template
|
self._val_tpl = value_template
|
||||||
self._attr_unique_id = slugify(f"{name}_{file_path}")
|
self._attr_unique_id = unique_id
|
||||||
|
|
||||||
def update(self) -> None:
|
def update(self) -> None:
|
||||||
"""Get the latest entry from a file and updates the state."""
|
"""Get the latest entry from a file and updates the state."""
|
||||||
|
@ -12,13 +12,11 @@
|
|||||||
"title": "File sensor",
|
"title": "File sensor",
|
||||||
"description": "Set up a file based sensor",
|
"description": "Set up a file based sensor",
|
||||||
"data": {
|
"data": {
|
||||||
"name": "Name",
|
|
||||||
"file_path": "File path",
|
"file_path": "File path",
|
||||||
"value_template": "Value template",
|
"value_template": "Value template",
|
||||||
"unit_of_measurement": "Unit of measurement"
|
"unit_of_measurement": "Unit of measurement"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"name": "Name of the file based sensor",
|
|
||||||
"file_path": "The local file path to retrieve the sensor value from",
|
"file_path": "The local file path to retrieve the sensor value from",
|
||||||
"value_template": "A template to render the the sensors value based on the file content",
|
"value_template": "A template to render the the sensors value based on the file content",
|
||||||
"unit_of_measurement": "Unit of measurement for the sensor"
|
"unit_of_measurement": "Unit of measurement for the sensor"
|
||||||
@ -29,7 +27,7 @@
|
|||||||
"description": "Set up a service that allows to write notification to a file.",
|
"description": "Set up a service that allows to write notification to a file.",
|
||||||
"data": {
|
"data": {
|
||||||
"file_path": "[%key:component::file::config::step::sensor::data::file_path%]",
|
"file_path": "[%key:component::file::config::step::sensor::data::file_path%]",
|
||||||
"name": "[%key:component::file::config::step::sensor::data::name%]",
|
"name": "Name",
|
||||||
"timestamp": "Timestamp"
|
"timestamp": "Timestamp"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
|
@ -22,7 +22,6 @@ MOCK_CONFIG_SENSOR = {
|
|||||||
"platform": "sensor",
|
"platform": "sensor",
|
||||||
"file_path": "some/path",
|
"file_path": "some/path",
|
||||||
"value_template": "{{ value | round(1) }}",
|
"value_template": "{{ value | round(1) }}",
|
||||||
"name": "File",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user