mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Add MQTT fan as entity platform on MQTT subentries (#144698)
This commit is contained in:
parent
e22ea85e84
commit
2a38f03ec9
@ -143,6 +143,10 @@ from .const import (
|
||||
CONF_COMMAND_ON_TEMPLATE,
|
||||
CONF_COMMAND_TEMPLATE,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_DIRECTION_COMMAND_TEMPLATE,
|
||||
CONF_DIRECTION_COMMAND_TOPIC,
|
||||
CONF_DIRECTION_STATE_TOPIC,
|
||||
CONF_DIRECTION_VALUE_TEMPLATE,
|
||||
CONF_DISCOVERY_PREFIX,
|
||||
CONF_EFFECT_COMMAND_TEMPLATE,
|
||||
CONF_EFFECT_COMMAND_TOPIC,
|
||||
@ -169,15 +173,32 @@ from .const import (
|
||||
CONF_OFF_DELAY,
|
||||
CONF_ON_COMMAND_TYPE,
|
||||
CONF_OPTIONS,
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE,
|
||||
CONF_OSCILLATION_COMMAND_TOPIC,
|
||||
CONF_OSCILLATION_STATE_TOPIC,
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE,
|
||||
CONF_PAYLOAD_AVAILABLE,
|
||||
CONF_PAYLOAD_CLOSE,
|
||||
CONF_PAYLOAD_NOT_AVAILABLE,
|
||||
CONF_PAYLOAD_OPEN,
|
||||
CONF_PAYLOAD_OSCILLATION_OFF,
|
||||
CONF_PAYLOAD_OSCILLATION_ON,
|
||||
CONF_PAYLOAD_PRESS,
|
||||
CONF_PAYLOAD_RESET_PERCENTAGE,
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE,
|
||||
CONF_PAYLOAD_STOP,
|
||||
CONF_PAYLOAD_STOP_TILT,
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE,
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC,
|
||||
CONF_PERCENTAGE_STATE_TOPIC,
|
||||
CONF_PERCENTAGE_VALUE_TEMPLATE,
|
||||
CONF_POSITION_CLOSED,
|
||||
CONF_POSITION_OPEN,
|
||||
CONF_PRESET_MODE_COMMAND_TEMPLATE,
|
||||
CONF_PRESET_MODE_COMMAND_TOPIC,
|
||||
CONF_PRESET_MODE_STATE_TOPIC,
|
||||
CONF_PRESET_MODE_VALUE_TEMPLATE,
|
||||
CONF_PRESET_MODES_LIST,
|
||||
CONF_QOS,
|
||||
CONF_RED_TEMPLATE,
|
||||
CONF_RETAIN,
|
||||
@ -196,6 +217,8 @@ from .const import (
|
||||
CONF_SCHEMA,
|
||||
CONF_SET_POSITION_TEMPLATE,
|
||||
CONF_SET_POSITION_TOPIC,
|
||||
CONF_SPEED_RANGE_MAX,
|
||||
CONF_SPEED_RANGE_MIN,
|
||||
CONF_STATE_CLOSED,
|
||||
CONF_STATE_CLOSING,
|
||||
CONF_STATE_OPEN,
|
||||
@ -239,7 +262,10 @@ from .const import (
|
||||
DEFAULT_PAYLOAD_OFF,
|
||||
DEFAULT_PAYLOAD_ON,
|
||||
DEFAULT_PAYLOAD_OPEN,
|
||||
DEFAULT_PAYLOAD_OSCILLATE_OFF,
|
||||
DEFAULT_PAYLOAD_OSCILLATE_ON,
|
||||
DEFAULT_PAYLOAD_PRESS,
|
||||
DEFAULT_PAYLOAD_RESET,
|
||||
DEFAULT_PAYLOAD_STOP,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_POSITION_CLOSED,
|
||||
@ -247,6 +273,8 @@ from .const import (
|
||||
DEFAULT_PREFIX,
|
||||
DEFAULT_PROTOCOL,
|
||||
DEFAULT_QOS,
|
||||
DEFAULT_SPEED_RANGE_MAX,
|
||||
DEFAULT_SPEED_RANGE_MIN,
|
||||
DEFAULT_STATE_STOPPED,
|
||||
DEFAULT_TILT_CLOSED_POSITION,
|
||||
DEFAULT_TILT_MAX,
|
||||
@ -353,6 +381,7 @@ SUBENTRY_PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.COVER,
|
||||
Platform.FAN,
|
||||
Platform.LIGHT,
|
||||
Platform.NOTIFY,
|
||||
Platform.SENSOR,
|
||||
@ -437,6 +466,17 @@ TIMEOUT_SELECTOR = NumberSelector(
|
||||
# Cover specific selectors
|
||||
POSITION_SELECTOR = NumberSelector(NumberSelectorConfig(mode=NumberSelectorMode.BOX))
|
||||
|
||||
# Fan specific selectors
|
||||
FAN_SPEED_RANGE_MIN_SELECTOR = vol.All(
|
||||
NumberSelector(NumberSelectorConfig(mode=NumberSelectorMode.BOX, min=1)),
|
||||
vol.Coerce(int),
|
||||
)
|
||||
FAN_SPEED_RANGE_MAX_SELECTOR = vol.All(
|
||||
NumberSelector(NumberSelectorConfig(mode=NumberSelectorMode.BOX, min=2)),
|
||||
vol.Coerce(int),
|
||||
)
|
||||
PRESET_MODES_SELECTOR = OPTIONS_SELECTOR
|
||||
|
||||
# Switch specific selectors
|
||||
SWITCH_DEVICE_CLASS_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
@ -537,6 +577,29 @@ def validate_cover_platform_config(
|
||||
return errors
|
||||
|
||||
|
||||
@callback
|
||||
def validate_fan_platform_config(config: dict[str, Any]) -> dict[str, str]:
|
||||
"""Validate the fan config options."""
|
||||
errors: dict[str, str] = {}
|
||||
if (
|
||||
CONF_SPEED_RANGE_MIN in config
|
||||
and CONF_SPEED_RANGE_MAX in config
|
||||
and config[CONF_SPEED_RANGE_MIN] >= config[CONF_SPEED_RANGE_MAX]
|
||||
):
|
||||
errors["fan_speed_settings"] = (
|
||||
"fan_speed_range_max_must_be_greater_than_speed_range_min"
|
||||
)
|
||||
if (
|
||||
CONF_PRESET_MODES_LIST in config
|
||||
and config.get(CONF_PAYLOAD_RESET_PRESET_MODE) in config[CONF_PRESET_MODES_LIST]
|
||||
):
|
||||
errors["fan_preset_mode_settings"] = (
|
||||
"fan_preset_mode_reset_in_preset_modes_list"
|
||||
)
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
@callback
|
||||
def validate_sensor_platform_config(
|
||||
config: dict[str, Any],
|
||||
@ -597,9 +660,12 @@ class PlatformField:
|
||||
required: bool
|
||||
validator: Callable[..., Any] | None = None
|
||||
error: str | None = None
|
||||
default: str | int | bool | None | vol.Undefined = vol.UNDEFINED
|
||||
default: (
|
||||
str | int | bool | None | Callable[[dict[str, Any]], Any] | vol.Undefined
|
||||
) = vol.UNDEFINED
|
||||
is_schema_default: bool = False
|
||||
exclude_from_reconfig: bool = False
|
||||
exclude_from_config: bool = False
|
||||
conditions: tuple[dict[str, Any], ...] | None = None
|
||||
custom_filtering: bool = False
|
||||
section: str | None = None
|
||||
@ -634,7 +700,7 @@ def validate_light_platform_config(user_data: dict[str, Any]) -> dict[str, str]:
|
||||
return errors
|
||||
|
||||
|
||||
COMMON_ENTITY_FIELDS = {
|
||||
COMMON_ENTITY_FIELDS: dict[str, PlatformField] = {
|
||||
CONF_PLATFORM: PlatformField(
|
||||
selector=SUBENTRY_PLATFORM_SELECTOR,
|
||||
required=True,
|
||||
@ -651,7 +717,7 @@ COMMON_ENTITY_FIELDS = {
|
||||
),
|
||||
}
|
||||
|
||||
PLATFORM_ENTITY_FIELDS = {
|
||||
PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
|
||||
Platform.BINARY_SENSOR.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
selector=BINARY_SENSOR_DEVICE_CLASS_SELECTOR,
|
||||
@ -670,6 +736,32 @@ PLATFORM_ENTITY_FIELDS = {
|
||||
required=False,
|
||||
),
|
||||
},
|
||||
Platform.FAN.value: {
|
||||
"fan_feature_speed": PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=False,
|
||||
exclude_from_config=True,
|
||||
default=lambda config: bool(config.get(CONF_PERCENTAGE_COMMAND_TOPIC)),
|
||||
),
|
||||
"fan_feature_preset_modes": PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=False,
|
||||
exclude_from_config=True,
|
||||
default=lambda config: bool(config.get(CONF_PRESET_MODE_COMMAND_TOPIC)),
|
||||
),
|
||||
"fan_feature_oscillation": PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=False,
|
||||
exclude_from_config=True,
|
||||
default=lambda config: bool(config.get(CONF_OSCILLATION_COMMAND_TOPIC)),
|
||||
),
|
||||
"fan_feature_direction": PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=False,
|
||||
exclude_from_config=True,
|
||||
default=lambda config: bool(config.get(CONF_DIRECTION_COMMAND_TOPIC)),
|
||||
),
|
||||
},
|
||||
Platform.NOTIFY.value: {},
|
||||
Platform.SENSOR.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
@ -715,7 +807,7 @@ PLATFORM_ENTITY_FIELDS = {
|
||||
),
|
||||
},
|
||||
}
|
||||
PLATFORM_MQTT_FIELDS = {
|
||||
PLATFORM_MQTT_FIELDS: dict[str, dict[str, PlatformField]] = {
|
||||
Platform.BINARY_SENSOR.value: {
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
@ -951,6 +1043,226 @@ PLATFORM_MQTT_FIELDS = {
|
||||
section="cover_tilt_settings",
|
||||
),
|
||||
},
|
||||
Platform.FAN.value: {
|
||||
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_PAYLOAD_OFF: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_OFF,
|
||||
),
|
||||
CONF_PAYLOAD_ON: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ON,
|
||||
),
|
||||
CONF_RETAIN: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR, required=False, validator=bool
|
||||
),
|
||||
CONF_OPTIMISTIC: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR, required=False, validator=bool
|
||||
),
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_PERCENTAGE_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_PERCENTAGE_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_SPEED_RANGE_MIN: PlatformField(
|
||||
selector=FAN_SPEED_RANGE_MIN_SELECTOR,
|
||||
required=False,
|
||||
validator=int,
|
||||
default=DEFAULT_SPEED_RANGE_MIN,
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_SPEED_RANGE_MAX: PlatformField(
|
||||
selector=FAN_SPEED_RANGE_MAX_SELECTOR,
|
||||
required=False,
|
||||
validator=int,
|
||||
default=DEFAULT_SPEED_RANGE_MAX,
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_PAYLOAD_RESET_PERCENTAGE: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_RESET,
|
||||
section="fan_speed_settings",
|
||||
conditions=({"fan_feature_speed": True},),
|
||||
),
|
||||
CONF_PRESET_MODES_LIST: PlatformField(
|
||||
selector=PRESET_MODES_SELECTOR,
|
||||
required=True,
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_PRESET_MODE_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_PRESET_MODE_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_PRESET_MODE_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_PRESET_MODE_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_RESET,
|
||||
section="fan_preset_mode_settings",
|
||||
conditions=({"fan_feature_preset_modes": True},),
|
||||
),
|
||||
CONF_OSCILLATION_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_OSCILLATION_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_PAYLOAD_OSCILLATION_OFF: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_OSCILLATE_OFF,
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_PAYLOAD_OSCILLATION_ON: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_OSCILLATE_ON,
|
||||
section="fan_oscillation_settings",
|
||||
conditions=({"fan_feature_oscillation": True},),
|
||||
),
|
||||
CONF_DIRECTION_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
section="fan_direction_settings",
|
||||
conditions=({"fan_feature_direction": True},),
|
||||
),
|
||||
CONF_DIRECTION_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_direction_settings",
|
||||
conditions=({"fan_feature_direction": True},),
|
||||
),
|
||||
CONF_DIRECTION_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
section="fan_direction_settings",
|
||||
conditions=({"fan_feature_direction": True},),
|
||||
),
|
||||
CONF_DIRECTION_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
section="fan_direction_settings",
|
||||
conditions=({"fan_feature_direction": True},),
|
||||
),
|
||||
},
|
||||
Platform.NOTIFY.value: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
@ -1510,6 +1822,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
Platform.BINARY_SENSOR.value: None,
|
||||
Platform.BUTTON.value: None,
|
||||
Platform.COVER.value: validate_cover_platform_config,
|
||||
Platform.FAN.value: validate_fan_platform_config,
|
||||
Platform.LIGHT.value: validate_light_platform_config,
|
||||
Platform.NOTIFY.value: None,
|
||||
Platform.SENSOR.value: validate_sensor_platform_config,
|
||||
@ -1667,6 +1980,14 @@ def data_schema_from_fields(
|
||||
device_data: MqttDeviceData | None = None,
|
||||
) -> vol.Schema:
|
||||
"""Generate custom data schema from platform fields or device data."""
|
||||
|
||||
def get_default(field_details: PlatformField) -> Any:
|
||||
if callable(field_details.default):
|
||||
if TYPE_CHECKING:
|
||||
assert component_data is not None
|
||||
return field_details.default(component_data)
|
||||
return field_details.default
|
||||
|
||||
if device_data is not None:
|
||||
component_data_with_user_input: dict[str, Any] | None = dict(device_data)
|
||||
if TYPE_CHECKING:
|
||||
@ -1693,7 +2014,7 @@ def data_schema_from_fields(
|
||||
if field_details.required
|
||||
else vol.Optional(
|
||||
field_name,
|
||||
default=field_details.default
|
||||
default=get_default(field_details)
|
||||
if field_details.default is not None
|
||||
else vol.UNDEFINED,
|
||||
): field_details.selector(component_data_with_user_input) # type: ignore[operator]
|
||||
@ -2581,13 +2902,21 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
|
||||
"""Update component data defaults."""
|
||||
for component_data in self._subentry_data["components"].values():
|
||||
platform = component_data[CONF_PLATFORM]
|
||||
subentry_default_data = subentry_schema_default_data_from_fields(
|
||||
platform_fields: dict[str, PlatformField] = (
|
||||
COMMON_ENTITY_FIELDS
|
||||
| PLATFORM_ENTITY_FIELDS[platform]
|
||||
| PLATFORM_MQTT_FIELDS[platform],
|
||||
| PLATFORM_MQTT_FIELDS[platform]
|
||||
)
|
||||
subentry_default_data = subentry_schema_default_data_from_fields(
|
||||
platform_fields,
|
||||
component_data,
|
||||
)
|
||||
component_data.update(subentry_default_data)
|
||||
for key, platform_field in platform_fields.items():
|
||||
if not platform_field.exclude_from_config:
|
||||
continue
|
||||
if key in component_data:
|
||||
component_data.pop(key)
|
||||
|
||||
@callback
|
||||
def _async_create_subentry(
|
||||
|
@ -78,6 +78,10 @@ CONF_CURRENT_HUMIDITY_TEMPLATE = "current_humidity_template"
|
||||
CONF_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic"
|
||||
CONF_CURRENT_TEMP_TEMPLATE = "current_temperature_template"
|
||||
CONF_CURRENT_TEMP_TOPIC = "current_temperature_topic"
|
||||
CONF_DIRECTION_COMMAND_TEMPLATE = "direction_command_template"
|
||||
CONF_DIRECTION_COMMAND_TOPIC = "direction_command_topic"
|
||||
CONF_DIRECTION_STATE_TOPIC = "direction_state_topic"
|
||||
CONF_DIRECTION_VALUE_TEMPLATE = "direction_value_template"
|
||||
CONF_ENABLED_BY_DEFAULT = "enabled_by_default"
|
||||
CONF_EFFECT_COMMAND_TEMPLATE = "effect_command_template"
|
||||
CONF_EFFECT_COMMAND_TOPIC = "effect_command_topic"
|
||||
@ -109,16 +113,33 @@ CONF_MODE_STATE_TEMPLATE = "mode_state_template"
|
||||
CONF_MODE_STATE_TOPIC = "mode_state_topic"
|
||||
CONF_OFF_DELAY = "off_delay"
|
||||
CONF_ON_COMMAND_TYPE = "on_command_type"
|
||||
CONF_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic"
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE = "oscillation_command_template"
|
||||
CONF_OSCILLATION_STATE_TOPIC = "oscillation_state_topic"
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE = "oscillation_value_template"
|
||||
CONF_PAYLOAD_CLOSE = "payload_close"
|
||||
CONF_PAYLOAD_OPEN = "payload_open"
|
||||
CONF_PAYLOAD_OSCILLATION_OFF = "payload_oscillation_off"
|
||||
CONF_PAYLOAD_OSCILLATION_ON = "payload_oscillation_on"
|
||||
CONF_PAYLOAD_PRESS = "payload_press"
|
||||
CONF_PAYLOAD_RESET_PERCENTAGE = "payload_reset_percentage"
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE = "payload_reset_preset_mode"
|
||||
CONF_PAYLOAD_STOP = "payload_stop"
|
||||
CONF_PAYLOAD_STOP_TILT = "payload_stop_tilt"
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE = "percentage_command_template"
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"
|
||||
CONF_PERCENTAGE_STATE_TOPIC = "percentage_state_topic"
|
||||
CONF_PERCENTAGE_VALUE_TEMPLATE = "percentage_value_template"
|
||||
CONF_POSITION_CLOSED = "position_closed"
|
||||
CONF_POSITION_OPEN = "position_open"
|
||||
CONF_POWER_COMMAND_TOPIC = "power_command_topic"
|
||||
CONF_POWER_COMMAND_TEMPLATE = "power_command_template"
|
||||
CONF_PRECISION = "precision"
|
||||
CONF_PRESET_MODE_COMMAND_TEMPLATE = "preset_mode_command_template"
|
||||
CONF_PRESET_MODE_COMMAND_TOPIC = "preset_mode_command_topic"
|
||||
CONF_PRESET_MODES_LIST = "preset_modes"
|
||||
CONF_PRESET_MODE_STATE_TOPIC = "preset_mode_state_topic"
|
||||
CONF_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template"
|
||||
CONF_RED_TEMPLATE = "red_template"
|
||||
CONF_RGB_COMMAND_TEMPLATE = "rgb_command_template"
|
||||
CONF_RGB_COMMAND_TOPIC = "rgb_command_topic"
|
||||
@ -134,6 +155,8 @@ CONF_RGBWW_STATE_TOPIC = "rgbww_state_topic"
|
||||
CONF_RGBWW_VALUE_TEMPLATE = "rgbww_value_template"
|
||||
CONF_SET_POSITION_TEMPLATE = "set_position_template"
|
||||
CONF_SET_POSITION_TOPIC = "set_position_topic"
|
||||
CONF_SPEED_RANGE_MAX = "speed_range_max"
|
||||
CONF_SPEED_RANGE_MIN = "speed_range_min"
|
||||
CONF_STATE_CLOSED = "state_closed"
|
||||
CONF_STATE_CLOSING = "state_closing"
|
||||
CONF_STATE_OPEN = "state_open"
|
||||
@ -204,8 +227,11 @@ DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"
|
||||
DEFAULT_PAYLOAD_OFF = "OFF"
|
||||
DEFAULT_PAYLOAD_ON = "ON"
|
||||
DEFAULT_PAYLOAD_OPEN = "OPEN"
|
||||
DEFAULT_PAYLOAD_OSCILLATE_OFF = "oscillate_off"
|
||||
DEFAULT_PAYLOAD_OSCILLATE_ON = "oscillate_on"
|
||||
DEFAULT_PAYLOAD_PRESS = "PRESS"
|
||||
DEFAULT_PAYLOAD_STOP = "STOP"
|
||||
DEFAULT_PAYLOAD_RESET = "None"
|
||||
DEFAULT_PORT = 1883
|
||||
DEFAULT_RETAIN = False
|
||||
DEFAULT_TILT_CLOSED_POSITION = 0
|
||||
@ -218,6 +244,8 @@ DEFAULT_WS_PATH = "/"
|
||||
DEFAULT_POSITION_CLOSED = 0
|
||||
DEFAULT_POSITION_OPEN = 100
|
||||
DEFAULT_RETAIN = False
|
||||
DEFAULT_SPEED_RANGE_MAX = 100
|
||||
DEFAULT_SPEED_RANGE_MIN = 1
|
||||
DEFAULT_STATE_STOPPED = "stopped"
|
||||
DEFAULT_WHITE_SCALE = 255
|
||||
|
||||
|
@ -43,8 +43,38 @@ from .config import MQTT_RW_SCHEMA
|
||||
from .const import (
|
||||
CONF_COMMAND_TEMPLATE,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_DIRECTION_COMMAND_TEMPLATE,
|
||||
CONF_DIRECTION_COMMAND_TOPIC,
|
||||
CONF_DIRECTION_STATE_TOPIC,
|
||||
CONF_DIRECTION_VALUE_TEMPLATE,
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE,
|
||||
CONF_OSCILLATION_COMMAND_TOPIC,
|
||||
CONF_OSCILLATION_STATE_TOPIC,
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE,
|
||||
CONF_PAYLOAD_OSCILLATION_OFF,
|
||||
CONF_PAYLOAD_OSCILLATION_ON,
|
||||
CONF_PAYLOAD_RESET_PERCENTAGE,
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE,
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE,
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC,
|
||||
CONF_PERCENTAGE_STATE_TOPIC,
|
||||
CONF_PERCENTAGE_VALUE_TEMPLATE,
|
||||
CONF_PRESET_MODE_COMMAND_TEMPLATE,
|
||||
CONF_PRESET_MODE_COMMAND_TOPIC,
|
||||
CONF_PRESET_MODE_STATE_TOPIC,
|
||||
CONF_PRESET_MODE_VALUE_TEMPLATE,
|
||||
CONF_PRESET_MODES_LIST,
|
||||
CONF_SPEED_RANGE_MAX,
|
||||
CONF_SPEED_RANGE_MIN,
|
||||
CONF_STATE_TOPIC,
|
||||
CONF_STATE_VALUE_TEMPLATE,
|
||||
DEFAULT_PAYLOAD_OFF,
|
||||
DEFAULT_PAYLOAD_ON,
|
||||
DEFAULT_PAYLOAD_OSCILLATE_OFF,
|
||||
DEFAULT_PAYLOAD_OSCILLATE_ON,
|
||||
DEFAULT_PAYLOAD_RESET,
|
||||
DEFAULT_SPEED_RANGE_MAX,
|
||||
DEFAULT_SPEED_RANGE_MIN,
|
||||
PAYLOAD_NONE,
|
||||
)
|
||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||
@ -59,39 +89,7 @@ from .util import valid_publish_topic, valid_subscribe_topic
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
CONF_DIRECTION_STATE_TOPIC = "direction_state_topic"
|
||||
CONF_DIRECTION_COMMAND_TOPIC = "direction_command_topic"
|
||||
CONF_DIRECTION_VALUE_TEMPLATE = "direction_value_template"
|
||||
CONF_DIRECTION_COMMAND_TEMPLATE = "direction_command_template"
|
||||
CONF_PERCENTAGE_STATE_TOPIC = "percentage_state_topic"
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"
|
||||
CONF_PERCENTAGE_VALUE_TEMPLATE = "percentage_value_template"
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE = "percentage_command_template"
|
||||
CONF_PAYLOAD_RESET_PERCENTAGE = "payload_reset_percentage"
|
||||
CONF_SPEED_RANGE_MIN = "speed_range_min"
|
||||
CONF_SPEED_RANGE_MAX = "speed_range_max"
|
||||
CONF_PRESET_MODE_STATE_TOPIC = "preset_mode_state_topic"
|
||||
CONF_PRESET_MODE_COMMAND_TOPIC = "preset_mode_command_topic"
|
||||
CONF_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template"
|
||||
CONF_PRESET_MODE_COMMAND_TEMPLATE = "preset_mode_command_template"
|
||||
CONF_PRESET_MODES_LIST = "preset_modes"
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE = "payload_reset_preset_mode"
|
||||
CONF_OSCILLATION_STATE_TOPIC = "oscillation_state_topic"
|
||||
CONF_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic"
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE = "oscillation_value_template"
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE = "oscillation_command_template"
|
||||
CONF_PAYLOAD_OSCILLATION_ON = "payload_oscillation_on"
|
||||
CONF_PAYLOAD_OSCILLATION_OFF = "payload_oscillation_off"
|
||||
|
||||
DEFAULT_NAME = "MQTT Fan"
|
||||
DEFAULT_PAYLOAD_ON = "ON"
|
||||
DEFAULT_PAYLOAD_OFF = "OFF"
|
||||
DEFAULT_PAYLOAD_RESET = "None"
|
||||
DEFAULT_SPEED_RANGE_MIN = 1
|
||||
DEFAULT_SPEED_RANGE_MAX = 100
|
||||
|
||||
OSCILLATE_ON_PAYLOAD = "oscillate_on"
|
||||
OSCILLATE_OFF_PAYLOAD = "oscillate_off"
|
||||
|
||||
MQTT_FAN_ATTRIBUTES_BLOCKED = frozenset(
|
||||
{
|
||||
@ -165,10 +163,10 @@ _PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||
vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_OSCILLATION_OFF, default=OSCILLATE_OFF_PAYLOAD
|
||||
CONF_PAYLOAD_OSCILLATION_OFF, default=DEFAULT_PAYLOAD_OSCILLATE_OFF
|
||||
): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_OSCILLATION_ON, default=OSCILLATE_ON_PAYLOAD
|
||||
CONF_PAYLOAD_OSCILLATION_ON, default=DEFAULT_PAYLOAD_OSCILLATE_ON
|
||||
): cv.string,
|
||||
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
|
||||
}
|
||||
|
@ -214,6 +214,10 @@
|
||||
"description": "Please configure specific details for {platform} entity \"{entity}\":",
|
||||
"data": {
|
||||
"device_class": "Device class",
|
||||
"fan_feature_speed": "Speed support",
|
||||
"fan_feature_preset_modes": "Preset modes support",
|
||||
"fan_feature_oscillation": "Oscillation support",
|
||||
"fan_feature_direction": "Direction support",
|
||||
"options": "Add option",
|
||||
"schema": "Schema",
|
||||
"state_class": "State class",
|
||||
@ -222,6 +226,10 @@
|
||||
},
|
||||
"data_description": {
|
||||
"device_class": "The Device class of the {platform} entity. [Learn more.]({url}#device_class)",
|
||||
"fan_feature_speed": "The fan supports multiple speeds.",
|
||||
"fan_feature_preset_modes": "The fan supports preset modes.",
|
||||
"fan_feature_oscillation": "The fan supports oscillation.",
|
||||
"fan_feature_direction": "The fan supports direction.",
|
||||
"options": "Options for allowed sensor state values. The sensor’s Device class must be set to Enumeration. The 'Options' setting cannot be used together with State class or Unit of measurement.",
|
||||
"schema": "The schema to use. [Learn more.]({url}#comparison-of-light-mqtt-schemas)",
|
||||
"state_class": "The [State class](https://developers.home-assistant.io/docs/core/entity/sensor/#available-state-classes) of the sensor. [Learn more.]({url}#state_class)",
|
||||
@ -404,6 +412,80 @@
|
||||
"brightness_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract the brightness value."
|
||||
}
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"name": "Direction settings",
|
||||
"data": {
|
||||
"direction_command_topic": "Direction command topic",
|
||||
"direction_command_template": "Direction command template",
|
||||
"direction_state_topic": "Direction state topic",
|
||||
"direction_value_template": "Direction value template"
|
||||
},
|
||||
"data_description": {
|
||||
"direction_command_topic": "The MQTT topic to publish commands to change the fan direction payload, either `forward` or `reverse`. Use the direction command template to customize the payload. [Learn more.]({url}#direction_command_topic)",
|
||||
"direction_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the direction command topic. The template variable `value` will be either `forward` or `reverse`.",
|
||||
"direction_state_topic": "The MQTT topic subscribed to receive fan direction state. Accepted state payloads are `forward` or `reverse`. [Learn more.]({url}#direction_state_topic)",
|
||||
"direction_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract fan direction state value. The template should return either `forward` or `reverse`. When the template returns an empty string, the direction will be ignored."
|
||||
}
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"name": "Oscillation settings",
|
||||
"data": {
|
||||
"oscillation_command_topic": "Oscillation command topic",
|
||||
"oscillation_command_template": "Oscillation command template",
|
||||
"oscillation_state_topic": "Oscillation state topic",
|
||||
"oscillation_value_template": "Oscillation value template",
|
||||
"payload_oscillation_off": "Payload \"oscillation off\"",
|
||||
"payload_oscillation_on": "Payload \"oscillation on\""
|
||||
},
|
||||
"data_description": {
|
||||
"oscillation_command_topic": "The MQTT topic to publish commands to change the fan oscillation state. [Learn more.]({url}#oscillation_command_topic)",
|
||||
"oscillation_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the oscillation command topic.",
|
||||
"oscillation_state_topic": "The MQTT topic subscribed to receive fan oscillation state. [Learn more.]({url}#oscillation_state_topic)",
|
||||
"oscillation_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract fan oscillation state value.",
|
||||
"payload_oscillation_off": "The payload that represents the oscillation \"off\" state.",
|
||||
"payload_oscillation_on": "The payload that represents the oscillation \"on\" state."
|
||||
}
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"name": "Preset mode settings",
|
||||
"data": {
|
||||
"payload_reset_preset_mode": "Payload \"reset preset mode\"",
|
||||
"preset_modes": "Preset modes",
|
||||
"preset_mode_command_topic": "Preset mode command topic",
|
||||
"preset_mode_command_template": "Preset mode command template",
|
||||
"preset_mode_state_topic": "Preset mode state topic",
|
||||
"preset_mode_value_template": "Preset mode value template"
|
||||
},
|
||||
"data_description": {
|
||||
"payload_reset_preset_mode": "A special payload that resets the fan preset mode state attribute to unknown when received at the preset mode state topic.",
|
||||
"preset_modes": "List of preset modes this fan is capable of running at. Common examples include auto, smart, whoosh, eco and breeze.",
|
||||
"preset_mode_command_topic": "The MQTT topic to publish commands to change the fan preset mode. [Learn more.]({url}#preset_mode_command_topic)",
|
||||
"preset_mode_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the preset mode command topic.",
|
||||
"preset_mode_state_topic": "The MQTT topic subscribed to receive fan preset mode. [Learn more.]({url}#preset_mode_state_topic)",
|
||||
"preset_mode_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract fan preset mode value."
|
||||
}
|
||||
},
|
||||
"fan_speed_settings": {
|
||||
"name": "Speed settings",
|
||||
"data": {
|
||||
"payload_reset_percentage": "Payload \"reset percentage\"",
|
||||
"percentage_command_topic": "Percentage command topic",
|
||||
"percentage_command_template": "Percentage command template",
|
||||
"percentage_state_topic": "Percentage state topic",
|
||||
"percentage_value_template": "Percentage value template",
|
||||
"speed_range_min": "Speed range min",
|
||||
"speed_range_max": "Speed range max"
|
||||
},
|
||||
"data_description": {
|
||||
"payload_reset_percentage": "A special payload that resets the fan speed percentage state attribute to unknown when received at the percentage state topic.",
|
||||
"percentage_command_topic": "The MQTT topic to publish commands to change the fan speed state based on a percentage. [Learn more.]({url}#percentage_command_topic)",
|
||||
"percentage_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the percentage command topic.",
|
||||
"percentage_state_topic": "The MQTT topic subscribed to receive fan speed based on percentage. [Learn more.]({url}#percentage_state_topic)",
|
||||
"percentage_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract the speed percentage value.",
|
||||
"speed_range_min": "The minimum of numeric output range (off not included, so speed_range_min - 1 represents 0 %). The number of speeds within the \"speed range\" / 100 will determine the percentage step.",
|
||||
"speed_range_max": "The maximum of numeric output range (representing 100 %). The number of speeds within the \"speed range\" / 100 will determine the percentage step."
|
||||
}
|
||||
},
|
||||
"light_color_mode_settings": {
|
||||
"name": "Color mode settings",
|
||||
"data": {
|
||||
@ -551,6 +633,8 @@
|
||||
"cover_tilt_command_template_must_be_used_with_tilt_command_topic": "The tilt command template must be used with the tilt command topic",
|
||||
"cover_tilt_status_template_must_be_used_with_tilt_status_topic": "The tilt value template must be used with the tilt status topic",
|
||||
"cover_value_template_must_be_used_with_state_topic": "The value template must be used with the state topic option",
|
||||
"fan_speed_range_max_must_be_greater_than_speed_range_min": "Speed range max must be greater than speed range min",
|
||||
"fan_preset_mode_reset_in_preset_modes_list": "Payload \"preset mode reset\" is not a valid preset mode",
|
||||
"invalid_input": "Invalid value",
|
||||
"invalid_subscribe_topic": "Invalid subscribe topic",
|
||||
"invalid_template": "Invalid template",
|
||||
@ -817,6 +901,7 @@
|
||||
"binary_sensor": "[%key:component::binary_sensor::title%]",
|
||||
"button": "[%key:component::button::title%]",
|
||||
"cover": "[%key:component::cover::title%]",
|
||||
"fan": "[%key:component::fan::title%]",
|
||||
"light": "[%key:component::light::title%]",
|
||||
"notify": "[%key:component::notify::title%]",
|
||||
"sensor": "[%key:component::sensor::title%]",
|
||||
|
@ -127,6 +127,44 @@ MOCK_SUBENTRY_COVER_COMPONENT = {
|
||||
"entity_picture": "https://example.com/b37acf667fa04c688ad7dfb27de2178b",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_FAN_COMPONENT = {
|
||||
"717f924ae9ca4fe9864d845d75d23c9f": {
|
||||
"platform": "fan",
|
||||
"name": "Breezer",
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"percentage_command_topic": "test-topic/pct",
|
||||
"percentage_state_topic": "test-topic/pct",
|
||||
"percentage_command_template": "{{ value }}",
|
||||
"percentage_value_template": "{{ value_json.percentage }}",
|
||||
"payload_reset_percentage": "None",
|
||||
"preset_modes": ["eco", "auto"],
|
||||
"preset_mode_command_topic": "test-topic/prm",
|
||||
"preset_mode_state_topic": "test-topic/prm",
|
||||
"preset_mode_command_template": "{{ value }}",
|
||||
"preset_mode_value_template": "{{ value_json.preset_mode }}",
|
||||
"payload_reset_preset_mode": "None",
|
||||
"oscillation_command_topic": "test-topic/osc",
|
||||
"oscillation_state_topic": "test-topic/osc",
|
||||
"oscillation_command_template": "{{ value }}",
|
||||
"oscillation_value_template": "{{ value_json.oscillation }}",
|
||||
"payload_oscillation_off": "oscillate_off",
|
||||
"payload_oscillation_on": "oscillate_on",
|
||||
"direction_command_topic": "test-topic/dir",
|
||||
"direction_state_topic": "test-topic/dir",
|
||||
"direction_command_template": "{{ value }}",
|
||||
"direction_value_template": "{{ value_json.direction }}",
|
||||
"payload_off": "OFF",
|
||||
"payload_on": "ON",
|
||||
"entity_picture": "https://example.com/717f924ae9ca4fe9864d845d75d23c9f",
|
||||
"optimistic": False,
|
||||
"retain": False,
|
||||
"speed_range_max": 100,
|
||||
"speed_range_min": 1,
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_NOTIFY_COMPONENT1 = {
|
||||
"363a7ecad6be4a19b939a016ea93e994": {
|
||||
"platform": "notify",
|
||||
@ -264,6 +302,10 @@ MOCK_COVER_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_COVER_COMPONENT,
|
||||
}
|
||||
MOCK_FAN_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_FAN_COMPONENT,
|
||||
}
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 1}},
|
||||
"components": MOCK_SUBENTRY_NOTIFY_COMPONENT1,
|
||||
|
@ -36,6 +36,7 @@ from .common import (
|
||||
MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_BUTTON_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_COVER_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_FAN_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_LIGHT_BASIC_KELVIN_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_MULTI,
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_NO_NAME,
|
||||
@ -2785,6 +2786,157 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
),
|
||||
"Milk notifier Blind",
|
||||
),
|
||||
(
|
||||
MOCK_FAN_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Breezer"},
|
||||
{
|
||||
"fan_feature_speed": True,
|
||||
"fan_feature_preset_modes": True,
|
||||
"fan_feature_oscillation": True,
|
||||
"fan_feature_direction": True,
|
||||
},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"fan_speed_settings": {
|
||||
"percentage_command_template": "{{ value }}",
|
||||
"percentage_command_topic": "test-topic/pct",
|
||||
"percentage_state_topic": "test-topic/pct",
|
||||
"percentage_value_template": "{{ value_json.percentage }}",
|
||||
"speed_range_min": 1,
|
||||
"speed_range_max": 100,
|
||||
"payload_reset_percentage": "None",
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"preset_modes": ["eco", "auto"],
|
||||
"preset_mode_command_template": "{{ value }}",
|
||||
"preset_mode_command_topic": "test-topic/prm",
|
||||
"preset_mode_state_topic": "test-topic/prm",
|
||||
"preset_mode_value_template": "{{ value_json.preset_mode }}",
|
||||
"payload_reset_preset_mode": "None",
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"oscillation_command_template": "{{ value }}",
|
||||
"oscillation_command_topic": "test-topic/osc",
|
||||
"oscillation_state_topic": "test-topic/osc",
|
||||
"oscillation_value_template": "{{ value_json.oscillation }}",
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"direction_command_template": "{{ value }}",
|
||||
"direction_command_topic": "test-topic/dir",
|
||||
"direction_state_topic": "test-topic/dir",
|
||||
"direction_value_template": "{{ value_json.direction }}",
|
||||
},
|
||||
"retain": False,
|
||||
"optimistic": False,
|
||||
},
|
||||
(
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic#invalid",
|
||||
"fan_speed_settings": {
|
||||
"percentage_command_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"preset_modes": ["eco", "auto"],
|
||||
"preset_mode_command_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"oscillation_command_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"direction_command_topic": "test-topic#invalid",
|
||||
},
|
||||
},
|
||||
{
|
||||
"command_topic": "invalid_publish_topic",
|
||||
"fan_preset_mode_settings": "invalid_publish_topic",
|
||||
"fan_speed_settings": "invalid_publish_topic",
|
||||
"fan_oscillation_settings": "invalid_publish_topic",
|
||||
"fan_direction_settings": "invalid_publish_topic",
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
"fan_speed_settings": {
|
||||
"percentage_command_topic": "test-topic",
|
||||
"percentage_state_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"preset_modes": ["eco", "auto"],
|
||||
"preset_mode_command_topic": "test-topic",
|
||||
"preset_mode_state_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"oscillation_command_topic": "test-topic",
|
||||
"oscillation_state_topic": "test-topic#invalid",
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"direction_command_topic": "test-topic",
|
||||
"direction_state_topic": "test-topic#invalid",
|
||||
},
|
||||
},
|
||||
{
|
||||
"state_topic": "invalid_subscribe_topic",
|
||||
"fan_preset_mode_settings": "invalid_subscribe_topic",
|
||||
"fan_speed_settings": "invalid_subscribe_topic",
|
||||
"fan_oscillation_settings": "invalid_subscribe_topic",
|
||||
"fan_direction_settings": "invalid_subscribe_topic",
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"fan_speed_settings": {
|
||||
"percentage_command_topic": "test-topic",
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"preset_modes": ["None", "auto"],
|
||||
"preset_mode_command_topic": "test-topic",
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"oscillation_command_topic": "test-topic",
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"direction_command_topic": "test-topic",
|
||||
},
|
||||
},
|
||||
{
|
||||
"fan_preset_mode_settings": "fan_preset_mode_reset_in_preset_modes_list",
|
||||
},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"fan_speed_settings": {
|
||||
"percentage_command_topic": "test-topic",
|
||||
"speed_range_min": 100,
|
||||
"speed_range_max": 10,
|
||||
},
|
||||
"fan_preset_mode_settings": {
|
||||
"preset_modes": ["eco", "auto"],
|
||||
"preset_mode_command_topic": "test-topic",
|
||||
},
|
||||
"fan_oscillation_settings": {
|
||||
"oscillation_command_topic": "test-topic",
|
||||
},
|
||||
"fan_direction_settings": {
|
||||
"direction_command_topic": "test-topic",
|
||||
},
|
||||
},
|
||||
{
|
||||
"fan_speed_settings": "fan_speed_range_max_must_be_greater_than_speed_range_min",
|
||||
},
|
||||
),
|
||||
),
|
||||
"Milk notifier Breezer",
|
||||
),
|
||||
(
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 1}},
|
||||
@ -2971,6 +3123,7 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
"binary_sensor",
|
||||
"button",
|
||||
"cover",
|
||||
"fan",
|
||||
"notify_with_entity_name",
|
||||
"notify_no_entity_name",
|
||||
"sensor_options",
|
||||
|
Loading…
x
Reference in New Issue
Block a user