def test_has_at_least_one_key(): """Test has_at_least_one_key validator.""" schema = vol.Schema(cv.has_at_least_one_key('beer', 'soda')) for value in (None, [], {}, {'wine': None}): with pytest.raises(vol.MultipleInvalid): schema(value) for value in ({'beer': None}, {'soda': None}): schema(value)
vol.Optional(OZW_INSTANCE, default=1): vol.Coerce(int), vol.Required(PARAMETER): vol.Coerce(int), vol.Required(VALUE): vol.Any( vol.All( cv.ensure_list, [ vol.All( { vol.Exclusive(ATTR_LABEL, "bit"): cv.string, vol.Exclusive(ATTR_POSITION, "bit"): vol.Coerce(int), vol.Required(ATTR_VALUE): bool, }, cv.has_at_least_one_key(ATTR_LABEL, ATTR_POSITION), ) ], ), vol.Coerce(int), bool, cv.string, ), }) def websocket_set_config_parameter(hass, connection, msg): """Set a config parameter to a node.""" _call_util_function(hass, connection, msg, True, set_config_parameter, msg[PARAMETER], msg[VALUE]) @websocket_api.websocket_command({
ATTR_TARGET_TEMP_HIGH, ] _LOGGER = logging.getLogger(__name__) TURN_ON_OFF_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, }) SET_AUX_HEAT_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_AUX_HEAT): cv.boolean, }) SET_TEMPERATURE_SCHEMA = vol.Schema( vol.All( cv.has_at_least_one_key(ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW), { vol.Exclusive(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float), vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float), vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float), vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Optional(ATTR_HVAC_MODE): vol.In(HVAC_MODES), })) SET_FAN_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_FAN_MODE): cv.string, }) SET_PRESET_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
], ) }, extra=vol.ALLOW_EXTRA, ) DELETE_SMS_SCHEMA = vol.Schema({ vol.Optional(ATTR_HOST): cv.string, vol.Required(ATTR_SMS_ID): vol.All(cv.ensure_list, [cv.positive_int]), }) SET_OPTION_SCHEMA = vol.Schema( vol.All( cv.has_at_least_one_key(ATTR_FAILOVER, ATTR_AUTOCONNECT), { vol.Optional(ATTR_HOST): cv.string, vol.Optional(ATTR_FAILOVER): vol.In(FAILOVER_MODES), vol.Optional(ATTR_AUTOCONNECT): vol.In(AUTOCONNECT_MODES), }, )) CONNECT_LTE_SCHEMA = vol.Schema({vol.Optional(ATTR_HOST): cv.string}) DISCONNECT_LTE_SCHEMA = vol.Schema({vol.Optional(ATTR_HOST): cv.string}) @attr.s class ModemData: """Class for modem state."""
CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT) from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) CONF_PROTOCOL = 'protocol' CONF_MODE = 'mode' DEFAULT_SSH_PORT = 22 CONF_SSH_KEY = 'ssh_key' CONF_PUB_KEY = 'pub_key' SECRET_GROUP = 'Password or SSH Key' PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_PASSWORD, CONF_PUB_KEY, CONF_SSH_KEY), PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Optional(CONF_PROTOCOL, default='ssh'): vol.In(['ssh', 'telnet']), vol.Optional(CONF_MODE, default='router'): vol.In(['router', 'ap']), vol.Optional(CONF_PORT, default=DEFAULT_SSH_PORT): cv.port, vol.Exclusive(CONF_PASSWORD, SECRET_GROUP): cv.string, vol.Exclusive(CONF_SSH_KEY, SECRET_GROUP): cv.isfile, vol.Exclusive(CONF_PUB_KEY, SECRET_GROUP): cv.isfile })) _LOGGER = logging.getLogger(__name__)
msg=CONF_PLM_HUB_MSG): cv.string, vol.Exclusive(CONF_HOST, 'plm_or_hub', msg=CONF_PLM_HUB_MSG): cv.string, vol.Optional(CONF_IP_PORT): cv.port, vol.Optional(CONF_HUB_USERNAME): cv.string, vol.Optional(CONF_HUB_PASSWORD): cv.string, vol.Optional(CONF_HUB_VERSION, default=2): vol.In([1, 2]), vol.Optional(CONF_OVERRIDE): vol.All( cv.ensure_list_csv, [CONF_DEVICE_OVERRIDE_SCHEMA]), vol.Optional(CONF_X10_ALL_UNITS_OFF): vol.In(HOUSECODES), vol.Optional(CONF_X10_ALL_LIGHTS_ON): vol.In(HOUSECODES), vol.Optional(CONF_X10_ALL_LIGHTS_OFF): vol.In(HOUSECODES), vol.Optional(CONF_X10): vol.All(cv.ensure_list_csv, [CONF_X10_SCHEMA]) }, extra=vol.ALLOW_EXTRA, required=True), cv.has_at_least_one_key(CONF_PORT, CONF_HOST), set_default_port) }, extra=vol.ALLOW_EXTRA) ADD_ALL_LINK_SCHEMA = vol.Schema({ vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255), vol.Required(SRV_ALL_LINK_MODE): vol.In([SRV_CONTROLLER, SRV_RESPONDER]), }) DEL_ALL_LINK_SCHEMA = vol.Schema({ vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255), }) LOAD_ALDB_SCHEMA = vol.Schema({ vol.Required(CONF_ENTITY_ID): cv.entity_id,
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up an input datetime.""" component = EntityComponent(_LOGGER, DOMAIN, hass) id_manager = collection.IDManager() yaml_collection = collection.YamlCollection( logging.getLogger(f"{__name__}.yaml_collection"), id_manager) collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component, yaml_collection, InputDatetime.from_yaml) storage_collection = DateTimeStorageCollection( Store(hass, STORAGE_VERSION, STORAGE_KEY), logging.getLogger(f"{__name__}.storage_collection"), id_manager, ) collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component, storage_collection, InputDatetime) await yaml_collection.async_load([{ CONF_ID: id_, **cfg } for id_, cfg in config.get(DOMAIN, {}).items()]) await storage_collection.async_load() collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN, CREATE_FIELDS, UPDATE_FIELDS).async_setup(hass) async def reload_service_handler(service_call: ServiceCallType) -> None: """Reload yaml entities.""" conf = await component.async_prepare_reload(skip_reset=True) if conf is None: conf = {DOMAIN: {}} await yaml_collection.async_load([{ CONF_ID: id_, **cfg } for id_, cfg in conf.get(DOMAIN, {}).items()]) homeassistant.helpers.service.async_register_admin_service( hass, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA, ) component.async_register_entity_service( "set_datetime", vol.All( vol.Schema( { vol.Optional(ATTR_DATE): cv.date, vol.Optional(ATTR_TIME): cv.time, vol.Optional(ATTR_DATETIME): cv.datetime, vol.Optional(ATTR_TIMESTAMP): vol.Coerce(float), }, extra=vol.ALLOW_EXTRA, ), cv.has_at_least_one_key(ATTR_DATE, ATTR_TIME, ATTR_DATETIME, ATTR_TIMESTAMP), validate_set_datetime_attrs, ), "async_set_datetime", ) return True
from homeassistant.helpers import config_validation as cv from homeassistant.helpers.event import async_track_time_change CONF_HOURS = "hours" CONF_MINUTES = "minutes" CONF_SECONDS = "seconds" _LOGGER = logging.getLogger(__name__) TRIGGER_SCHEMA = vol.All(vol.Schema({ vol.Required(CONF_PLATFORM): 'time', CONF_AFTER: cv.time, CONF_HOURS: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_MINUTES: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_SECONDS: vol.Any(vol.Coerce(int), vol.Coerce(str)), }), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AFTER)) def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" if CONF_AFTER in config: after = config.get(CONF_AFTER) hours, minutes, seconds = after.hour, after.minute, after.second else: hours = config.get(CONF_HOURS) minutes = config.get(CONF_MINUTES) seconds = config.get(CONF_SECONDS) @asyncio.coroutine def time_automation_listener(now): """Listen for time changes and calls action."""
def async_register(self) -> None: """Register all our services.""" @callback def get_nodes_from_service_data(val: dict[str, Any]) -> dict[str, Any]: """Get nodes set from service data.""" nodes: set[ZwaveNode] = set() # Convert all entity IDs to nodes for entity_id in expand_entity_ids(self._hass, val.pop(ATTR_ENTITY_ID, [])): try: nodes.add( async_get_node_from_entity_id(self._hass, entity_id, self._ent_reg, self._dev_reg)) except ValueError as err: const.LOGGER.warning(err.args[0]) # Convert all area IDs to nodes for area_id in val.pop(ATTR_AREA_ID, []): nodes.update( async_get_nodes_from_area_id(self._hass, area_id, self._ent_reg, self._dev_reg)) # Convert all device IDs to nodes for device_id in val.pop(ATTR_DEVICE_ID, []): try: nodes.add( async_get_node_from_device_id(self._hass, device_id, self._dev_reg)) except ValueError as err: const.LOGGER.warning(err.args[0]) val[const.ATTR_NODES] = nodes return val @callback def validate_multicast_nodes(val: dict[str, Any]) -> dict[str, Any]: """Validate the input nodes for multicast.""" nodes: set[ZwaveNode] = val[const.ATTR_NODES] broadcast: bool = val[const.ATTR_BROADCAST] # User must specify a node if they are attempting a broadcast and have more # than one zwave-js network. if (broadcast and not nodes and len(self._hass.config_entries.async_entries( const.DOMAIN)) > 1): raise vol.Invalid( "You must include at least one entity or device in the service call" ) first_node = next((node for node in nodes), None) # If any nodes don't have matching home IDs, we can't run the command because # we can't multicast across multiple networks if first_node and any(node.client.driver.controller.home_id != first_node.client.driver.controller.home_id for node in nodes): raise vol.Invalid( "Multicast commands only work on devices in the same network" ) return val @callback def validate_entities(val: dict[str, Any]) -> dict[str, Any]: """Validate entities exist and are from the zwave_js platform.""" val[ATTR_ENTITY_ID] = expand_entity_ids(self._hass, val[ATTR_ENTITY_ID]) for entity_id in val[ATTR_ENTITY_ID]: entry = self._ent_reg.async_get(entity_id) if entry is None or entry.platform != const.DOMAIN: raise vol.Invalid( f"Entity {entity_id} is not a valid {const.DOMAIN} entity." ) return val self._hass.services.async_register( const.DOMAIN, const.SERVICE_SET_CONFIG_PARAMETER, self.async_set_config_parameter, schema=vol.Schema( vol.All( { vol.Optional(ATTR_AREA_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Any(vol.Coerce(int), cv.string), vol.Optional(const.ATTR_CONFIG_PARAMETER_BITMASK): vol.Any(vol.Coerce(int), BITMASK_SCHEMA), vol.Required(const.ATTR_CONFIG_VALUE): vol.Any(vol.Coerce(int), BITMASK_SCHEMA, cv.string), }, cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID), parameter_name_does_not_need_bitmask, get_nodes_from_service_data, ), ), ) self._hass.services.async_register( const.DOMAIN, const.SERVICE_BULK_SET_PARTIAL_CONFIG_PARAMETERS, self.async_bulk_set_partial_config_parameters, schema=vol.Schema( vol.All( { vol.Optional(ATTR_AREA_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Required(const.ATTR_CONFIG_PARAMETER): vol.Coerce(int), vol.Required(const.ATTR_CONFIG_VALUE): vol.Any( vol.Coerce(int), { vol.Any(vol.Coerce(int), BITMASK_SCHEMA, cv.string): vol.Any(vol.Coerce(int), BITMASK_SCHEMA, cv.string) }, ), }, cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID), get_nodes_from_service_data, ), ), ) self._hass.services.async_register( const.DOMAIN, const.SERVICE_REFRESH_VALUE, self.async_poll_value, schema=vol.Schema( vol.All( { vol.Required(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(const.ATTR_REFRESH_ALL_VALUES, default=False): cv.boolean, }, validate_entities, )), ) self._hass.services.async_register( const.DOMAIN, const.SERVICE_SET_VALUE, self.async_set_value, schema=vol.Schema( vol.All( { vol.Optional(ATTR_AREA_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Required(const.ATTR_COMMAND_CLASS): vol.Coerce(int), vol.Required(const.ATTR_PROPERTY): vol.Any(vol.Coerce(int), str), vol.Optional(const.ATTR_PROPERTY_KEY): vol.Any(vol.Coerce(int), str), vol.Optional(const.ATTR_ENDPOINT): vol.Coerce(int), vol.Required(const.ATTR_VALUE): VALUE_SCHEMA, vol.Optional(const.ATTR_WAIT_FOR_RESULT): cv.boolean, vol.Optional(const.ATTR_OPTIONS): { cv.string: VALUE_SCHEMA }, }, cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID), get_nodes_from_service_data, ), ), ) self._hass.services.async_register( const.DOMAIN, const.SERVICE_MULTICAST_SET_VALUE, self.async_multicast_set_value, schema=vol.Schema( vol.All( { vol.Optional(ATTR_AREA_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(const.ATTR_BROADCAST, default=False): cv.boolean, vol.Required(const.ATTR_COMMAND_CLASS): vol.Coerce(int), vol.Required(const.ATTR_PROPERTY): vol.Any(vol.Coerce(int), str), vol.Optional(const.ATTR_PROPERTY_KEY): vol.Any(vol.Coerce(int), str), vol.Optional(const.ATTR_ENDPOINT): vol.Coerce(int), vol.Required(const.ATTR_VALUE): VALUE_SCHEMA, vol.Optional(const.ATTR_OPTIONS): { cv.string: VALUE_SCHEMA }, }, vol.Any( cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID), broadcast_command, ), get_nodes_from_service_data, validate_multicast_nodes, ), ), ) self._hass.services.async_register( const.DOMAIN, const.SERVICE_PING, self.async_ping, schema=vol.Schema( vol.All( { vol.Optional(ATTR_AREA_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_DEVICE_ID): vol.All(cv.ensure_list, [cv.string]), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, }, cv.has_at_least_one_key(ATTR_DEVICE_ID, ATTR_ENTITY_ID, ATTR_AREA_ID), get_nodes_from_service_data, ), ), )
DOMAIN = 'konnected' CONF_ACTIVATION = 'activation' STATE_LOW = 'low' STATE_HIGH = 'high' PIN_TO_ZONE = {1: 1, 2: 2, 5: 3, 6: 4, 7: 5, 8: 'out', 9: 6} ZONE_TO_PIN = {zone: pin for pin, zone in PIN_TO_ZONE.items()} _BINARY_SENSOR_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_PIN, 's_pin'): vol.Any(*PIN_TO_ZONE), vol.Exclusive(CONF_ZONE, 's_pin'): vol.Any(*ZONE_TO_PIN), vol.Required(CONF_TYPE): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_NAME): cv.string, }), cv.has_at_least_one_key(CONF_PIN, CONF_ZONE)) _SWITCH_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_PIN, 'a_pin'): vol.Any(*PIN_TO_ZONE), vol.Exclusive(CONF_ZONE, 'a_pin'): vol.Any(*ZONE_TO_PIN), vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_ACTIVATION, default=STATE_HIGH): vol.All(vol.Lower, vol.Any(STATE_HIGH, STATE_LOW)) }), cv.has_at_least_one_key(CONF_PIN, CONF_ZONE)) CONFIG_SCHEMA = vol.Schema( {
vol.Optional(CONF_OFFSET, default=0): vol.Coerce(float), vol.Optional(CONF_MAX_TEMP, default=35): cv.positive_int, vol.Optional(CONF_MIN_TEMP, default=5): cv.positive_int, vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float), vol.Optional(CONF_STRUCTURE, default=DEFAULT_STRUCTURE_PREFIX): cv.string, vol.Optional(CONF_UNIT, default=DEFAULT_TEMP_UNIT): cv.string, }) COVERS_SCHEMA = vol.All( cv.has_at_least_one_key(CALL_TYPE_COIL, CONF_REGISTER), vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(cv.time_period, lambda value: value.total_seconds()), vol.Optional(CONF_DEVICE_CLASS): COVER_DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_SLAVE, default=DEFAULT_SLAVE): cv.positive_int, vol.Optional(CONF_STATE_CLOSED, default=0): cv.positive_int, vol.Optional(CONF_STATE_CLOSING, default=3): cv.positive_int, vol.Optional(CONF_STATE_OPEN, default=1): cv.positive_int,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_OPTIMISTIC): cv.boolean, vol.Optional(CONF_TILT_OPTIMISTIC): cv.boolean, vol.Optional(POSITION_ACTION): cv.SCRIPT_SCHEMA, vol.Optional(TILT_ACTION): cv.SCRIPT_SCHEMA, vol.Optional(CONF_FRIENDLY_NAME): cv.string, vol.Optional(CONF_ENTITY_ID): cv.entity_ids, }), cv.has_at_least_one_key(OPEN_ACTION, POSITION_ACTION), ) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( {vol.Required(CONF_COVERS): cv.schema_with_slug_keys(COVER_SCHEMA)}) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Template cover.""" covers = [] for device, device_config in config[CONF_COVERS].items(): state_template = device_config.get(CONF_VALUE_TEMPLATE)
ATTR_ENTRY_ID = "entry_id" _LOGGER = logging.getLogger(__name__) DOMAIN = ha.DOMAIN SERVICE_RELOAD_CORE_CONFIG = "reload_core_config" SERVICE_RELOAD_CONFIG_ENTRY = "reload_config_entry" SERVICE_CHECK_CONFIG = "check_config" SERVICE_UPDATE_ENTITY = "update_entity" SERVICE_SET_LOCATION = "set_location" SCHEMA_UPDATE_ENTITY = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids}) SCHEMA_RELOAD_CONFIG_ENTRY = vol.All( vol.Schema({ vol.Optional(ATTR_ENTRY_ID): str, **cv.ENTITY_SERVICE_FIELDS, }, ), cv.has_at_least_one_key(ATTR_ENTRY_ID, *cv.ENTITY_SERVICE_FIELDS), ) SHUTDOWN_SERVICES = (SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART) async def async_setup(hass: ha.HomeAssistant, config: dict) -> bool: # noqa: C901 """Set up general services related to Home Assistant.""" async def async_handle_turn_service(service): """Handle calls to homeassistant.turn_on/off.""" referenced = await async_extract_referenced_entity_ids(hass, service) all_referenced = referenced.referenced | referenced.indirectly_referenced # Generic turn on/off method requires entity id if not all_referenced:
value[CONF_ALIAS] = alias return value return validate _TIMESPEC = vol.Schema({ 'days': cv.positive_int, 'hours': cv.positive_int, 'minutes': cv.positive_int, 'seconds': cv.positive_int, 'milliseconds': cv.positive_int, }) _TIMESPEC_REQ = cv.has_at_least_one_key( 'days', 'hours', 'minutes', 'seconds', 'milliseconds', ) _DELAY_SCHEMA = vol.Any( vol.Schema({ vol.Required(CONF_DELAY): vol.All(_TIMESPEC.extend({ vol.Optional(CONF_ALIAS): cv.string }), _TIMESPEC_REQ) }), # Alternative format in case people forgot to indent after 'delay:' vol.All(_TIMESPEC.extend({ vol.Required(CONF_DELAY): None, vol.Optional(CONF_ALIAS): cv.string, }), _TIMESPEC_REQ) )
[ vol.Schema({ vol.Exclusive(DEVICE_DESCRIPTOR, DEVICE_ID_GROUP): cv.string, vol.Exclusive(DEVICE_NAME, DEVICE_ID_GROUP): cv.string, vol.Optional(TYPE, default=["key_up"]): vol.All(cv.ensure_list, [vol.In(KEY_VALUE)]), vol.Optional(EMULATE_KEY_HOLD, default=False): cv.boolean, vol.Optional(EMULATE_KEY_HOLD_DELAY, default=0.250): float, vol.Optional(EMULATE_KEY_HOLD_REPEAT, default=0.033): float, }), cv.has_at_least_one_key(DEVICE_DESCRIPTOR, DEVICE_ID_GROUP), ], ) }, extra=vol.ALLOW_EXTRA, ) async def async_setup(hass, config): """Set up the keyboard_remote.""" config = config.get(DOMAIN) remote = KeyboardRemote(hass, config) remote.setup() return True
EVENT_MATRIX_COMMAND = 'matrix_command' DOMAIN = 'matrix' COMMAND_SCHEMA = vol.All( # Basic Schema vol.Schema({ vol.Exclusive(CONF_WORD, 'trigger'): cv.string, vol.Exclusive(CONF_EXPRESSION, 'trigger'): cv.is_regex, vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ROOMS, default=[]): vol.All(cv.ensure_list, [cv.string]), }), # Make sure it's either a word or an expression command cv.has_at_least_one_key(CONF_WORD, CONF_EXPRESSION) ) CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_HOMESERVER): cv.url, vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, vol.Required(CONF_USERNAME): cv.matches_regex("@[^:]*:.*"), vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_ROOMS, default=[]): vol.All(cv.ensure_list, [cv.string]), vol.Optional(CONF_COMMANDS, default=[]): [COMMAND_SCHEMA] }) }, extra=vol.ALLOW_EXTRA) SERVICE_SEND_MESSAGE = 'send_message'
vol.Schema( {vol.Required(CONF_PLATFORM): cv.platform_validator(DOMAIN)}, extra=vol.ALLOW_EXTRA), _platform_validator(METHOD_TRIGGER, 'TRIGGER_SCHEMA')), ]) _CONDITION_SCHEMA = vol.Any( CONDITION_USE_TRIGGER_VALUES, vol.All(cv.ensure_list, [ vol.All( vol.Schema({ CONF_PLATFORM: str, CONF_CONDITION: str, }, extra=vol.ALLOW_EXTRA), cv.has_at_least_one_key(CONF_PLATFORM, CONF_CONDITION), ), ])) PLATFORM_SCHEMA = vol.Schema({ CONF_ALIAS: cv.string, vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA, vol.Required(CONF_CONDITION_TYPE, default=DEFAULT_CONDITION_TYPE): vol.All(vol.Lower, vol.Any(CONDITION_TYPE_AND, CONDITION_TYPE_OR)), CONF_CONDITION: _CONDITION_SCHEMA, vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA, })
_LOGGER = logging.getLogger(__name__) CONF_ITEMS = 'items' ICON = 'mdi:coin' MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=2*60*60) # 2h MIN_TIME_BETWEEN_CURRENCY_UPDATES = timedelta(seconds=12*60*60) # 12h _ITEM_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_URL, 'XOR'): cv.string, vol.Exclusive(CONF_ID, 'XOR'): cv.string, vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_CURRENCY): cv.string }), cv.has_at_least_one_key(CONF_URL, CONF_ID) ) _ITEMS_SCHEMA = vol.Schema([_ITEM_SCHEMA]) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_ITEMS): _ITEMS_SCHEMA, vol.Required(CONF_CURRENCY): cv.string, }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Gearbest sensor.""" from gearbest_parser import CurrencyConverter currency = config.get(CONF_CURRENCY)
if devices: miai_text_to_speech(devices[0]['deviceID'], sys.argv[3] if len(sys.argv) > 3 else "测试") exit(0) # Config validation import voluptuous as vol import homeassistant.helpers.config_validation as cv SERVICE_SCHEMA = vol.All( vol.Schema({ vol.Optional('message'): cv.string, vol.Optional('volume'): vol.Range(min=0, max=100), vol.Optional('devno'): vol.Range(min=0, max=9), }), cv.has_at_least_one_key("message", "volume"), ) class miaimsg(object): def __init__(self, hass, conf): self._miid = conf['miid'] self._password = conf.get('password') self._devices = None async def async_send_message(self, message, data): devno = data.get('devno', 0) volume = data.get('volume') if message or volume: if not await self.async_send_once(devno, message, volume): if not await self.async_send_once(devno, message, volume):
_LOGGER = logging.getLogger(__name__) ON_OFF_SERVICE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, }) SET_AWAY_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_AWAY_MODE): cv.boolean, }) SET_AUX_HEAT_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_AUX_HEAT): cv.boolean, }) SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All( cv.has_at_least_one_key( ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW), { vol.Exclusive(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float), vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float), vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float), vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Optional(ATTR_OPERATION_MODE): cv.string, } )) SET_FAN_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_FAN_MODE): cv.string, }) SET_HOLD_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, vol.Required(ATTR_HOLD_MODE): cv.string,
cv.boolean, }) COILS_SCHEMA = vol.Schema({ vol.Required(CONF_COIL): cv.positive_int, vol.Required(CONF_NAME): cv.string, vol.Required(CONF_SLAVE): cv.positive_int, vol.Optional(CONF_HUB, default=DEFAULT_HUB): cv.string, }) PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_COILS, CONF_REGISTERS), PLATFORM_SCHEMA.extend({ vol.Optional(CONF_COILS): [COILS_SCHEMA], vol.Optional(CONF_REGISTERS): [REGISTERS_SCHEMA], }), ) def setup_platform(hass, config, add_entities, discovery_info=None): """Read configuration and create Modbus devices.""" switches = [] if CONF_COILS in config: for coil in config.get(CONF_COILS): hub_name = coil.get(CONF_HUB) hub = hass.data[MODBUS_DOMAIN][hub_name] switches.append(
MONITORED_NETWORKS = 'monitored-networks' NETWORKS_URI = 'v2/networks' REQUEST_TIMEOUT = 5 # In seconds; argument to asyncio.timeout SCAN_INTERVAL = timedelta(minutes=5) # Timely, and doesn't suffocate the API STATIONS_URI = 'v2/networks/{uid}?fields=network.stations' CITYBIKES_ATTRIBUTION = "Information provided by the CityBikes Project "\ "(https://citybik.es/#about)" PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_RADIUS, CONF_STATIONS_LIST), PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=''): cv.string, vol.Optional(CONF_NETWORK): cv.string, vol.Inclusive(CONF_LATITUDE, 'coordinates'): cv.latitude, vol.Inclusive(CONF_LONGITUDE, 'coordinates'): cv.longitude, vol.Optional(CONF_RADIUS, 'station_filter'): cv.positive_int, vol.Optional(CONF_STATIONS_LIST, 'station_filter'): vol.All(cv.ensure_list, vol.Length(min=1), [cv.string]) })) NETWORK_SCHEMA = vol.Schema({ vol.Required(ATTR_ID): cv.string, vol.Required(ATTR_NAME): cv.string, vol.Required(ATTR_LOCATION): vol.Schema({ vol.Required(ATTR_LATITUDE): cv.latitude,
DECONZ_SERVICES = "deconz_services" SERVICE_FIELD = "field" SERVICE_ENTITY = "entity" SERVICE_DATA = "data" SERVICE_CONFIGURE_DEVICE = "configure" SERVICE_CONFIGURE_DEVICE_SCHEMA = vol.All( vol.Schema({ vol.Optional(SERVICE_ENTITY): cv.entity_id, vol.Optional(SERVICE_FIELD): cv.matches_regex("/.*"), vol.Required(SERVICE_DATA): dict, vol.Optional(CONF_BRIDGE_ID): str, }), cv.has_at_least_one_key(SERVICE_ENTITY, SERVICE_FIELD), ) SERVICE_DEVICE_REFRESH = "device_refresh" SERVICE_REMOVE_ORPHANED_ENTRIES = "remove_orphaned_entries" SELECT_GATEWAY_SCHEMA = vol.All(vol.Schema({vol.Optional(CONF_BRIDGE_ID): str})) async def async_setup_services(hass): """Set up services for deCONZ integration.""" if hass.data.get(DECONZ_SERVICES, False): return hass.data[DECONZ_SERVICES] = True
vol.Optional(NOTIFY_DOMAIN, default={}): vol.All(cv.ensure_list, [NOTIFY_SCHEMA]), vol.Optional(SENSOR_DOMAIN, default={}): SENSOR_SCHEMA, vol.Optional(BINARY_SENSOR_DOMAIN, default={}): BINARY_SENSOR_SCHEMA, })]) }, extra=vol.ALLOW_EXTRA) DELETE_SMS_SCHEMA = vol.Schema({ vol.Optional(ATTR_HOST): cv.string, vol.Required(ATTR_SMS_ID): vol.All(cv.ensure_list, [cv.positive_int]), }) SET_OPTION_SCHEMA = vol.Schema( vol.All(cv.has_at_least_one_key(ATTR_FAILOVER, ATTR_AUTOCONNECT), { vol.Optional(ATTR_HOST): cv.string, vol.Optional(ATTR_FAILOVER): vol.In(FAILOVER_MODES), vol.Optional(ATTR_AUTOCONNECT): vol.In(AUTOCONNECT_MODES), }) ) CONNECT_LTE_SCHEMA = vol.Schema({ vol.Optional(ATTR_HOST): cv.string, }) @attr.s class ModemData: """Class for modem state."""
}) # Service call validation schema MQTT_PUBLISH_SCHEMA = vol.All( vol.Schema( { vol.Exclusive(ATTR_TOPIC, CONF_TOPIC): valid_publish_topic, vol.Exclusive(ATTR_TOPIC_TEMPLATE, CONF_TOPIC): cv.string, vol.Exclusive(ATTR_PAYLOAD, CONF_PAYLOAD): cv.string, vol.Exclusive(ATTR_PAYLOAD_TEMPLATE, CONF_PAYLOAD): cv.string, vol.Optional(ATTR_QOS, default=DEFAULT_QOS): _VALID_QOS_SCHEMA, vol.Optional(ATTR_RETAIN, default=DEFAULT_RETAIN): cv.boolean, }, required=True, ), cv.has_at_least_one_key(ATTR_TOPIC, ATTR_TOPIC_TEMPLATE), ) SubscribePayloadType = Union[str, bytes] # Only bytes if encoding is None class MqttCommandTemplate: """Class for rendering MQTT payload with command templates.""" def __init__( self, command_template: template.Template | None, *, hass: HomeAssistant | None = None, entity: Entity | None = None, ) -> None: """Instantiate a command template."""
ATTR_NETWORK = 'network' ATTR_STATIONS_LIST = 'stations' ATTR_ID = 'id' ATTR_UID = 'uid' ATTR_NAME = 'name' ATTR_EXTRA = 'extra' ATTR_TIMESTAMP = 'timestamp' ATTR_EMPTY_SLOTS = 'empty_slots' ATTR_FREE_BIKES = 'free_bikes' ATTR_TIMESTAMP = 'timestamp' CITYBIKES_ATTRIBUTION = "Information provided by the CityBikes Project "\ "(https://citybik.es/#about)" PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_RADIUS, CONF_STATIONS_LIST), PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=''): cv.string, vol.Optional(CONF_NETWORK): cv.string, vol.Inclusive(CONF_LATITUDE, 'coordinates'): cv.latitude, vol.Inclusive(CONF_LONGITUDE, 'coordinates'): cv.longitude, vol.Optional(CONF_RADIUS, 'station_filter'): cv.positive_int, vol.Optional(CONF_STATIONS_LIST, 'station_filter'): vol.All( cv.ensure_list, vol.Length(min=1), [cv.string]) })) NETWORK_SCHEMA = vol.Schema({ vol.Required(ATTR_ID): cv.string,
DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT, CONF_MODE, CONF_PROTOCOL) REQUIREMENTS = ['pexpect==4.0.1'] _LOGGER = logging.getLogger(__name__) CONF_PUB_KEY = 'pub_key' CONF_SSH_KEY = 'ssh_key' DEFAULT_SSH_PORT = 22 SECRET_GROUP = 'Password or SSH Key' PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_PASSWORD, CONF_PUB_KEY, CONF_SSH_KEY), PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Optional(CONF_PROTOCOL, default='ssh'): vol.In(['ssh', 'telnet']), vol.Optional(CONF_MODE, default='router'): vol.In(['router', 'ap']), vol.Optional(CONF_PORT, default=DEFAULT_SSH_PORT): cv.port, vol.Exclusive(CONF_PASSWORD, SECRET_GROUP): cv.string, vol.Exclusive(CONF_SSH_KEY, SECRET_GROUP): cv.isfile, vol.Exclusive(CONF_PUB_KEY, SECRET_GROUP): cv.isfile })) _LEASES_CMD = 'cat /var/lib/misc/dnsmasq.leases' _LEASES_REGEX = re.compile( r'\w+\s' +
CONF_VALUE_TEMPLATE, ) from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv from . import async_get_config_and_coordinator, create_rest_data_from_config from .const import CONF_JSON_ATTRS, CONF_JSON_ATTRS_PATH from .entity import RestEntity from .schema import RESOURCE_SCHEMA, SENSOR_SCHEMA _LOGGER = logging.getLogger(__name__) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({**RESOURCE_SCHEMA, **SENSOR_SCHEMA}) PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_RESOURCE, CONF_RESOURCE_TEMPLATE), PLATFORM_SCHEMA) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the RESTful sensor.""" # Must update the sensor now (including fetching the rest resource) to # ensure it's updating its state. if discovery_info is not None: conf, coordinator, rest = await async_get_config_and_coordinator( hass, SENSOR_DOMAIN, discovery_info) else: conf = config
_LOGGER = logging.getLogger(__name__) PLATFORM_SCHEMA = vol.All( PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Exclusive(CONF_API_KEY, 'source'): cv.string, vol.Optional(CONF_QUERY): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(cv.time_period, vol.Range(min=MIN_SCAN_INTERVAL)), vol.Exclusive(CONF_ENTITY_ID, 'source'): cv.entity_id, }), cv.has_at_least_one_key(CONF_API_KEY, CONF_ENTITY_ID), cv.key_dependency(CONF_API_KEY, CONF_QUERY), ) _WU_API_URL = 'http://api.wunderground.com/api/'\ '{api_key}/{features}/q/{query}.json' _20_MIN = dt.timedelta(minutes=20) _40_MIN = dt.timedelta(minutes=40) async def _async_get_wu_data(hass, session, api_key, features, query): try: with async_timeout.timeout(9, loop=hass.loop): resp = await session.get( _WU_API_URL.format(api_key=api_key,
from homeassistant.helpers.event import async_track_time_change CONF_HOURS = 'hours' CONF_MINUTES = 'minutes' CONF_SECONDS = 'seconds' _LOGGER = logging.getLogger(__name__) TRIGGER_SCHEMA = vol.All( vol.Schema({ vol.Required(CONF_PLATFORM): 'time', CONF_AT: cv.time, CONF_HOURS: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_MINUTES: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_SECONDS: vol.Any(vol.Coerce(int), vol.Coerce(str)), }), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AT)) async def async_trigger(hass, config, action, automation_info): """Listen for state changes based on configuration.""" if CONF_AT in config: at_time = config.get(CONF_AT) hours, minutes, seconds = at_time.hour, at_time.minute, at_time.second else: hours = config.get(CONF_HOURS) minutes = config.get(CONF_MINUTES) seconds = config.get(CONF_SECONDS) @callback def time_automation_listener(now): """Listen for time changes and calls action."""
from homeassistant.components.sensor import SensorEntity from homeassistant.helpers import config_validation as cv, entity_platform from .const import DOMAIN, SMARTTUB_CONTROLLER from .entity import SmartTubSensorBase # the desired duration, in hours, of the cycle ATTR_DURATION = "duration" ATTR_CYCLE_LAST_UPDATED = "cycle_last_updated" ATTR_MODE = "mode" # the hour of the day at which to start the cycle (0-23) ATTR_START_HOUR = "start_hour" SET_PRIMARY_FILTRATION_SCHEMA = vol.All( cv.has_at_least_one_key(ATTR_DURATION, ATTR_START_HOUR), cv.make_entity_service_schema( { vol.Optional(ATTR_DURATION): vol.All(int, vol.Range(min=1, max=24)), vol.Optional(ATTR_START_HOUR): vol.All(int, vol.Range(min=0, max=23)), }, ), ) SET_SECONDARY_FILTRATION_SCHEMA = { vol.Required(ATTR_MODE): vol.In( { mode.name.lower() for mode in smarttub.SpaSecondaryFiltrationCycle.SecondaryFiltrationMode } ),
TRIGGER_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): 'sun', vol.Required(CONF_EVENT): _SUN_EVENT, vol.Required(CONF_OFFSET, default=timedelta(0)): cv.time_offset, }) IF_ACTION_SCHEMA = vol.All( vol.Schema({ vol.Required(CONF_PLATFORM): 'sun', CONF_BEFORE: _SUN_EVENT, CONF_AFTER: _SUN_EVENT, vol.Required(CONF_BEFORE_OFFSET, default=timedelta(0)): cv.time_offset, vol.Required(CONF_AFTER_OFFSET, default=timedelta(0)): cv.time_offset, }), cv.has_at_least_one_key(CONF_BEFORE, CONF_AFTER), ) def trigger(hass, config, action): """Listen for events based on configuration.""" event = config.get(CONF_EVENT) offset = config.get(CONF_OFFSET) # Do something to call action if event == EVENT_SUNRISE: track_sunrise(hass, action, offset) else: track_sunset(hass, action, offset) return True
vol.Optional(CONF_DEPARTURE): cv.time, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_MODE, default=TRAVEL_MODE_CAR): vol.In(TRAVEL_MODE), vol.Optional(CONF_ROUTE_MODE, default=ROUTE_MODE_FASTEST): vol.In(ROUTE_MODE), vol.Optional(CONF_TRAFFIC_MODE, default=False): cv.boolean, vol.Optional(CONF_UNIT_SYSTEM): vol.In(UNITS), }) PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_DESTINATION_LATITUDE, CONF_DESTINATION_ENTITY_ID), cv.has_at_least_one_key(CONF_ORIGIN_LATITUDE, CONF_ORIGIN_ENTITY_ID), cv.key_value_schemas( CONF_MODE, { None: PLATFORM_SCHEMA, TRAVEL_MODE_BICYCLE: PLATFORM_SCHEMA, TRAVEL_MODE_CAR: PLATFORM_SCHEMA, TRAVEL_MODE_PEDESTRIAN: PLATFORM_SCHEMA, TRAVEL_MODE_PUBLIC: PLATFORM_SCHEMA, TRAVEL_MODE_TRUCK:
"""Support for device connected via Lightwave WiFi-link hub.""" import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import (CONF_HOST, CONF_LIGHTS, CONF_NAME, CONF_SWITCHES) from homeassistant.helpers.discovery import async_load_platform LIGHTWAVE_LINK = 'lightwave_link' DOMAIN = 'lightwave' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema( vol.All(cv.has_at_least_one_key(CONF_LIGHTS, CONF_SWITCHES), { vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_LIGHTS, default={}): { cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), }, vol.Optional(CONF_SWITCHES, default={}): { cv.string: vol.Schema({vol.Required(CONF_NAME): cv.string}), } }) ) }, extra=vol.ALLOW_EXTRA) async def async_setup(hass, config): """Try to start embedded Lightwave broker.""" from lightwave.lightwave import LWLink
cv.boolean, }) SERVER_CONFIG_SCHEMA = vol.Schema( vol.All( { vol.Optional(CONF_HOST): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_TOKEN): cv.string, vol.Optional(CONF_SERVER): cv.string, vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, vol.Optional(MP_DOMAIN, default={}): MEDIA_PLAYER_SCHEMA, }, cv.has_at_least_one_key(CONF_HOST, CONF_TOKEN), )) CONFIG_SCHEMA = vol.Schema({PLEX_DOMAIN: SERVER_CONFIG_SCHEMA}, extra=vol.ALLOW_EXTRA) _LOGGER = logging.getLogger(__package__) async def async_setup(hass, config): """Set up the Plex component.""" hass.data.setdefault( PLEX_DOMAIN, { SERVERS: {}, DISPATCHERS: {},
vol.Optional(CONF_SLAVE): cv.positive_int, vol.Optional(CONF_STATE_OFF): cv.positive_int, vol.Optional(CONF_STATE_ON): cv.positive_int, vol.Optional(CONF_VERIFY_REGISTER): cv.positive_int, vol.Optional(CONF_VERIFY_STATE, default=True): cv.boolean, }) COILS_SCHEMA = vol.Schema({ vol.Required(CONF_COIL): cv.positive_int, vol.Required(CONF_NAME): cv.string, vol.Required(CONF_SLAVE): cv.positive_int, vol.Optional(CONF_HUB, default=DEFAULT_HUB): cv.string, }) PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_COILS, CONF_REGISTERS), PLATFORM_SCHEMA.extend({ vol.Optional(CONF_COILS): [COILS_SCHEMA], vol.Optional(CONF_REGISTERS): [REGISTERS_SCHEMA], })) def setup_platform(hass, config, add_entities, discovery_info=None): """Read configuration and create Modbus devices.""" switches = [] if CONF_COILS in config: for coil in config.get(CONF_COILS): hub_name = coil.get(CONF_HUB) hub = hass.data[MODBUS_DOMAIN][hub_name] switches.append(ModbusCoilSwitch( hub, coil.get(CONF_NAME), coil.get(CONF_SLAVE),
cv.port, vol.Optional(CONF_HUB_USERNAME): cv.string, vol.Optional(CONF_HUB_PASSWORD): cv.string, vol.Optional(CONF_HUB_VERSION, default=2): vol.In([1, 2]), vol.Optional(CONF_OVERRIDE): vol.All(cv.ensure_list_csv, [CONF_DEVICE_OVERRIDE_SCHEMA]), vol.Optional(CONF_X10): vol.All(cv.ensure_list_csv, [CONF_X10_SCHEMA]), }, extra=vol.ALLOW_EXTRA, required=True, ), cv.has_at_least_one_key(CONF_PORT, CONF_HOST), set_default_port, ) }, extra=vol.ALLOW_EXTRA, ) ADD_ALL_LINK_SCHEMA = vol.Schema({ vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255), vol.Required(SRV_ALL_LINK_MODE): vol.In([SRV_CONTROLLER, SRV_RESPONDER]), }) DEL_ALL_LINK_SCHEMA = vol.Schema( {vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255)})
EVENT_HANGOUTS_MESSAGE_RECEIVED = 'hangouts_message_received' CONF_CONVERSATION_ID = 'id' CONF_CONVERSATION_NAME = 'name' SERVICE_SEND_MESSAGE = 'send_message' SERVICE_UPDATE = 'update' SERVICE_RECONNECT = 'reconnect' TARGETS_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_CONVERSATION_ID, 'id or name'): cv.string, vol.Exclusive(CONF_CONVERSATION_NAME, 'id or name'): cv.string }), cv.has_at_least_one_key(CONF_CONVERSATION_ID, CONF_CONVERSATION_NAME) ) MESSAGE_SEGMENT_SCHEMA = vol.Schema({ vol.Required('text'): cv.string, vol.Optional('is_bold'): cv.boolean, vol.Optional('is_italic'): cv.boolean, vol.Optional('is_strikethrough'): cv.boolean, vol.Optional('is_underline'): cv.boolean, vol.Optional('parse_str'): cv.boolean, vol.Optional('link_target'): cv.string }) MESSAGE_DATA_SCHEMA = vol.Schema({ vol.Optional('image_file'): cv.string, vol.Optional('image_url'): cv.string })
CONF_RECOLLECT_PLACE_ID = 'recollect_place_id' DEFAULT_ATTR = 'City and County of Denver, CO' CONFIG_FILE = '.recollect_place_id' MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10) PICKUP_TYPES = { 'compost': ('Compost Pickup', 'mdi:food-apple'), 'extra_trash': ('Extra Trash Pickup', 'mdi:truck'), 'recycling': ('Recycling Pickup', 'mdi:recycle'), 'trash': ('Trash Pickup', 'mdi:delete') } PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_API_KEY, CONF_MONITORED_CONDITIONS), PLATFORM_SCHEMA.extend({ vol.Exclusive(CONF_API_KEY, 'method'): cv.string, vol.Exclusive(CONF_RECOLLECT_PLACE_ID, 'method'): cv.string, vol.Required(CONF_MONITORED_CONDITIONS, default=list(PICKUP_TYPES)): vol.All(cv.ensure_list, [vol.In(PICKUP_TYPES)]), })) async def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Configure the platform and add the sensors."""
CONF_DISCOVERY = 'discovery' STATE_LOW = 'low' STATE_HIGH = 'high' PIN_TO_ZONE = {1: 1, 2: 2, 5: 3, 6: 4, 7: 5, 8: 'out', 9: 6} ZONE_TO_PIN = {zone: pin for pin, zone in PIN_TO_ZONE.items()} _BINARY_SENSOR_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_PIN, 's_pin'): vol.Any(*PIN_TO_ZONE), vol.Exclusive(CONF_ZONE, 's_pin'): vol.Any(*ZONE_TO_PIN), vol.Required(CONF_TYPE): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_INVERSE, default=False): cv.boolean, }), cv.has_at_least_one_key(CONF_PIN, CONF_ZONE) ) _SWITCH_SCHEMA = vol.All( vol.Schema({ vol.Exclusive(CONF_PIN, 'a_pin'): vol.Any(*PIN_TO_ZONE), vol.Exclusive(CONF_ZONE, 'a_pin'): vol.Any(*ZONE_TO_PIN), vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_ACTIVATION, default=STATE_HIGH): vol.All(vol.Lower, vol.Any(STATE_HIGH, STATE_LOW)), vol.Optional(CONF_MOMENTARY): vol.All(vol.Coerce(int), vol.Range(min=10)), vol.Optional(CONF_PAUSE): vol.All(vol.Coerce(int), vol.Range(min=10)), vol.Optional(CONF_REPEAT): vol.All(vol.Coerce(int), vol.Range(min=-1)),
cv.boolean, vol.Optional(LEVEL): vol.All( cv.string, vol.Lower, vol.In([log_level.value for log_level in LogLevel]), lambda val: LogLevel(val), # pylint: disable=unnecessary-lambda ), vol.Optional(LOG_TO_FILE): cv.boolean, vol.Optional(FILENAME): cv.string, vol.Optional(FORCE_CONSOLE): cv.boolean, }), cv.has_at_least_one_key(ENABLED, FILENAME, FORCE_CONSOLE, LEVEL, LOG_TO_FILE), filename_is_present_if_logging_to_file, ), }, ) @async_get_entry async def websocket_update_log_config( hass: HomeAssistant, connection: ActiveConnection, msg: dict, entry: ConfigEntry, client: Client, ) -> None: """Update the driver log config.""" await client.driver.async_update_log_config(LogConfig(**msg[CONFIG])) connection.send_result(msg[ID], )
vol.Optional(CONF_HOST): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) }, extra=vol.ALLOW_EXTRA) SERVICE_DECONZ = 'configure' SERVICE_FIELD = 'field' SERVICE_ENTITY = 'entity' SERVICE_DATA = 'data' SERVICE_SCHEMA = vol.All(vol.Schema({ vol.Optional(SERVICE_ENTITY): cv.entity_id, vol.Optional(SERVICE_FIELD): cv.matches_regex('/.*'), vol.Required(SERVICE_DATA): dict, }), cv.has_at_least_one_key(SERVICE_ENTITY, SERVICE_FIELD)) SERVICE_DEVICE_REFRESH = 'device_refresh' async def async_setup(hass, config): """Load configuration for deCONZ component. Discovery has loaded the component if DOMAIN is not present in config. """ if DOMAIN in config: deconz_config = None if CONF_HOST in config[DOMAIN]: deconz_config = config[DOMAIN] if deconz_config and not configured_hosts(hass): hass.async_add_job(hass.config_entries.flow.async_init(
CONF_IS_PM25, CONF_IS_PRESSURE, CONF_IS_REACTIVE_POWER, CONF_IS_SIGNAL_STRENGTH, CONF_IS_SULPHUR_DIOXIDE, CONF_IS_TEMPERATURE, CONF_IS_VOLATILE_ORGANIC_COMPOUNDS, CONF_IS_VOLTAGE, CONF_IS_VALUE, ]), vol.Optional(CONF_BELOW): vol.Any(vol.Coerce(float)), vol.Optional(CONF_ABOVE): vol.Any(vol.Coerce(float)), }), cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE), ) async def async_get_conditions(hass: HomeAssistant, device_id: str) -> list[dict[str, str]]: """List device conditions.""" conditions: list[dict[str, str]] = [] entity_registry = await async_get_registry(hass) entries = [ entry for entry in async_entries_for_device(entity_registry, device_id) if entry.domain == DOMAIN ] for entry in entries: device_class = get_device_class(hass,
NEW_DEVICE_DEFAULTS_SCHEMA = vol.Any(None, vol.Schema({ vol.Optional(CONF_TRACK_NEW, default=DEFAULT_TRACK_NEW): cv.boolean, vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, })) PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ vol.Optional(CONF_SCAN_INTERVAL): cv.time_period, vol.Optional(CONF_TRACK_NEW): cv.boolean, vol.Optional(CONF_CONSIDER_HOME, default=DEFAULT_CONSIDER_HOME): vol.All( cv.time_period, cv.positive_timedelta), vol.Optional(CONF_NEW_DEVICE_DEFAULTS, default={}): NEW_DEVICE_DEFAULTS_SCHEMA }) PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE.extend(PLATFORM_SCHEMA.schema) SERVICE_SEE_PAYLOAD_SCHEMA = vol.Schema(vol.All( cv.has_at_least_one_key(ATTR_MAC, ATTR_DEV_ID), { ATTR_MAC: cv.string, ATTR_DEV_ID: cv.string, ATTR_HOST_NAME: cv.string, ATTR_LOCATION_NAME: cv.string, ATTR_GPS: cv.gps, ATTR_GPS_ACCURACY: cv.positive_int, ATTR_BATTERY: cv.positive_int, ATTR_ATTRIBUTES: dict, ATTR_SOURCE_TYPE: vol.In(SOURCE_TYPES), ATTR_CONSIDER_HOME: cv.time_period, # Temp workaround for iOS app introduced in 0.65 vol.Optional('battery_status'): str, vol.Optional('hostname'): str, }))
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_PAYLOAD): cv.string, vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_JSON_ATTRS_PATH): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, } ) PLATFORM_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_RESOURCE, CONF_RESOURCE_TEMPLATE), PLATFORM_SCHEMA ) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the RESTful sensor.""" name = config.get(CONF_NAME) resource = config.get(CONF_RESOURCE) resource_template = config.get(CONF_RESOURCE_TEMPLATE) method = config.get(CONF_METHOD) payload = config.get(CONF_PAYLOAD) verify_ssl = config.get(CONF_VERIFY_SSL) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) headers = config.get(CONF_HEADERS) unit = config.get(CONF_UNIT_OF_MEASUREMENT)
ATTR_CYCLES = 'cycles' ATTR_TOTAL_DURATION = 'total_duration' CONF_ZONE_RUN_TIME = 'zone_run_time' DEFAULT_PORT = 8080 DEFAULT_SSL = True DEFAULT_ZONE_RUN_SECONDS = 60 * 10 MIN_SCAN_TIME_LOCAL = timedelta(seconds=1) MIN_SCAN_TIME_REMOTE = timedelta(seconds=5) MIN_SCAN_TIME_FORCED = timedelta(milliseconds=100) PLATFORM_SCHEMA = vol.Schema( vol.All( cv.has_at_least_one_key(CONF_IP_ADDRESS, CONF_EMAIL), { vol.Required(CONF_PLATFORM): cv.string, vol.Optional(CONF_SCAN_INTERVAL): cv.time_period, vol.Exclusive(CONF_IP_ADDRESS, 'auth'): cv.string, vol.Exclusive(CONF_EMAIL, 'auth'): vol.Email(), # pylint: disable=no-value-for-parameter vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
DOMAIN = 'matrix' COMMAND_SCHEMA = vol.All( # Basic Schema vol.Schema({ vol.Exclusive(CONF_WORD, 'trigger'): cv.string, vol.Exclusive(CONF_EXPRESSION, 'trigger'): cv.is_regex, vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_ROOMS, default=[]): vol.All(cv.ensure_list, [cv.string]), }), # Make sure it's either a word or an expression command cv.has_at_least_one_key(CONF_WORD, CONF_EXPRESSION)) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Required(CONF_HOMESERVER): cv.url, vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, vol.Required(CONF_USERNAME): cv.matches_regex("@[^:]*:.*"), vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_ROOMS, default=[]): vol.All(cv.ensure_list, [cv.string]),
import voluptuous as vol from homeassistant.core import callback from homeassistant.const import ( CONF_VALUE_TEMPLATE, CONF_PLATFORM, CONF_ENTITY_ID, CONF_BELOW, CONF_ABOVE) from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers import condition, config_validation as cv TRIGGER_SCHEMA = vol.All(vol.Schema({ vol.Required(CONF_PLATFORM): 'numeric_state', vol.Required(CONF_ENTITY_ID): cv.entity_ids, CONF_BELOW: vol.Coerce(float), CONF_ABOVE: vol.Coerce(float), vol.Optional(CONF_VALUE_TEMPLATE): cv.template, }), cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE)) _LOGGER = logging.getLogger(__name__) def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) below = config.get(CONF_BELOW) above = config.get(CONF_ABOVE) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass @callback def state_automation_listener(entity, from_s, to_s):
vol.Optional(CONF_AWAY_HIDE, default=DEFAULT_AWAY_HIDE): cv.boolean, })) PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ vol.Optional(CONF_SCAN_INTERVAL): cv.time_period, vol.Optional(CONF_TRACK_NEW): cv.boolean, vol.Optional(CONF_CONSIDER_HOME, default=DEFAULT_CONSIDER_HOME): vol.All(cv.time_period, cv.positive_timedelta), vol.Optional(CONF_NEW_DEVICE_DEFAULTS, default={}): NEW_DEVICE_DEFAULTS_SCHEMA }) SERVICE_SEE_PAYLOAD_SCHEMA = vol.Schema( vol.All( cv.has_at_least_one_key(ATTR_MAC, ATTR_DEV_ID), { ATTR_MAC: cv.string, ATTR_DEV_ID: cv.string, ATTR_HOST_NAME: cv.string, ATTR_LOCATION_NAME: cv.string, ATTR_GPS: cv.gps, ATTR_GPS_ACCURACY: cv.positive_int, ATTR_BATTERY: cv.positive_int,
_platform_validator(METHOD_TRIGGER, 'TRIGGER_SCHEMA') ), ] ) _CONDITION_SCHEMA = vol.Any( CONDITION_USE_TRIGGER_VALUES, vol.All( cv.ensure_list, [ vol.All( vol.Schema({ CONF_PLATFORM: str, CONF_CONDITION: str, }, extra=vol.ALLOW_EXTRA), cv.has_at_least_one_key(CONF_PLATFORM, CONF_CONDITION), ), ] ) ) PLATFORM_SCHEMA = vol.Schema({ CONF_ALIAS: cv.string, vol.Optional(CONF_HIDE_ENTITY, default=DEFAULT_HIDE_ENTITY): cv.boolean, vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA, vol.Required(CONF_CONDITION_TYPE, default=DEFAULT_CONDITION_TYPE): vol.All(vol.Lower, vol.Any(CONDITION_TYPE_AND, CONDITION_TYPE_OR)), vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA, vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA, })
# Deprecated in 0.88.0, invalidated in 0.91.0, remove in 0.92.0 ATTR_TARGET_INVALIDATION_VERSION = '0.91.0' _NOTIFY_SCHEMA = vol.All( vol.Schema({ vol.Optional(CONF_NAME): cv.string, vol.Optional(ATTR_TARGET): vol.All(cv.ensure_list, [cv.string]), vol.Optional(CONF_RECIPIENT): vol.All(cv.ensure_list, [cv.string]) }), cv.deprecated( ATTR_TARGET, replacement_key=CONF_RECIPIENT, invalidation_version=ATTR_TARGET_INVALIDATION_VERSION ), cv.has_at_least_one_key(CONF_RECIPIENT), ) CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.All(cv.ensure_list, [vol.Schema({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_NOTIFY): vol.All(cv.ensure_list, [_NOTIFY_SCHEMA]), })]) }, extra=vol.ALLOW_EXTRA) @attr.s class ModemData: """Class for modem state."""