Allow extra keys in MQTT discovery messages (#58390)

* Allow extra keys in MQTT discovery messages

* Remove extra keys
This commit is contained in:
Erik Montnemery 2021-10-25 13:47:06 +02:00 committed by GitHub
parent a8a8b532d0
commit 640a7fee9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 628 additions and 480 deletions

View File

@ -97,6 +97,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -111,7 +113,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, alarm.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, alarm.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -135,7 +137,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
value_template = self._config.get(CONF_VALUE_TEMPLATE)

View File

@ -58,6 +58,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -72,7 +74,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, binary_sensor.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, binary_sensor.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -101,7 +103,7 @@ class MqttBinarySensor(MqttEntity, BinarySensorEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
value_template = self._config.get(CONF_VALUE_TEMPLATE)

View File

@ -37,6 +37,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -51,7 +53,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, camera.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, camera.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -76,7 +78,7 @@ class MqttCamera(MqttEntity, Camera):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""

View File

@ -268,6 +268,8 @@ PLATFORM_SCHEMA = SCHEMA_BASE.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, async_add_entities, config: ConfigType, discovery_info=None
@ -282,7 +284,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, climate.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, climate.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -319,7 +321,7 @@ class MqttClimate(MqttEntity, ClimateEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
async def async_added_to_hass(self):
"""Handle being added to Home Assistant."""

View File

@ -142,53 +142,58 @@ def validate_options(value):
return value
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_GET_POSITION_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): vol.Any(
cv.string, None
),
vol.Optional(CONF_PAYLOAD_OPEN, default=DEFAULT_PAYLOAD_OPEN): vol.Any(
cv.string, None
),
vol.Optional(CONF_PAYLOAD_STOP, default=DEFAULT_PAYLOAD_STOP): vol.Any(
cv.string, None
),
vol.Optional(CONF_POSITION_CLOSED, default=DEFAULT_POSITION_CLOSED): int,
vol.Optional(CONF_POSITION_OPEN, default=DEFAULT_POSITION_OPEN): int,
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
vol.Optional(CONF_SET_POSITION_TEMPLATE): cv.template,
vol.Optional(CONF_SET_POSITION_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_STATE_CLOSED, default=STATE_CLOSED): cv.string,
vol.Optional(CONF_STATE_CLOSING, default=STATE_CLOSING): cv.string,
vol.Optional(CONF_STATE_OPEN, default=STATE_OPEN): cv.string,
vol.Optional(CONF_STATE_OPENING, default=STATE_OPENING): cv.string,
vol.Optional(CONF_STATE_STOPPED, default=DEFAULT_STATE_STOPPED): cv.string,
vol.Optional(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(
CONF_TILT_CLOSED_POSITION, default=DEFAULT_TILT_CLOSED_POSITION
): int,
vol.Optional(CONF_TILT_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_TILT_MAX, default=DEFAULT_TILT_MAX): int,
vol.Optional(CONF_TILT_MIN, default=DEFAULT_TILT_MIN): int,
vol.Optional(CONF_TILT_OPEN_POSITION, default=DEFAULT_TILT_OPEN_POSITION): int,
vol.Optional(
CONF_TILT_STATE_OPTIMISTIC, default=DEFAULT_TILT_OPTIMISTIC
): cv.boolean,
vol.Optional(CONF_TILT_STATUS_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_TILT_STATUS_TEMPLATE): cv.template,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_GET_POSITION_TEMPLATE): cv.template,
vol.Optional(CONF_TILT_COMMAND_TEMPLATE): cv.template,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_GET_POSITION_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): vol.Any(
cv.string, None
),
vol.Optional(CONF_PAYLOAD_OPEN, default=DEFAULT_PAYLOAD_OPEN): vol.Any(
cv.string, None
),
vol.Optional(CONF_PAYLOAD_STOP, default=DEFAULT_PAYLOAD_STOP): vol.Any(
cv.string, None
),
vol.Optional(CONF_POSITION_CLOSED, default=DEFAULT_POSITION_CLOSED): int,
vol.Optional(CONF_POSITION_OPEN, default=DEFAULT_POSITION_OPEN): int,
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
vol.Optional(CONF_SET_POSITION_TEMPLATE): cv.template,
vol.Optional(CONF_SET_POSITION_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_STATE_CLOSED, default=STATE_CLOSED): cv.string,
vol.Optional(CONF_STATE_CLOSING, default=STATE_CLOSING): cv.string,
vol.Optional(CONF_STATE_OPEN, default=STATE_OPEN): cv.string,
vol.Optional(CONF_STATE_OPENING, default=STATE_OPENING): cv.string,
vol.Optional(CONF_STATE_STOPPED, default=DEFAULT_STATE_STOPPED): cv.string,
vol.Optional(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(
CONF_TILT_CLOSED_POSITION, default=DEFAULT_TILT_CLOSED_POSITION
): int,
vol.Optional(CONF_TILT_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_TILT_MAX, default=DEFAULT_TILT_MAX): int,
vol.Optional(CONF_TILT_MIN, default=DEFAULT_TILT_MIN): int,
vol.Optional(
CONF_TILT_OPEN_POSITION, default=DEFAULT_TILT_OPEN_POSITION
): int,
vol.Optional(
CONF_TILT_STATE_OPTIMISTIC, default=DEFAULT_TILT_OPTIMISTIC
): cv.boolean,
vol.Optional(CONF_TILT_STATUS_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_TILT_STATUS_TEMPLATE): cv.template,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_GET_POSITION_TEMPLATE): cv.template,
vol.Optional(CONF_TILT_COMMAND_TEMPLATE): cv.template,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
validate_options,
)
DISCOVERY_SCHEMA = vol.All(
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
validate_options,
)
@ -206,7 +211,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, cover.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, cover.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -235,7 +240,7 @@ class MqttCover(MqttEntity, CoverEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
no_position = (

View File

@ -37,15 +37,15 @@ PLATFORM_SCHEMA_DISCOVERY = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA_DISCOVERY.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_entry_from_discovery(hass, config_entry, async_add_entities):
"""Set up MQTT device tracker dynamically through MQTT discovery."""
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(
hass, device_tracker.DOMAIN, setup, PLATFORM_SCHEMA_DISCOVERY
)
await async_setup_entry_helper(hass, device_tracker.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -67,7 +67,7 @@ class MqttDeviceTracker(MqttEntity, TrackerEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_DISCOVERY
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -47,7 +47,6 @@ from .mixins import (
MQTT_ENTITY_DEVICE_INFO_SCHEMA,
cleanup_device_registry,
device_info_from_config,
validate_device_has_at_least_one_identifier,
)
_LOGGER = logging.getLogger(__name__)
@ -85,7 +84,7 @@ TRIGGER_DISCOVERY_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
vol.Required(CONF_TYPE): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE, default=None): vol.Any(None, cv.string),
},
validate_device_has_at_least_one_identifier,
extra=vol.REMOVE_EXTRA,
)
DEVICE_TRIGGERS = "mqtt_device_triggers"

View File

@ -113,6 +113,64 @@ def valid_preset_mode_configuration(config):
return config
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_OSCILLATION_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_OSCILLATION_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_PERCENTAGE_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_PERCENTAGE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_PERCENTAGE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PERCENTAGE_VALUE_TEMPLATE): cv.template,
# CONF_PRESET_MODE_COMMAND_TOPIC and CONF_PRESET_MODES_LIST must be used together
vol.Inclusive(
CONF_PRESET_MODE_COMMAND_TOPIC, "preset_modes"
): mqtt.valid_publish_topic,
vol.Inclusive(
CONF_PRESET_MODES_LIST, "preset_modes", default=[]
): cv.ensure_list,
vol.Optional(CONF_PRESET_MODE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_PRESET_MODE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PRESET_MODE_VALUE_TEMPLATE): cv.template,
vol.Optional(
CONF_SPEED_RANGE_MIN, default=DEFAULT_SPEED_RANGE_MIN
): cv.positive_int,
vol.Optional(
CONF_SPEED_RANGE_MAX, default=DEFAULT_SPEED_RANGE_MAX
): cv.positive_int,
vol.Optional(
CONF_PAYLOAD_RESET_PERCENTAGE, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(
CONF_PAYLOAD_RESET_PRESET_MODE, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(CONF_PAYLOAD_HIGH_SPEED, default=SPEED_HIGH): cv.string,
vol.Optional(CONF_PAYLOAD_LOW_SPEED, default=SPEED_LOW): cv.string,
vol.Optional(CONF_PAYLOAD_MEDIUM_SPEED, default=SPEED_MEDIUM): cv.string,
vol.Optional(CONF_PAYLOAD_OFF_SPEED, default=SPEED_OFF): cv.string,
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
): cv.string,
vol.Optional(
CONF_PAYLOAD_OSCILLATION_ON, default=OSCILLATE_ON_PAYLOAD
): cv.string,
vol.Optional(CONF_SPEED_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(
CONF_SPEED_LIST,
default=[SPEED_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH],
): cv.ensure_list,
vol.Optional(CONF_SPEED_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_SPEED_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
# CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_LIST, CONF_SPEED_STATE_TOPIC, CONF_SPEED_VALUE_TEMPLATE and
# Speeds SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH SPEED_OFF,
@ -124,63 +182,23 @@ PLATFORM_SCHEMA = vol.All(
cv.deprecated(CONF_SPEED_LIST),
cv.deprecated(CONF_SPEED_STATE_TOPIC),
cv.deprecated(CONF_SPEED_VALUE_TEMPLATE),
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_OSCILLATION_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_OSCILLATION_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_PERCENTAGE_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_PERCENTAGE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_PERCENTAGE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PERCENTAGE_VALUE_TEMPLATE): cv.template,
# CONF_PRESET_MODE_COMMAND_TOPIC and CONF_PRESET_MODES_LIST must be used together
vol.Inclusive(
CONF_PRESET_MODE_COMMAND_TOPIC, "preset_modes"
): mqtt.valid_publish_topic,
vol.Inclusive(
CONF_PRESET_MODES_LIST, "preset_modes", default=[]
): cv.ensure_list,
vol.Optional(CONF_PRESET_MODE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_PRESET_MODE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_PRESET_MODE_VALUE_TEMPLATE): cv.template,
vol.Optional(
CONF_SPEED_RANGE_MIN, default=DEFAULT_SPEED_RANGE_MIN
): cv.positive_int,
vol.Optional(
CONF_SPEED_RANGE_MAX, default=DEFAULT_SPEED_RANGE_MAX
): cv.positive_int,
vol.Optional(
CONF_PAYLOAD_RESET_PERCENTAGE, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(
CONF_PAYLOAD_RESET_PRESET_MODE, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(CONF_PAYLOAD_HIGH_SPEED, default=SPEED_HIGH): cv.string,
vol.Optional(CONF_PAYLOAD_LOW_SPEED, default=SPEED_LOW): cv.string,
vol.Optional(CONF_PAYLOAD_MEDIUM_SPEED, default=SPEED_MEDIUM): cv.string,
vol.Optional(CONF_PAYLOAD_OFF_SPEED, default=SPEED_OFF): cv.string,
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
): cv.string,
vol.Optional(
CONF_PAYLOAD_OSCILLATION_ON, default=OSCILLATE_ON_PAYLOAD
): cv.string,
vol.Optional(CONF_SPEED_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(
CONF_SPEED_LIST,
default=[SPEED_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH],
): cv.ensure_list,
vol.Optional(CONF_SPEED_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_SPEED_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_STATE_VALUE_TEMPLATE): cv.template,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
valid_speed_range_configuration,
valid_preset_mode_configuration,
)
DISCOVERY_SCHEMA = vol.All(
# CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_LIST, CONF_SPEED_STATE_TOPIC, CONF_SPEED_VALUE_TEMPLATE and
# Speeds SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH SPEED_OFF,
# are deprecated, support will be removed with release 2021.9
cv.deprecated(CONF_PAYLOAD_HIGH_SPEED),
cv.deprecated(CONF_PAYLOAD_LOW_SPEED),
cv.deprecated(CONF_PAYLOAD_MEDIUM_SPEED),
cv.deprecated(CONF_SPEED_COMMAND_TOPIC),
cv.deprecated(CONF_SPEED_LIST),
cv.deprecated(CONF_SPEED_STATE_TOPIC),
cv.deprecated(CONF_SPEED_VALUE_TEMPLATE),
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
valid_speed_range_configuration,
valid_preset_mode_configuration,
)
@ -199,7 +217,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, fan.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, fan.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -236,7 +254,7 @@ class MqttFan(MqttEntity, FanEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -86,46 +86,52 @@ def valid_humidity_range_configuration(config):
return config
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
# CONF_AVAIALABLE_MODES_LIST and CONF_MODE_COMMAND_TOPIC must be used together
vol.Inclusive(
CONF_AVAILABLE_MODES_LIST, "available_modes", default=[]
): cv.ensure_list,
vol.Inclusive(
CONF_MODE_COMMAND_TOPIC, "available_modes"
): mqtt.valid_publish_topic,
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_HUMIDIFIER): vol.In(
[DEVICE_CLASS_HUMIDIFIER, DEVICE_CLASS_DEHUMIDIFIER]
),
vol.Optional(CONF_MODE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_MODE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
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_STATE_VALUE_TEMPLATE): cv.template,
vol.Required(CONF_TARGET_HUMIDITY_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_TARGET_HUMIDITY_COMMAND_TEMPLATE): cv.template,
vol.Optional(
CONF_TARGET_HUMIDITY_MAX, default=DEFAULT_MAX_HUMIDITY
): cv.positive_int,
vol.Optional(
CONF_TARGET_HUMIDITY_MIN, default=DEFAULT_MIN_HUMIDITY
): cv.positive_int,
vol.Optional(CONF_TARGET_HUMIDITY_STATE_TEMPLATE): cv.template,
vol.Optional(CONF_TARGET_HUMIDITY_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(
CONF_PAYLOAD_RESET_HUMIDITY, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(CONF_PAYLOAD_RESET_MODE, default=DEFAULT_PAYLOAD_RESET): cv.string,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
# CONF_AVAIALABLE_MODES_LIST and CONF_MODE_COMMAND_TOPIC must be used together
vol.Inclusive(
CONF_AVAILABLE_MODES_LIST, "available_modes", default=[]
): cv.ensure_list,
vol.Inclusive(
CONF_MODE_COMMAND_TOPIC, "available_modes"
): mqtt.valid_publish_topic,
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_HUMIDIFIER): vol.In(
[DEVICE_CLASS_HUMIDIFIER, DEVICE_CLASS_DEHUMIDIFIER]
),
vol.Optional(CONF_MODE_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_MODE_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_MODE_STATE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
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_STATE_VALUE_TEMPLATE): cv.template,
vol.Required(CONF_TARGET_HUMIDITY_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_TARGET_HUMIDITY_COMMAND_TEMPLATE): cv.template,
vol.Optional(
CONF_TARGET_HUMIDITY_MAX, default=DEFAULT_MAX_HUMIDITY
): cv.positive_int,
vol.Optional(
CONF_TARGET_HUMIDITY_MIN, default=DEFAULT_MIN_HUMIDITY
): cv.positive_int,
vol.Optional(CONF_TARGET_HUMIDITY_STATE_TEMPLATE): cv.template,
vol.Optional(CONF_TARGET_HUMIDITY_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(
CONF_PAYLOAD_RESET_HUMIDITY, default=DEFAULT_PAYLOAD_RESET
): cv.string,
vol.Optional(
CONF_PAYLOAD_RESET_MODE, default=DEFAULT_PAYLOAD_RESET
): cv.string,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
valid_humidity_range_configuration,
valid_mode_configuration,
)
DISCOVERY_SCHEMA = vol.All(
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
valid_humidity_range_configuration,
valid_mode_configuration,
)
@ -144,7 +150,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, humidifier.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, humidifier.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -179,7 +185,7 @@ class MqttHumidifier(MqttEntity, HumidifierEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -11,9 +11,31 @@ from homeassistant.helpers.typing import ConfigType
from .. import DOMAIN, PLATFORMS
from ..mixins import async_setup_entry_helper
from .schema import CONF_SCHEMA, MQTT_LIGHT_SCHEMA_SCHEMA
from .schema_basic import PLATFORM_SCHEMA_BASIC, async_setup_entity_basic
from .schema_json import PLATFORM_SCHEMA_JSON, async_setup_entity_json
from .schema_template import PLATFORM_SCHEMA_TEMPLATE, async_setup_entity_template
from .schema_basic import (
DISCOVERY_SCHEMA_BASIC,
PLATFORM_SCHEMA_BASIC,
async_setup_entity_basic,
)
from .schema_json import (
DISCOVERY_SCHEMA_JSON,
PLATFORM_SCHEMA_JSON,
async_setup_entity_json,
)
from .schema_template import (
DISCOVERY_SCHEMA_TEMPLATE,
PLATFORM_SCHEMA_TEMPLATE,
async_setup_entity_template,
)
def validate_mqtt_light_discovery(value):
"""Validate MQTT light schema."""
schemas = {
"basic": DISCOVERY_SCHEMA_BASIC,
"json": DISCOVERY_SCHEMA_JSON,
"template": DISCOVERY_SCHEMA_TEMPLATE,
}
return schemas[value[CONF_SCHEMA]](value)
def validate_mqtt_light(value):
@ -26,6 +48,12 @@ def validate_mqtt_light(value):
return schemas[value[CONF_SCHEMA]](value)
DISCOVERY_SCHEMA = vol.All(
MQTT_LIGHT_SCHEMA_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA),
validate_mqtt_light_discovery,
)
PLATFORM_SCHEMA = vol.All(
MQTT_LIGHT_SCHEMA_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA), validate_mqtt_light
)
@ -44,7 +72,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, light.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, light.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(

View File

@ -152,9 +152,7 @@ VALUE_TEMPLATE_KEYS = [
CONF_XY_VALUE_TEMPLATE,
]
PLATFORM_SCHEMA_BASIC = vol.All(
# CONF_VALUE_TEMPLATE is deprecated, support will be removed in 2021.10
cv.deprecated(CONF_VALUE_TEMPLATE, CONF_STATE_VALUE_TEMPLATE),
_PLATFORM_SCHEMA_BASE = (
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_BRIGHTNESS_COMMAND_TOPIC): mqtt.valid_publish_topic,
@ -212,10 +210,22 @@ PLATFORM_SCHEMA_BASIC = vol.All(
vol.Optional(CONF_XY_COMMAND_TOPIC): mqtt.valid_publish_topic,
vol.Optional(CONF_XY_STATE_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_XY_VALUE_TEMPLATE): cv.template,
}
},
)
.extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
.extend(MQTT_LIGHT_SCHEMA_SCHEMA.schema),
.extend(MQTT_LIGHT_SCHEMA_SCHEMA.schema)
)
PLATFORM_SCHEMA_BASIC = vol.All(
# CONF_VALUE_TEMPLATE is deprecated, support will be removed in 2021.10
cv.deprecated(CONF_VALUE_TEMPLATE, CONF_STATE_VALUE_TEMPLATE),
_PLATFORM_SCHEMA_BASE,
)
DISCOVERY_SCHEMA_BASIC = vol.All(
# CONF_VALUE_TEMPLATE is deprecated, support will be removed in 2021.10
cv.deprecated(CONF_VALUE_TEMPLATE, CONF_STATE_VALUE_TEMPLATE),
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
)
@ -268,7 +278,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_BASIC
return DISCOVERY_SCHEMA_BASIC
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -102,7 +102,7 @@ def valid_color_configuration(config):
return config
PLATFORM_SCHEMA_JSON = vol.All(
_PLATFORM_SCHEMA_BASE = (
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_BRIGHTNESS, default=DEFAULT_BRIGHTNESS): cv.boolean,
@ -143,7 +143,16 @@ PLATFORM_SCHEMA_JSON = vol.All(
},
)
.extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
.extend(MQTT_LIGHT_SCHEMA_SCHEMA.schema),
.extend(MQTT_LIGHT_SCHEMA_SCHEMA.schema)
)
PLATFORM_SCHEMA_JSON = vol.All(
_PLATFORM_SCHEMA_BASE,
valid_color_configuration,
)
DISCOVERY_SCHEMA_JSON = vol.All(
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
valid_color_configuration,
)
@ -184,7 +193,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_JSON
return DISCOVERY_SCHEMA_JSON
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -84,6 +84,8 @@ PLATFORM_SCHEMA_TEMPLATE = (
.extend(MQTT_LIGHT_SCHEMA_SCHEMA.schema)
)
DISCOVERY_SCHEMA_TEMPLATE = PLATFORM_SCHEMA_TEMPLATE.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_entity_template(
hass, config, async_add_entities, config_entry, discovery_data
@ -117,7 +119,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_TEMPLATE
return DISCOVERY_SCHEMA_TEMPLATE
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -49,6 +49,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -63,7 +65,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, lock.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, lock.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -88,7 +90,7 @@ class MqttLock(MqttEntity, LockEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -59,21 +59,28 @@ def validate_config(config):
return config
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
vol.Optional(CONF_STEP, default=DEFAULT_STEP): vol.All(
vol.Coerce(float), vol.Range(min=1e-3)
),
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
},
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string,
vol.Optional(CONF_STEP, default=DEFAULT_STEP): vol.All(
vol.Coerce(float), vol.Range(min=1e-3)
),
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
},
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
validate_config,
)
DISCOVERY_SCHEMA = vol.All(
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
validate_config,
)
@ -91,7 +98,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, number.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, number.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -120,7 +127,7 @@ class MqttNumber(MqttEntity, NumberEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -35,6 +35,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_AVAILABILITY_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -49,7 +51,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, scene.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, scene.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -85,7 +87,7 @@ class MqttScene(
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
config = DISCOVERY_SCHEMA(discovery_payload)
self._setup_from_config(config)
await self.availability_discovery_update(config)
self.async_write_ha_state()

View File

@ -41,15 +41,22 @@ def validate_config(config):
return config
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Required(CONF_OPTIONS): cv.ensure_list,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
},
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Required(CONF_OPTIONS): cv.ensure_list,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
},
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
validate_config,
)
DISCOVERY_SCHEMA = vol.All(
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
validate_config,
)
@ -67,7 +74,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, select.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, select.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -96,7 +103,7 @@ class MqttSelect(MqttEntity, SelectEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -80,20 +80,28 @@ def validate_options(conf):
return conf
_PLATFORM_SCHEMA_BASE = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_LAST_RESET_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_STATE_CLASS): STATE_CLASSES_SCHEMA,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
PLATFORM_SCHEMA = vol.All(
cv.deprecated(CONF_LAST_RESET_TOPIC),
mqtt.MQTT_RO_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_LAST_RESET_TOPIC): mqtt.valid_subscribe_topic,
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_STATE_CLASS): STATE_CLASSES_SCHEMA,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema),
_PLATFORM_SCHEMA_BASE,
validate_options,
)
DISCOVERY_SCHEMA = vol.All(
cv.deprecated(CONF_LAST_RESET_TOPIC),
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
validate_options,
)
@ -111,7 +119,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, sensor.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, sensor.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -143,7 +151,7 @@ class MqttSensor(MqttEntity, SensorEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -51,6 +51,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
DISCOVERY_SCHEMA = PLATFORM_SCHEMA.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_platform(
hass: HomeAssistant, config: ConfigType, async_add_entities, discovery_info=None
@ -65,7 +67,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, switch.DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, switch.DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(
@ -93,7 +95,7 @@ class MqttSwitch(MqttEntity, SwitchEntity, RestoreEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA
return DISCOVERY_SCHEMA
def _setup_from_config(self, config):
"""(Re)Setup the entity."""

View File

@ -29,7 +29,6 @@ from .mixins import (
async_setup_entry_helper,
cleanup_device_registry,
device_info_from_config,
validate_device_has_at_least_one_identifier,
)
from .util import valid_subscribe_topic
@ -45,7 +44,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
vol.Required(CONF_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
},
validate_device_has_at_least_one_identifier,
extra=vol.REMOVE_EXTRA,
)

View File

@ -9,8 +9,22 @@ from homeassistant.helpers.reload import async_setup_reload_service
from .. import DOMAIN as MQTT_DOMAIN, PLATFORMS
from ..mixins import async_setup_entry_helper
from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE
from .schema_legacy import PLATFORM_SCHEMA_LEGACY, async_setup_entity_legacy
from .schema_state import PLATFORM_SCHEMA_STATE, async_setup_entity_state
from .schema_legacy import (
DISCOVERY_SCHEMA_LEGACY,
PLATFORM_SCHEMA_LEGACY,
async_setup_entity_legacy,
)
from .schema_state import (
DISCOVERY_SCHEMA_STATE,
PLATFORM_SCHEMA_STATE,
async_setup_entity_state,
)
def validate_mqtt_vacuum_discovery(value):
"""Validate MQTT vacuum schema."""
schemas = {LEGACY: DISCOVERY_SCHEMA_LEGACY, STATE: DISCOVERY_SCHEMA_STATE}
return schemas[value[CONF_SCHEMA]](value)
def validate_mqtt_vacuum(value):
@ -19,6 +33,10 @@ def validate_mqtt_vacuum(value):
return schemas[value[CONF_SCHEMA]](value)
DISCOVERY_SCHEMA = vol.All(
MQTT_VACUUM_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA), validate_mqtt_vacuum_discovery
)
PLATFORM_SCHEMA = vol.All(
MQTT_VACUUM_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA), validate_mqtt_vacuum
)
@ -35,7 +53,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
setup = functools.partial(
_async_setup_entity, hass, async_add_entities, config_entry=config_entry
)
await async_setup_entry_helper(hass, DOMAIN, setup, PLATFORM_SCHEMA)
await async_setup_entry_helper(hass, DOMAIN, setup, DISCOVERY_SCHEMA)
async def _async_setup_entity(

View File

@ -156,6 +156,8 @@ PLATFORM_SCHEMA_LEGACY = (
.extend(MQTT_VACUUM_SCHEMA.schema)
)
DISCOVERY_SCHEMA_LEGACY = PLATFORM_SCHEMA_LEGACY.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_entity_legacy(
hass, config, async_add_entities, config_entry, discovery_data
@ -185,7 +187,7 @@ class MqttVacuum(MqttEntity, VacuumEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_LEGACY
return DISCOVERY_SCHEMA_LEGACY
def _setup_from_config(self, config):
supported_feature_strings = config[CONF_SUPPORTED_FEATURES]

View File

@ -136,6 +136,9 @@ PLATFORM_SCHEMA_STATE = (
)
DISCOVERY_SCHEMA_STATE = PLATFORM_SCHEMA_STATE.extend({}, extra=vol.REMOVE_EXTRA)
async def async_setup_entity_state(
hass, config, async_add_entities, config_entry, discovery_data
):
@ -159,7 +162,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
@staticmethod
def config_schema():
"""Return the config schema."""
return PLATFORM_SCHEMA_STATE
return DISCOVERY_SCHEMA_STATE
def _setup_from_config(self, config):
supported_feature_strings = config[CONF_SUPPORTED_FEATURES]

View File

@ -625,15 +625,13 @@ async def test_discovery_update_alarm_topic_and_template(hass, mqtt_mock, caplog
([("alarm/state2", '{"state2":{"state":"triggered"}}')], "triggered", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
alarm_control_panel.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)
@ -658,15 +656,13 @@ async def test_discovery_update_alarm_template(hass, mqtt_mock, caplog):
([("alarm/state1", '{"state2":{"state":"triggered"}}')], "triggered", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
alarm_control_panel.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -679,15 +679,13 @@ async def test_discovery_update_binary_sensor_topic_template(hass, mqtt_mock, ca
([("sensor/state2", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
binary_sensor.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)
@ -714,15 +712,13 @@ async def test_discovery_update_binary_sensor_template(hass, mqtt_mock, caplog):
([("sensor/state1", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
binary_sensor.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -161,11 +161,11 @@ async def test_discovery_removal_camera(hass, mqtt_mock, caplog):
async def test_discovery_update_camera(hass, mqtt_mock, caplog):
"""Test update of discovered camera."""
data1 = '{ "name": "Beer", "topic": "test_topic"}'
data2 = '{ "name": "Milk", "topic": "test_topic"}'
config1 = {"name": "Beer", "topic": "test_topic"}
config2 = {"name": "Milk", "topic": "test_topic"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, camera.DOMAIN, data1, data2
hass, mqtt_mock, caplog, camera.DOMAIN, config1, config2
)

View File

@ -991,10 +991,10 @@ async def test_discovery_removal_climate(hass, mqtt_mock, caplog):
async def test_discovery_update_climate(hass, mqtt_mock, caplog):
"""Test update of discovered climate."""
data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk" }'
config1 = {"name": "Beer"}
config2 = {"name": "Milk"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, CLIMATE_DOMAIN, data1, data2
hass, mqtt_mock, caplog, CLIMATE_DOMAIN, config1, config2
)

View File

@ -662,8 +662,8 @@ async def help_test_discovery_update(
mqtt_mock,
caplog,
domain,
discovery_data1,
discovery_data2,
discovery_config1,
discovery_config2,
state_data1=None,
state_data2=None,
):
@ -671,6 +671,14 @@ async def help_test_discovery_update(
This is a test helper for the MqttDiscoveryUpdate mixin.
"""
# Add some future configuration to the configurations
config1 = copy.deepcopy(discovery_config1)
config1["some_future_option_1"] = "future_option_1"
config2 = copy.deepcopy(discovery_config2)
config2["some_future_option_2"] = "future_option_2"
discovery_data1 = json.dumps(config1)
discovery_data2 = json.dumps(config2)
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", discovery_data1)
await hass.async_block_till_done()

View File

@ -2401,10 +2401,10 @@ async def test_discovery_removal_cover(hass, mqtt_mock, caplog):
async def test_discovery_update_cover(hass, mqtt_mock, caplog):
"""Test update of discovered cover."""
data1 = '{ "name": "Beer", "command_topic": "test_topic" }'
data2 = '{ "name": "Milk", "command_topic": "test_topic" }'
config1 = {"name": "Beer", "command_topic": "test_topic"}
config2 = {"name": "Milk", "command_topic": "test_topic"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, cover.DOMAIN, data1, data2
hass, mqtt_mock, caplog, cover.DOMAIN, config1, config2
)

View File

@ -130,7 +130,7 @@ async def test_discover_bad_triggers(hass, device_reg, entity_reg, mqtt_mock):
'{ "automation_type":"trigger",'
' "device":{"identifiers":["0AFFD2"]},'
' "payloads": "short_press",'
' "topic": "foobar/triggers/button1",'
' "topics": "foobar/triggers/button1",'
' "type": "button_short_press",'
' "subtype": "button_1" }'
)
@ -167,22 +167,28 @@ async def test_discover_bad_triggers(hass, device_reg, entity_reg, mqtt_mock):
async def test_update_remove_triggers(hass, device_reg, entity_reg, mqtt_mock):
"""Test triggers can be updated and removed."""
data1 = (
'{ "automation_type":"trigger",'
' "device":{"identifiers":["0AFFD2"]},'
' "payload": "short_press",'
' "topic": "foobar/triggers/button1",'
' "type": "button_short_press",'
' "subtype": "button_1" }'
)
data2 = (
'{ "automation_type":"trigger",'
' "device":{"identifiers":["0AFFD2"]},'
' "payload": "short_press",'
' "topic": "foobar/triggers/button1",'
' "type": "button_short_press",'
' "subtype": "button_2" }'
)
config1 = {
"automation_type": "trigger",
"device": {"identifiers": ["0AFFD2"]},
"payload": "short_press",
"topic": "foobar/triggers/button1",
"type": "button_short_press",
"subtype": "button_1",
}
config1["some_future_option_1"] = "future_option_1"
data1 = json.dumps(config1)
config2 = {
"automation_type": "trigger",
"device": {"identifiers": ["0AFFD2"]},
"payload": "short_press",
"topic": "foobar/triggers/button1",
"type": "button_short_press",
"subtype": "button_2",
}
config2["topic"] = "foobar/tag_scanned2"
data2 = json.dumps(config2)
async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data1)
await hass.async_block_till_done()

View File

@ -1590,9 +1590,11 @@ async def test_discovery_removal_fan(hass, mqtt_mock, caplog):
async def test_discovery_update_fan(hass, mqtt_mock, caplog):
"""Test update of discovered fan."""
data1 = '{ "name": "Beer", "command_topic": "test_topic" }'
data2 = '{ "name": "Milk", "command_topic": "test_topic" }'
await help_test_discovery_update(hass, mqtt_mock, caplog, fan.DOMAIN, data1, data2)
config1 = {"name": "Beer", "command_topic": "test_topic"}
config2 = {"name": "Milk", "command_topic": "test_topic"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, fan.DOMAIN, config1, config2
)
async def test_discovery_update_unchanged_fan(hass, mqtt_mock, caplog):

View File

@ -975,10 +975,18 @@ async def test_discovery_removal_humidifier(hass, mqtt_mock, caplog):
async def test_discovery_update_humidifier(hass, mqtt_mock, caplog):
"""Test update of discovered humidifier."""
data1 = '{ "name": "Beer", "command_topic": "test_topic", "target_humidity_command_topic": "test-topic2" }'
data2 = '{ "name": "Milk", "command_topic": "test_topic", "target_humidity_command_topic": "test-topic2" }'
config1 = {
"name": "Beer",
"command_topic": "test_topic",
"target_humidity_command_topic": "test-topic2",
}
config2 = {
"name": "Milk",
"command_topic": "test_topic",
"target_humidity_command_topic": "test-topic2",
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, humidifier.DOMAIN, data1, data2
hass, mqtt_mock, caplog, humidifier.DOMAIN, config1, config2
)

View File

@ -651,10 +651,10 @@ async def test_discovery_removal_vacuum(hass, mqtt_mock, caplog):
async def test_discovery_update_vacuum(hass, mqtt_mock, caplog):
"""Test update of discovered vacuum."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }'
config1 = {"name": "Beer", " " "command_topic": "test_topic"}
config2 = {"name": "Milk", " " "command_topic": "test_topic"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
hass, mqtt_mock, caplog, vacuum.DOMAIN, config1, config2
)

View File

@ -153,7 +153,6 @@ light:
payload_off: "off"
"""
import json
from os import path
from unittest.mock import call, patch
@ -2798,65 +2797,61 @@ async def test_discovery_deprecated(hass, mqtt_mock, caplog):
async def test_discovery_update_light_topic_and_template(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = json.dumps(
{
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
)
config1 = {
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
data2 = json.dumps(
{
"name": "Milk",
"state_topic": "test_light_rgb/state2",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state2",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state2",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state2",
"color_temp_state_topic": "test_light_rgb/state2",
"effect_state_topic": "test_light_rgb/state2",
"hs_state_topic": "test_light_rgb/state2",
"rgb_state_topic": "test_light_rgb/state2",
"white_value_state_topic": "test_light_rgb/state2",
"xy_state_topic": "test_light_rgb/state2",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
)
config2 = {
"name": "Milk",
"state_topic": "test_light_rgb/state2",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state2",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state2",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state2",
"color_temp_state_topic": "test_light_rgb/state2",
"effect_state_topic": "test_light_rgb/state2",
"hs_state_topic": "test_light_rgb/state2",
"rgb_state_topic": "test_light_rgb/state2",
"white_value_state_topic": "test_light_rgb/state2",
"xy_state_topic": "test_light_rgb/state2",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
state_data1 = [
(
[
@ -3054,8 +3049,8 @@ async def test_discovery_update_light_topic_and_template(hass, mqtt_mock, caplog
mqtt_mock,
caplog,
light.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)
@ -3063,65 +3058,61 @@ async def test_discovery_update_light_topic_and_template(hass, mqtt_mock, caplog
async def test_discovery_update_light_template(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = json.dumps(
{
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
)
config1 = {
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
data2 = json.dumps(
{
"name": "Milk",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
)
config2 = {
"name": "Milk",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
state_data1 = [
(
[
@ -3277,8 +3268,8 @@ async def test_discovery_update_light_template(hass, mqtt_mock, caplog):
mqtt_mock,
caplog,
light.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -1786,20 +1786,20 @@ async def test_discovery_removal(hass, mqtt_mock, caplog):
async def test_discovery_update_light(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = (
'{ "name": "Beer",'
' "schema": "json",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic" }'
)
data2 = (
'{ "name": "Milk",'
' "schema": "json",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic" }'
)
config1 = {
"name": "Beer",
"schema": "json",
"state_topic": "test_topic",
"command_topic": "test_topic",
}
config2 = {
"name": "Milk",
"schema": "json",
"state_topic": "test_topic",
"command_topic": "test_topic",
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
hass, mqtt_mock, caplog, light.DOMAIN, config1, config2
)

View File

@ -950,24 +950,24 @@ async def test_discovery_removal(hass, mqtt_mock, caplog):
async def test_discovery_update_light(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = (
'{ "name": "Beer",'
' "schema": "template",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic",'
' "command_on_template": "on",'
' "command_off_template": "off"}'
)
data2 = (
'{ "name": "Milk",'
' "schema": "template",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic",'
' "command_on_template": "on",'
' "command_off_template": "off"}'
)
config1 = {
"name": "Beer",
"schema": "template",
"state_topic": "test_topic",
"command_topic": "test_topic",
"command_on_template": "on",
"command_off_template": "off",
}
config2 = {
"name": "Milk",
"schema": "template",
"state_topic": "test_topic",
"command_topic": "test_topic",
"command_on_template": "on",
"command_off_template": "off",
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, light.DOMAIN, data1, data2
hass, mqtt_mock, caplog, light.DOMAIN, config1, config2
)

View File

@ -379,19 +379,21 @@ async def test_discovery_removal_lock(hass, mqtt_mock, caplog):
async def test_discovery_update_lock(hass, mqtt_mock, caplog):
"""Test update of discovered lock."""
data1 = (
'{ "name": "Beer",'
' "state_topic": "test_topic",'
' "command_topic": "command_topic",'
' "availability_topic": "availability_topic1" }'
config1 = {
"name": "Beer",
"state_topic": "test_topic",
"command_topic": "command_topic",
"availability_topic": "availability_topic1",
}
config2 = {
"name": "Milk",
"state_topic": "test_topic2",
"command_topic": "command_topic",
"availability_topic": "availability_topic2",
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, LOCK_DOMAIN, config1, config2
)
data2 = (
'{ "name": "Milk",'
' "state_topic": "test_topic2",'
' "command_topic": "command_topic",'
' "availability_topic": "availability_topic2" }'
)
await help_test_discovery_update(hass, mqtt_mock, caplog, LOCK_DOMAIN, data1, data2)
async def test_discovery_update_unchanged_lock(hass, mqtt_mock, caplog):

View File

@ -344,15 +344,19 @@ async def test_discovery_removal_number(hass, mqtt_mock, caplog):
async def test_discovery_update_number(hass, mqtt_mock, caplog):
"""Test update of discovered number."""
data1 = (
'{ "name": "Beer", "state_topic": "test-topic", "command_topic": "test-topic"}'
)
data2 = (
'{ "name": "Milk", "state_topic": "test-topic", "command_topic": "test-topic"}'
)
config1 = {
"name": "Beer",
"state_topic": "test-topic",
"command_topic": "test-topic",
}
config2 = {
"name": "Milk",
"state_topic": "test-topic",
"command_topic": "test-topic",
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, number.DOMAIN, data1, data2
hass, mqtt_mock, caplog, number.DOMAIN, config1, config2
)

View File

@ -1,6 +1,5 @@
"""The tests for the MQTT scene platform."""
import copy
import json
from unittest.mock import patch
import pytest
@ -147,15 +146,13 @@ async def test_discovery_update_payload(hass, mqtt_mock, caplog):
config1["payload_on"] = "ON"
config2["payload_on"] = "ACTIVATE"
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
scene.DOMAIN,
data1,
data2,
config1,
config2,
)

View File

@ -309,11 +309,21 @@ async def test_discovery_removal_select(hass, mqtt_mock, caplog):
async def test_discovery_update_select(hass, mqtt_mock, caplog):
"""Test update of discovered select."""
data1 = '{ "name": "Beer", "state_topic": "test-topic", "command_topic": "test-topic", "options": ["milk", "beer"]}'
data2 = '{ "name": "Milk", "state_topic": "test-topic", "command_topic": "test-topic", "options": ["milk", "beer"]}'
config1 = {
"name": "Beer",
"state_topic": "test-topic",
"command_topic": "test-topic",
"options": ["milk", "beer"],
}
config2 = {
"name": "Milk",
"state_topic": "test-topic",
"command_topic": "test-topic",
"options": ["milk", "beer"],
}
await help_test_discovery_update(
hass, mqtt_mock, caplog, select.DOMAIN, data1, data2
hass, mqtt_mock, caplog, select.DOMAIN, config1, config2
)

View File

@ -661,15 +661,13 @@ async def test_discovery_update_sensor_topic_template(hass, mqtt_mock, caplog):
([("sensor/state2", '{"state":100}')], "200", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
sensor.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)
@ -694,15 +692,13 @@ async def test_discovery_update_sensor_template(hass, mqtt_mock, caplog):
([("sensor/state1", '{"state":100}')], "200", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
sensor.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -427,10 +427,10 @@ async def test_discovery_removal_vacuum(hass, mqtt_mock, caplog):
async def test_discovery_update_vacuum(hass, mqtt_mock, caplog):
"""Test update of discovered vacuum."""
data1 = '{ "schema": "state", "name": "Beer", "command_topic": "test_topic"}'
data2 = '{ "schema": "state", "name": "Milk", "command_topic": "test_topic"}'
config1 = {"schema": "state", "name": "Beer", "command_topic": "test_topic"}
config2 = {"schema": "state", "name": "Milk", "command_topic": "test_topic"}
await help_test_discovery_update(
hass, mqtt_mock, caplog, vacuum.DOMAIN, data1, data2
hass, mqtt_mock, caplog, vacuum.DOMAIN, config1, config2
)

View File

@ -1,6 +1,5 @@
"""The tests for the MQTT switch platform."""
import copy
import json
from unittest.mock import patch
import pytest
@ -339,15 +338,13 @@ async def test_discovery_update_switch_topic_template(hass, mqtt_mock, caplog):
([("switch/state2", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
switch.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)
@ -374,15 +371,13 @@ async def test_discovery_update_switch_template(hass, mqtt_mock, caplog):
([("switch/state1", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
switch.DOMAIN,
data1,
data2,
config1,
config2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -144,7 +144,9 @@ async def test_if_fires_on_mqtt_message_after_update_with_device(
):
"""Test tag scanning after update."""
config1 = copy.deepcopy(DEFAULT_CONFIG_DEVICE)
config1["some_future_option_1"] = "future_option_1"
config2 = copy.deepcopy(DEFAULT_CONFIG_DEVICE)
config2["some_future_option_2"] = "future_option_2"
config2["topic"] = "foobar/tag_scanned2"
async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config1))