class BinarySensorSchema: """Schema validation for binary sensors.""" CONF_IGNORE_INTERNAL_STATE = "ignore_internal_state" CONF_CONTEXT_TIMEOUT = "context_timeout" CONF_RESET_AFTER = "reset_after" CONF_DEVICE_CLASS = "device_class" SCHEMA = BaseDeviceSchema.SCHEMA.extend({ vol.Required(CONF_ADDRESS): RemoteValueSchema.SCHEMA.extend({ vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, }), vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=True): boolean, vol.Optional(CONF_CONTEXT_TIMEOUT, default=1.0): vol.All(vol.Coerce(float), vol.Range(min=0, max=10)), vol.Optional(CONF_DEVICE_CLASS): string, vol.Optional(CONF_RESET_AFTER): positive_int, })
class MediaSelector(Selector): """Selector for media.""" selector_type = "media" CONFIG_SCHEMA = vol.Schema({}) DATA_SCHEMA = vol.Schema({ # Although marked as optional in frontend, this field is required vol.Required("entity_id"): cv.entity_id_or_uuid, # Although marked as optional in frontend, this field is required vol.Required("media_content_id"): str, # Although marked as optional in frontend, this field is required vol.Required("media_content_type"): str, vol.Remove("metadata"): dict, }) def __init__(self, config: MediaSelectorConfig | None = None) -> None: """Instantiate a selector.""" super().__init__(config) def __call__(self, data: Any) -> dict[str, float]: """Validate the passed selection.""" media: dict[str, float] = self.DATA_SCHEMA(data) return media
class CoverSchema: """Voluptuous schema for KNX covers.""" CONF_LONG_MOVEMENT = "long_movement" CONF_SHORT_MOVEMENT = "short_movement" CONF_STOP_ADDRESS = "stop_address" CONF_POSITION = "position" CONF_ANGLE = "angle" CONF_TRAVELLING_TIME_DOWN = "travelling_time_down" CONF_TRAVELLING_TIME_UP = "travelling_time_up" DEFAULT_TRAVEL_TIME = 25 SCHEMA = BaseDeviceSchema.SCHEMA.extend( { vol.Required( CONF_LONG_MOVEMENT ): RemoteValueSchema.SCHEMA_INVERTABLE.extend( { vol.Required(CONF_ADDRESS): ensure_group_address, vol.Remove(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional( CONF_SHORT_MOVEMENT ): RemoteValueSchema.SCHEMA_INVERTABLE.extend( { vol.Required(CONF_ADDRESS): ensure_group_address, vol.Remove(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_STOP_ADDRESS): ensure_group_address, vol.Optional(CONF_POSITION): RemoteValueSchema.SCHEMA_INVERTABLE.extend( {vol.Required(CONF_ADDRESS): ensure_group_address} ), vol.Optional(CONF_ANGLE): RemoteValueSchema.SCHEMA_INVERTABLE.extend( {vol.Required(CONF_ADDRESS): ensure_group_address} ), vol.Optional( CONF_TRAVELLING_TIME_DOWN, default=DEFAULT_TRAVEL_TIME ): positive_int, vol.Optional( CONF_TRAVELLING_TIME_UP, default=DEFAULT_TRAVEL_TIME ): positive_int, } )
class SensorSchema: """Voluptuous schema for KNX sensors.""" CONF_TYPE = "type" CONF_SENSOR = "sensor" SCHEMA = BaseDeviceSchema.SCHEMA.extend( { vol.Required(CONF_SENSOR): RemoteValueSchema.SCHEMA.extend( { vol.Required(CONF_STATE_ADDRESS): ensure_group_address, vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_TYPE): sensor_value_type, } ), } )
class DateTimeSchema: """Voluptuous schema for KNX date time devices.""" CONF_TIME = "time" CONF_BROADCAST_TYPE = "broadcast_type" SCHEMA = BaseDeviceSchema.SCHEMA.extend({ vol.Required(CONF_TIME): RemoteValueSchema.SCHEMA.extend({ vol.Required(CONF_ADDRESS): ensure_group_address, vol.Remove(CONF_STATE_ADDRESS): ensure_group_address, vol.Optional(CONF_BROADCAST_TYPE, default=DateTimeType.TIME): enum(DateTimeType), }), })
class SceneSchema: """Voluptuous schema for KNX scenes.""" CONF_SCENE = "scene" CONF_SCENE_NUMBER = "scene_number" SCHEMA = BaseDeviceSchema.SCHEMA.extend({ vol.Required(CONF_SCENE): RemoteValueSchema.SCHEMA.extend({ vol.Required(CONF_ADDRESS): ensure_group_address, vol.Remove(CONF_STATE_ADDRESS): ensure_group_address, vol.Optional(CONF_STATE_UPDATE, default=False): False, vol.Required(CONF_SCENE_NUMBER): vol.All(vol.Coerce(int), vol.Range(min=1, max=64)), }), })
class ExposeSchema: """Voluptuous schema for KNX exposures.""" CONF_TYPE = "type" CONF_ENTITY_ID = "entity_id" # HA only CONF_ATTRIBUTE = "attribute" CONF_DEFAULT = "default" CONF_NAME = "name" SCHEMA = BaseDeviceSchema.SCHEMA.extend( { vol.Remove(CONF_NAME): False, vol.Required(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_TYPE): sensor_value_type, vol.Optional(CONF_DEFAULT): match_all, vol.Optional(CONF_ATTRIBUTE): string, vol.Optional(CONF_ENTITY_ID): valid_entity_id, } )
PLATFORM_SCHEMA = vol.All( cv.removed(CONF_UNIT_OF_MEASUREMENT), PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_UNIQUE_ID): cv.string, vol.Required(CONF_SOURCE_SENSOR): cv.entity_id, vol.Optional(CONF_ROUND_DIGITS, default=DEFAULT_ROUND): vol.Coerce(int), vol.Optional(CONF_UNIT_PREFIX, default=None): vol.In(UNIT_PREFIXES), vol.Optional(CONF_UNIT_TIME, default=TIME_HOURS): vol.In(UNIT_TIME), vol.Remove(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_METHOD, default=METHOD_TRAPEZOIDAL): vol.In(INTEGRATION_METHODS), }), ) async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Initialize Integration - Riemann sum integral config entry.""" registry = er.async_get(hass) # Validate + resolve entity registry id to entity_id
| SUPPORT_PAUSE | SUPPORT_STOP) CONF_ON_ACTION = "turn_on_action" DEFAULT_API_VERSION = 1 PLATFORM_SCHEMA = vol.All( cv.deprecated(CONF_HOST), cv.deprecated(CONF_NAME), cv.deprecated(CONF_API_VERSION), cv.deprecated(CONF_ON_ACTION), PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Remove(CONF_NAME): cv.string, vol.Optional(CONF_API_VERSION, default=DEFAULT_API_VERSION): vol.Coerce(int), vol.Remove(CONF_ON_ACTION): cv.SCRIPT_SCHEMA, }), ) def _inverted(data): return {v: k for k, v in data.items()} async def async_setup_platform(hass, config,
vol.Optional("quality_scale"): vol.In(SUPPORTED_QUALITY_SCALES), vol.Optional("requirements"): [str], vol.Optional("dependencies"): [str], vol.Optional("after_dependencies"): [str], vol.Required("codeowners"): [str], vol.Optional("loggers"): [str], vol.Optional("disabled"): str, vol.Optional("iot_class"): vol.In(SUPPORTED_IOT_CLASSES), vol.Optional("supported_brands"): vol.Schema({str: str}), } ) CUSTOM_INTEGRATION_MANIFEST_SCHEMA = MANIFEST_SCHEMA.extend( { vol.Optional("version"): vol.All(str, verify_version), vol.Remove("supported_brands"): dict, } ) def validate_version(integration: Integration): """ Validate the version of the integration. Will be removed when the version key is no longer optional for custom integrations. """ if not integration.manifest.get("version"): integration.add_error("manifest", "No 'version' key in the manifest file.") return
cv.string, vol.Optional(CONF_REALTIME, default=DEFAULT_REALTIME): cv.boolean, vol.Optional(CONF_VEHICLE_TYPE, default=DEFAULT_VEHICLE_TYPE): vol.In(VEHICLE_TYPES), vol.Optional(CONF_UNITS): vol.In(UNITS), vol.Optional(CONF_AVOID_TOLL_ROADS, default=DEFAULT_AVOID_TOLL_ROADS): cv.boolean, vol.Optional(CONF_AVOID_SUBSCRIPTION_ROADS, default=DEFAULT_AVOID_SUBSCRIPTION_ROADS): cv.boolean, vol.Optional(CONF_AVOID_FERRIES, default=DEFAULT_AVOID_FERRIES): cv.boolean, # Remove options to exclude from import vol.Remove(CONF_ENTITY_NAMESPACE): cv.string, vol.Remove(CONF_SCAN_INTERVAL): cv.time_period, }, extra=vol.REMOVE_EXTRA, ) async def async_setup_platform(hass: HomeAssistant, config: Config, async_add_entities, discovery_info=None): """Set up the Waze travel time sensor platform.""" hass.async_create_task(
vol.Optional(CONF_MODE, default="driving"): vol.In(TRAVEL_MODE), vol.Optional(CONF_LANGUAGE): vol.In(ALL_LANGUAGES), vol.Optional(CONF_AVOID): vol.In(AVOID), vol.Optional(CONF_UNITS): vol.In(UNITS), vol.Exclusive(CONF_ARRIVAL_TIME, "time"): cv.string, vol.Exclusive(CONF_DEPARTURE_TIME, "time"): cv.string, vol.Optional(CONF_TRAFFIC_MODEL): vol.In(TRAVEL_MODEL), vol.Optional(CONF_TRANSIT_MODE): vol.In(TRANSPORT_TYPE), vol.Optional(CONF_TRANSIT_ROUTING_PREFERENCE): vol.In( TRANSIT_PREFS ), } ), ), # Remove options to exclude from import vol.Remove(CONF_ENTITY_NAMESPACE): cv.string, vol.Remove(CONF_SCAN_INTERVAL): cv.time_period, }, extra=vol.REMOVE_EXTRA, ) def convert_time_to_utc(timestr): """Take a string like 08:00:00 and convert it to a unix timestamp.""" combined = datetime.combine( dt_util.start_of_local_day(), dt_util.parse_time(timestr) ) if combined < datetime.now(): combined = combined + timedelta(days=1) return dt_util.as_timestamp(combined)
default=DEFAULT_EXPOSE_BY_DEFAULT): cv.boolean, vol.Optional(CONF_EXPOSED_DOMAINS, default=DEFAULT_EXPOSED_DOMAINS): cv.ensure_list, vol.Optional(CONF_ENTITY_CONFIG): { cv.entity_id: ENTITY_SCHEMA }, # str on purpose, makes sure it is configured correctly. vol.Optional(CONF_SECURE_DEVICES_PIN): str, vol.Optional(CONF_REPORT_STATE, default=False): cv.boolean, vol.Optional(CONF_SERVICE_ACCOUNT): GOOGLE_SERVICE_ACCOUNT, # deprecated configuration options vol.Remove(CONF_ALLOW_UNLOCK): cv.boolean, vol.Remove(CONF_API_KEY): cv.string, }, extra=vol.PREVENT_EXTRA, ), _check_report_state, ) CONFIG_SCHEMA = vol.Schema({DOMAIN: GOOGLE_ASSISTANT_SCHEMA}, extra=vol.ALLOW_EXTRA) async def async_setup(hass: HomeAssistant, yaml_config: dict[str, Any]): """Activate Google Actions component."""
{ vol.Optional(CONF_CLIMATE_SYSTEMS, default=[1]): vol.All(cv.ensure_list, [int]), vol.Required(CONF_NAME): str, vol.Optional(CONF_CURRENT_TEMPERATURE): cv.entity_id, vol.Optional(CONF_VALVE_POSITION): cv.entity_id, } ) SYSTEM_SCHEMA = vol.Schema( vol.All( cv.deprecated(CONF_CLIMATES), cv.deprecated(CONF_WATER_HEATERS), cv.deprecated(CONF_FANS), cv.deprecated(CONF_UNITS), { vol.Remove(CONF_CLIMATES): object, vol.Remove(CONF_WATER_HEATERS): object, vol.Remove(CONF_FANS): object, vol.Remove(CONF_UNITS): list, vol.Optional(CONF_SYSTEM): cv.positive_int, vol.Optional(CONF_SENSORS, default=[]): vol.All( cv.ensure_list, [cv.string] ), vol.Optional(CONF_SWITCHES, default=[]): vol.All( cv.ensure_list, [cv.string] ), vol.Optional(CONF_BINARY_SENSORS, default=[]): vol.All( cv.ensure_list, [cv.string] ), vol.Optional(CONF_THERMOSTATS, default={}): { cv.positive_int: THERMOSTAT_SCHEMA
class WeatherSchema: """Voluptuous schema for KNX weather devices.""" CONF_TEMPERATURE = "temperature" CONF_BRIGHTNESS_SOUTH = "brightness_south" CONF_BRIGHTNESS_NORTH = "brightness_north" CONF_BRIGHTNESS_EAST = "brightness_east" CONF_BRIGHTNESS_WEST = "brightness_west" CONF_RAIN_ALARM = "rain_alarm" CONF_WIND_ALARM = "wind_alarm" CONF_FROST_ALARM = "frost_alarm" CONF_WIND_SPEED = "wind_speed" CONF_DAY_NIGHT = "day_night" CONF_AIR_PRESSURE = "air_pressure" CONF_HUMIDITY = "humidity" CONF_EXPOSE_SENSORS = "expose_sensors" SCHEMA = BaseDeviceSchema.SCHEMA.extend( { vol.Required(CONF_TEMPERATURE): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_BRIGHTNESS_SOUTH): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_BRIGHTNESS_NORTH): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_BRIGHTNESS_EAST): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_BRIGHTNESS_WEST): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_RAIN_ALARM): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_WIND_ALARM): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_FROST_ALARM): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_WIND_SPEED): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_DAY_NIGHT): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_AIR_PRESSURE): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_HUMIDITY): RemoteValueSchema.SCHEMA.extend( { vol.Remove(CONF_ADDRESS): ensure_group_address, vol.Required(CONF_STATE_ADDRESS): ensure_group_address, } ), vol.Optional(CONF_EXPOSE_SENSORS, default=False): boolean, } )
vol.Schema( { vol.Required(CONF_PROJECT_ID): cv.string, vol.Optional( CONF_EXPOSE_BY_DEFAULT, default=DEFAULT_EXPOSE_BY_DEFAULT ): cv.boolean, vol.Optional( CONF_EXPOSED_DOMAINS, default=DEFAULT_EXPOSED_DOMAINS ): cv.ensure_list, vol.Optional(CONF_ENTITY_CONFIG): {cv.entity_id: ENTITY_SCHEMA}, # str on purpose, makes sure it is configured correctly. vol.Optional(CONF_SECURE_DEVICES_PIN): str, vol.Optional(CONF_REPORT_STATE, default=False): cv.boolean, vol.Optional(CONF_SERVICE_ACCOUNT): GOOGLE_SERVICE_ACCOUNT, # deprecated configuration options vol.Remove(CONF_ALLOW_UNLOCK): cv.boolean, vol.Remove(CONF_API_KEY): cv.string, }, extra=vol.PREVENT_EXTRA, ), _check_report_state, ) CONFIG_SCHEMA = vol.Schema( {vol.Optional(DOMAIN): GOOGLE_ASSISTANT_SCHEMA}, extra=vol.ALLOW_EXTRA ) async def async_setup(hass: HomeAssistant, yaml_config: ConfigType) -> bool: """Activate Google Actions component.""" if DOMAIN not in yaml_config:
| SUPPORT_STOP ) CONF_ON_ACTION = "turn_on_action" DEFAULT_API_VERSION = 1 PLATFORM_SCHEMA = vol.All( cv.deprecated(CONF_HOST), cv.deprecated(CONF_NAME), cv.deprecated(CONF_API_VERSION), cv.deprecated(CONF_ON_ACTION), PLATFORM_SCHEMA.extend( { vol.Required(CONF_HOST): cv.string, vol.Remove(CONF_NAME): cv.string, vol.Optional(CONF_API_VERSION, default=DEFAULT_API_VERSION): vol.Coerce( int ), vol.Remove(CONF_ON_ACTION): cv.SCRIPT_SCHEMA, } ), ) def _inverted(data): return {v: k for k, v in data.items()} async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Philips TV platform."""
vol.Schema({ **SCRIPT_ACTION_BASE_SCHEMA, vol.Exclusive(CONF_SERVICE, "service name"): vol.Any(service, dynamic_template), vol.Exclusive(CONF_SERVICE_TEMPLATE, "service name"): vol.Any(service, dynamic_template), vol.Optional("data"): vol.Any(template, vol.All(dict, template_complex)), vol.Optional("data_template"): vol.Any(template, vol.All(dict, template_complex)), vol.Optional(CONF_ENTITY_ID): comp_entity_ids, vol.Optional(CONF_TARGET): vol.Any(TARGET_SERVICE_FIELDS, dynamic_template), # The frontend stores data here. Don't use in core. vol.Remove("metadata"): dict, }), has_at_least_one_key(CONF_SERVICE, CONF_SERVICE_TEMPLATE), ) NUMERIC_STATE_THRESHOLD_SCHEMA = vol.Any( vol.Coerce(float), vol.All(str, entity_domain(["input_number", "number", "sensor"]))) CONDITION_BASE_SCHEMA = {vol.Optional(CONF_ALIAS): string} NUMERIC_STATE_CONDITION_SCHEMA = vol.All( vol.Schema({ **CONDITION_BASE_SCHEMA, vol.Required(CONF_CONDITION): "numeric_state",
from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.device_registry import DeviceEntryType from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType import homeassistant.util.dt as dt_util from .const import DEFAULT_NAME, DOMAIN PLATFORM_SCHEMA = vol.All( cv.removed(CONF_UNIT_OF_MEASUREMENT, raise_if_present=False), PLATFORM_SCHEMA.extend( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Remove(CONF_UNIT_OF_MEASUREMENT): cv.string, }, ), ) async def async_setup_platform( hass: HomeAssistant, config: ConfigType, async_add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the uptime sensor platform.""" hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN,