mirror of
https://github.com/home-assistant/core.git
synced 2026-05-22 17:00:50 +02:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b80a66026 | |||
| 9815dd74fd |
@@ -351,6 +351,7 @@ from .const import (
|
||||
CONF_TILT_STATE_OPTIMISTIC,
|
||||
CONF_TILT_STATUS_TEMPLATE,
|
||||
CONF_TILT_STATUS_TOPIC,
|
||||
CONF_TIMEZONE,
|
||||
CONF_TLS_INSECURE,
|
||||
CONF_TRANSITION,
|
||||
CONF_TRANSPORT,
|
||||
@@ -458,6 +459,8 @@ SUBENTRY_PLATFORMS = [
|
||||
Platform.BUTTON,
|
||||
Platform.CLIMATE,
|
||||
Platform.COVER,
|
||||
Platform.DATE,
|
||||
Platform.DATETIME,
|
||||
Platform.FAN,
|
||||
Platform.IMAGE,
|
||||
Platform.LIGHT,
|
||||
@@ -469,6 +472,7 @@ SUBENTRY_PLATFORMS = [
|
||||
Platform.SIREN,
|
||||
Platform.SWITCH,
|
||||
Platform.TEXT,
|
||||
Platform.TIME,
|
||||
Platform.VALVE,
|
||||
Platform.WATER_HEATER,
|
||||
]
|
||||
@@ -482,6 +486,10 @@ PWD_NOT_CHANGED = "__**password_not_changed**__"
|
||||
|
||||
DEVELOPER_DOCUMENTATION_URL = "https://developers.home-assistant.io/"
|
||||
USER_DOCUMENTATION_URL = "https://www.home-assistant.io/"
|
||||
TZ_ZONE_ABBR_URL = (
|
||||
"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
|
||||
"#Time_zone_abbreviations"
|
||||
)
|
||||
|
||||
INTEGRATION_URL = f"{USER_DOCUMENTATION_URL}integrations/{DOMAIN}/"
|
||||
TEMPLATING_URL = f"{USER_DOCUMENTATION_URL}docs/configuration/templating/"
|
||||
@@ -501,6 +509,7 @@ TRANSLATION_DESCRIPTION_PLACEHOLDERS = {
|
||||
"available_state_classes_url": AVAILABLE_STATE_CLASSES_URL,
|
||||
"naming_entities_url": NAMING_ENTITIES_URL,
|
||||
"registry_properties_url": REGISTRY_PROPERTIES_URL,
|
||||
"tz_abbr_url": TZ_ZONE_ABBR_URL,
|
||||
}
|
||||
|
||||
# Common selectors
|
||||
@@ -1234,6 +1243,8 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
Platform.BUTTON: None,
|
||||
Platform.CLIMATE: validate_climate_platform_config,
|
||||
Platform.COVER: validate_cover_platform_config,
|
||||
Platform.DATE: None,
|
||||
Platform.DATETIME: None,
|
||||
Platform.FAN: validate_fan_platform_config,
|
||||
Platform.IMAGE: None,
|
||||
Platform.LIGHT: validate_light_platform_config,
|
||||
@@ -1245,6 +1256,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
Platform.SIREN: None,
|
||||
Platform.SWITCH: None,
|
||||
Platform.TEXT: validate_text_platform_config,
|
||||
Platform.TIME: None,
|
||||
Platform.VALVE: None,
|
||||
Platform.WATER_HEATER: validate_water_heater_platform_config,
|
||||
}
|
||||
@@ -1410,6 +1422,8 @@ PLATFORM_ENTITY_FIELDS: dict[Platform, dict[str, PlatformField]] = {
|
||||
required=False,
|
||||
),
|
||||
},
|
||||
Platform.DATE: {},
|
||||
Platform.DATETIME: {},
|
||||
Platform.FAN: {
|
||||
"fan_feature_speed": PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
@@ -1514,6 +1528,7 @@ PLATFORM_ENTITY_FIELDS: dict[Platform, dict[str, PlatformField]] = {
|
||||
),
|
||||
},
|
||||
Platform.TEXT: {},
|
||||
Platform.TIME: {},
|
||||
Platform.VALVE: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
selector=VALVE_DEVICE_CLASS_SELECTOR, required=False, default=None
|
||||
@@ -2363,6 +2378,61 @@ PLATFORM_MQTT_FIELDS: dict[Platform, dict[str, PlatformField]] = {
|
||||
section="cover_tilt_settings",
|
||||
),
|
||||
},
|
||||
Platform.DATE: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
),
|
||||
CONF_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
),
|
||||
CONF_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_RETAIN: PlatformField(selector=BOOLEAN_SELECTOR, required=False),
|
||||
},
|
||||
Platform.DATETIME: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
),
|
||||
CONF_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
),
|
||||
CONF_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_TIMEZONE: PlatformField(selector=TEXT_SELECTOR, required=False),
|
||||
CONF_RETAIN: PlatformField(selector=BOOLEAN_SELECTOR, required=False),
|
||||
},
|
||||
Platform.FAN: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
@@ -3470,6 +3540,33 @@ PLATFORM_MQTT_FIELDS: dict[Platform, dict[str, PlatformField]] = {
|
||||
section="text_advanced_settings",
|
||||
),
|
||||
},
|
||||
Platform.TIME: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
),
|
||||
CONF_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
),
|
||||
CONF_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_RETAIN: PlatformField(selector=BOOLEAN_SELECTOR, required=False),
|
||||
},
|
||||
Platform.VALVE: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
|
||||
@@ -55,6 +55,7 @@ CONF_RETAIN = ATTR_RETAIN
|
||||
CONF_SCHEMA = "schema"
|
||||
CONF_STATE_TOPIC = "state_topic"
|
||||
CONF_STATE_VALUE_TEMPLATE = "state_value_template"
|
||||
CONF_TIMEZONE = "timezone"
|
||||
CONF_TOPIC = "topic"
|
||||
CONF_TRANSPORT = "transport"
|
||||
CONF_WS_PATH = "ws_path"
|
||||
|
||||
@@ -27,6 +27,7 @@ from .const import (
|
||||
CONF_COMMAND_TEMPLATE,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_STATE_TOPIC,
|
||||
CONF_TIMEZONE,
|
||||
PAYLOAD_NONE,
|
||||
)
|
||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||
@@ -40,8 +41,6 @@ from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_TIMEZONE = "timezone"
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
DEFAULT_NAME = "MQTT Date/Time"
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"support_duration": "Duration support",
|
||||
"support_volume_set": "Set volume support",
|
||||
"supported_color_modes": "Supported color modes",
|
||||
"timezone": "Time zone",
|
||||
"url_template": "URL template",
|
||||
"url_topic": "URL topic",
|
||||
"value_template": "Value template"
|
||||
@@ -428,6 +429,7 @@
|
||||
"support_duration": "The siren supports setting a duration in second. The `duration` variable will become available for use in the \"Command template\" setting. [Learn more.]({url}#support_duration)",
|
||||
"support_volume_set": "The siren supports setting a volume. The `volume_level` variable will become available for use in the \"Command template\" setting. [Learn more.]({url}#support_volume_set)",
|
||||
"supported_color_modes": "A list of color modes supported by the light. Possible color modes are On/Off, Brightness, Color temperature, HS, XY, RGB, RGBW, RGBWW, White. Note that if On/Off or Brightness are used, that must be the only value in the list. [Learn more.]({url}#supported_color_modes)",
|
||||
"timezone": "Set to a valid [IANA time zone identifier]({tz_abbr_url}). Do not set this option if the date/time structure is providing time zone information via the status update.",
|
||||
"url_template": "[Template]({value_templating_url}) to extract an URL from the received URL topic payload value. [Learn more.]({url}#url_template)",
|
||||
"url_topic": "The MQTT topic subscribed to receive messages containing the image URL. [Learn more.]({url}#url_topic)",
|
||||
"value_template": "Defines a [template]({value_templating_url}) to extract the {platform} entity value. [Learn more.]({url}#value_template)"
|
||||
@@ -1463,6 +1465,8 @@
|
||||
"button": "[%key:component::button::title%]",
|
||||
"climate": "[%key:component::climate::title%]",
|
||||
"cover": "[%key:component::cover::title%]",
|
||||
"date": "[%key:component::date::title%]",
|
||||
"datetime": "[%key:component::datetime::title%]",
|
||||
"fan": "[%key:component::fan::title%]",
|
||||
"image": "[%key:component::image::title%]",
|
||||
"light": "[%key:component::light::title%]",
|
||||
@@ -1474,6 +1478,7 @@
|
||||
"siren": "[%key:component::siren::title%]",
|
||||
"switch": "[%key:component::switch::title%]",
|
||||
"text": "[%key:component::text::title%]",
|
||||
"time": "[%key:component::time::title%]",
|
||||
"valve": "[%key:component::valve::title%]",
|
||||
"water_heater": "[%key:component::water_heater::title%]"
|
||||
}
|
||||
|
||||
@@ -319,6 +319,33 @@ MOCK_SUBENTRY_COVER_COMPONENT = {
|
||||
"entity_picture": "https://example.com/b37acf667fa04c688ad7dfb27de2178b",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_DATE_COMPONENT = {
|
||||
"aa261f6feed443e7b7d5f3fbe2a47411": {
|
||||
"platform": "date",
|
||||
"name": "Delivery day",
|
||||
"entity_category": None,
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/aa261f6feed443e7b7d5f3fbe2a47411",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_DATETIME_COMPONENT = {
|
||||
"aa261f6feed443e7b7d5f3fbe2a47412": {
|
||||
"platform": "datetime",
|
||||
"name": "Maintenance service",
|
||||
"entity_category": None,
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"timezone": "GMT",
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/aa261f6feed443e7b7d5f3fbe2a47412",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_FAN_COMPONENT = {
|
||||
"717f924ae9ca4fe9864d845d75d23c9f": {
|
||||
"platform": "fan",
|
||||
@@ -653,6 +680,19 @@ MOCK_SUBENTRY_TEXT_COMPONENT = {
|
||||
"entity_picture": "https://example.com/09261f6feed443e7b7d5f3fbe2a47413",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_TIME_COMPONENT = {
|
||||
"aa261f6feed443e7b7d5f3fbe2a47413": {
|
||||
"platform": "time",
|
||||
"name": "Happy hour",
|
||||
"entity_category": None,
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/aa261f6feed443e7b7d5f3fbe2a47413",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_VALVE_COMPONENT_STATE = {
|
||||
"09261f6feed443e7b7d5f32345a47413": {
|
||||
"platform": "valve",
|
||||
@@ -789,6 +829,14 @@ MOCK_COVER_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_COVER_COMPONENT,
|
||||
}
|
||||
MOCK_DATE_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_DATE_COMPONENT,
|
||||
}
|
||||
MOCK_DATETIME_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_DATETIME_COMPONENT,
|
||||
}
|
||||
MOCK_FAN_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_FAN_COMPONENT,
|
||||
@@ -865,6 +913,10 @@ MOCK_TEXT_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_TEXT_COMPONENT,
|
||||
}
|
||||
MOCK_TIME_SUBENTRY_DATA = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_TIME_COMPONENT,
|
||||
}
|
||||
MOCK_VALVE_SUBENTRY_DATA_STATE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_VALVE_COMPONENT_STATE,
|
||||
|
||||
@@ -46,6 +46,8 @@ from .common import (
|
||||
MOCK_CLIMATE_NO_TARGET_TEMP_SUBENTRY_DATA,
|
||||
MOCK_CLIMATE_SUBENTRY_DATA,
|
||||
MOCK_COVER_SUBENTRY_DATA,
|
||||
MOCK_DATE_SUBENTRY_DATA,
|
||||
MOCK_DATETIME_SUBENTRY_DATA,
|
||||
MOCK_FAN_SUBENTRY_DATA,
|
||||
MOCK_IMAGE_SUBENTRY_DATA_IMAGE_DATA,
|
||||
MOCK_IMAGE_SUBENTRY_DATA_IMAGE_URL,
|
||||
@@ -66,6 +68,7 @@ from .common import (
|
||||
MOCK_SIREN_SUBENTRY_DATA,
|
||||
MOCK_SWITCH_SUBENTRY_DATA,
|
||||
MOCK_TEXT_SUBENTRY_DATA,
|
||||
MOCK_TIME_SUBENTRY_DATA,
|
||||
MOCK_VALVE_SUBENTRY_DATA_POSITION,
|
||||
MOCK_VALVE_SUBENTRY_DATA_STATE,
|
||||
MOCK_WATER_HEATER_SUBENTRY_DATA,
|
||||
@@ -3163,6 +3166,65 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
"Milk notifier Blind",
|
||||
id="cover",
|
||||
),
|
||||
pytest.param(
|
||||
MOCK_DATE_SUBENTRY_DATA,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Delivery day"},
|
||||
{},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"retain": False,
|
||||
},
|
||||
(
|
||||
(
|
||||
{"command_topic": "test-topic#invalid"},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
},
|
||||
{"state_topic": "invalid_subscribe_topic"},
|
||||
),
|
||||
),
|
||||
"Milk notifier Delivery day",
|
||||
id="date",
|
||||
),
|
||||
pytest.param(
|
||||
MOCK_DATETIME_SUBENTRY_DATA,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Maintenance service"},
|
||||
{},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"timezone": "GMT",
|
||||
"retain": False,
|
||||
},
|
||||
(
|
||||
(
|
||||
{"command_topic": "test-topic#invalid"},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
},
|
||||
{"state_topic": "invalid_subscribe_topic"},
|
||||
),
|
||||
),
|
||||
"Milk notifier Maintenance service",
|
||||
id="datetime",
|
||||
),
|
||||
pytest.param(
|
||||
MOCK_FAN_SUBENTRY_DATA,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
@@ -3850,6 +3912,35 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
"Milk notifier MOTD",
|
||||
id="text",
|
||||
),
|
||||
pytest.param(
|
||||
MOCK_TIME_SUBENTRY_DATA,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Happy hour"},
|
||||
{},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"retain": False,
|
||||
},
|
||||
(
|
||||
(
|
||||
{"command_topic": "test-topic#invalid"},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
},
|
||||
{"state_topic": "invalid_subscribe_topic"},
|
||||
),
|
||||
),
|
||||
"Milk notifier Happy hour",
|
||||
id="time",
|
||||
),
|
||||
pytest.param(
|
||||
MOCK_VALVE_SUBENTRY_DATA_STATE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
|
||||
Reference in New Issue
Block a user