async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Xiaomi vacuum cleaner robot platform.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) token = config.get(CONF_TOKEN) name = config.get(CONF_NAME) # Create handler _LOGGER.info("Initializing with host %s (token %s...)", host, token) vacuum = DreameVacuum(host, token) mirobo = MiroboVacuum(name, vacuum) hass.data[DATA_KEY][host] = mirobo async_add_entities([mirobo], update_before_add=True) platform = entity_platform.current_platform.get() platform.async_register_entity_service( SERVICE_CLEAN_ZONE, { vol.Required(ATTR_ZONE_ARRAY): cv.string, vol.Required(ATTR_ZONE_REPEATER): vol.All( vol.Coerce(int), vol.Clamp(min=1, max=3) ), }, MiroboVacuum.async_clean_zone.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_ROOM, { vol.Required(ATTR_ZONE_ARRAY): cv.string, vol.Required(ATTR_ZONE_REPEATER): vol.All( vol.Coerce(int), vol.Clamp(min=1, max=3) ), }, MiroboVacuum.async_clean_room.__name__, ) platform.async_register_entity_service( SERVICE_WATER_LEVEL, { vol.Required(ATTR_WATER_LEVEL): cv.string, }, MiroboVacuum.async_set_water_level.__name__, ) platform.async_register_entity_service( SERVICE_SET_BRUSH_SPEED, { vol.Required(ATTR_FAN_SPEED): vol.All( vol.Coerce(int), vol.Clamp(min=0, max=3) ), }, MiroboVacuum.async_set_fan_speed.__name__, ) platform.async_register_entity_service( SERVICE_LOCATE, {}, MiroboVacuum.async_locate.__name__, ) platform.async_register_entity_service( SERVICE_START, {}, MiroboVacuum.async_start.__name__, ) platform.async_register_entity_service( SERVICE_STOP, {}, MiroboVacuum.async_stop.__name__, ) platform.async_register_entity_service( SERVICE_PAUSE, {}, MiroboVacuum.async_pause.__name__, ) platform.async_register_entity_service( SERVICE_RETURN_TO_BASE, {}, MiroboVacuum.async_return_to_base.__name__, )
DISCOVERY_INTERVAL = 60 MESSAGE_TIMEOUT = 1.0 MESSAGE_RETRIES = 8 UNAVAILABLE_GRACE = 90 SERVICE_LIFX_SET_STATE = "set_state" ATTR_INFRARED = "infrared" ATTR_ZONES = "zones" ATTR_POWER = "power" LIFX_SET_STATE_SCHEMA = cv.make_entity_service_schema({ **LIGHT_TURN_ON_SCHEMA, ATTR_INFRARED: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)), ATTR_ZONES: vol.All(cv.ensure_list, [cv.positive_int]), ATTR_POWER: cv.boolean, }) SERVICE_EFFECT_PULSE = "effect_pulse" SERVICE_EFFECT_COLORLOOP = "effect_colorloop" SERVICE_EFFECT_STOP = "effect_stop" ATTR_POWER_ON = "power_on" ATTR_PERIOD = "period" ATTR_CYCLES = "cycles" ATTR_SPREAD = "spread" ATTR_CHANGE = "change"
def __init__(self): """Initialize the config flow.""" if self.hass and not self.hass.data.get(DATA_ALEXAMEDIA): _LOGGER.info(STARTUP) _LOGGER.info("Loaded alexapy==%s", alexapy_version) self.login = None self.securitycode: Optional[Text] = None self.automatic_steps: int = 0 self.config = OrderedDict() self.proxy_schema = None self.data_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), (vol.Required(CONF_EMAIL), str), (vol.Required(CONF_PASSWORD), str), (vol.Required(CONF_URL, default="amazon.com"), str), (vol.Optional(CONF_SECURITYCODE), str), (vol.Optional(CONF_OTPSECRET), str), (vol.Optional(CONF_DEBUG, default=False), bool), (vol.Optional(CONF_INCLUDE_DEVICES, default=""), str), (vol.Optional(CONF_EXCLUDE_DEVICES, default=""), str), (vol.Optional(CONF_SCAN_INTERVAL, default=60), int), (vol.Optional(CONF_COOKIES_TXT, default=""), str), (vol.Optional(CONF_OAUTH_LOGIN, default=True), bool), ]) self.captcha_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), (vol.Required(CONF_PASSWORD), str), ( vol.Optional( CONF_SECURITYCODE, default=self.securitycode if self.securitycode else "", ), str, ), (vol.Required("captcha"), str), ]) self.twofactor_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), ( vol.Required( CONF_SECURITYCODE, default=self.securitycode if self.securitycode else "", ), str, ), ]) self.claimspicker_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), ( vol.Required("claimsoption", default=0), vol.All(cv.positive_int, vol.Clamp(min=0)), ), ]) self.authselect_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), ( vol.Required("authselectoption", default=0), vol.All(cv.positive_int, vol.Clamp(min=0)), ), ]) self.verificationcode_schema = OrderedDict([ (vol.Optional(CONF_PROXY, default=False), bool), (vol.Required("verificationcode"), str), ]) self.totp_register = OrderedDict([(vol.Optional(CONF_TOTP_REGISTER, default=False), bool)])
] CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_REGION, default=DEFAULT_REGION): cv.string, vol.Optional(CONF_MUTABLE, default=True): cv.boolean, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_UPDATE_INTERVAL): (vol.All(cv.time_period, vol.Clamp(min=MIN_UPDATE_INTERVAL))), vol.Optional(CONF_NAME, default={}): vol.Schema({cv.slug: cv.string}), vol.Optional(CONF_RESOURCES): vol.All(cv.ensure_list, [vol.In(RESOURCES)]) }), }, extra=vol.ALLOW_EXTRA) def setup(hass, config): """Setup Volkswagen Carnet component""" interval = config[DOMAIN].get(CONF_SCAN_INTERVAL) data = hass.data[DATA_KEY] = VolkswagenData(config) from volkswagencarnet import Connection
LEXUS_ID_FORMAT = '{}_{}' LEXUS_ID_LIST_SCHEMA = vol.Schema([int]) LEXUS_CONFIG_FILE = 'lexus_enform.conf' CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=300): vol.All(cv.positive_int, vol.Clamp(min=300)), vol.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, vol.Optional(CONF_PUSH_NOTIFICATIONS, default=False): cv.boolean, CONF_VINS: vol.All(cv.ensure_list, [{ vol.Required(CONF_VINS_VIN): cv.string, vol.Optional(CONF_VINS_FRIENDLY_NAME): cv.string, }]), }), }, extra=vol.ALLOW_EXTRA) NOTIFICATION_ID = 'tesla_integration_notification'
async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Xiaomi vacuum cleaner robot from a config entry.""" entities = [] if config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE: host = config_entry.data[CONF_HOST] token = config_entry.data[CONF_TOKEN] name = config_entry.title unique_id = config_entry.unique_id # Create handler _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) vacuum = Vacuum(host, token) mirobo = MiroboVacuum(name, vacuum, config_entry, unique_id) entities.append(mirobo) platform = entity_platform.async_get_current_platform() platform.async_register_entity_service( SERVICE_START_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_start.__name__, ) platform.async_register_entity_service( SERVICE_STOP_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_stop.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL, { vol.Optional(ATTR_RC_VELOCITY): vol.All( vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29) ), vol.Optional(ATTR_RC_ROTATION): vol.All( vol.Coerce(int), vol.Clamp(min=-179, max=179) ), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL_STEP, { vol.Optional(ATTR_RC_VELOCITY): vol.All( vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29) ), vol.Optional(ATTR_RC_ROTATION): vol.All( vol.Coerce(int), vol.Clamp(min=-179, max=179) ), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move_step.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_ZONE, { vol.Required(ATTR_ZONE_ARRAY): vol.All( list, [ vol.ExactSequence( [ vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), ] ) ], ), vol.Required(ATTR_ZONE_REPEATER): vol.All( vol.Coerce(int), vol.Clamp(min=1, max=3) ), }, MiroboVacuum.async_clean_zone.__name__, ) platform.async_register_entity_service( SERVICE_GOTO, { vol.Required("x_coord"): vol.Coerce(int), vol.Required("y_coord"): vol.Coerce(int), }, MiroboVacuum.async_goto.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_SEGMENT, {vol.Required("segments"): vol.Any(vol.Coerce(int), [vol.Coerce(int)])}, MiroboVacuum.async_clean_segment.__name__, ) async_add_entities(entities, update_before_add=True)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up Safegate Pro scene entries.""" _process_scenes_config(hass, async_add_entities, config) # This platform can be loaded multiple times. Only first time register the service. if hass.services.has_service(SCENE_DOMAIN, SERVICE_RELOAD): return # Store platform for later. platform = hass.data[ DATA_PLATFORM] = entity_platform.async_get_current_platform() async def reload_config(call): """Reload the scene config.""" try: conf = await conf_util.async_hass_config_yaml(hass) except HomeAssistantError as err: _LOGGER.error(err) return integration = await async_get_integration(hass, SCENE_DOMAIN) conf = await conf_util.async_process_component_config( hass, conf, integration) if not (conf and platform): return await platform.async_reset() # Extract only the config for the Safegate Pro platform, ignore the rest. for p_type, p_config in config_per_platform(conf, SCENE_DOMAIN): if p_type != HA_DOMAIN: continue _process_scenes_config(hass, async_add_entities, p_config) hass.bus.async_fire(EVENT_SCENE_RELOADED, context=call.context) hass.helpers.service.async_register_admin_service(SCENE_DOMAIN, SERVICE_RELOAD, reload_config) async def apply_service(call): """Apply a scene.""" reproduce_options = {} if ATTR_TRANSITION in call.data: reproduce_options[ATTR_TRANSITION] = call.data.get(ATTR_TRANSITION) await async_reproduce_state( hass, call.data[CONF_ENTITIES].values(), context=call.context, reproduce_options=reproduce_options, ) hass.services.async_register( SCENE_DOMAIN, SERVICE_APPLY, apply_service, vol.Schema({ vol.Optional(ATTR_TRANSITION): vol.All(vol.Coerce(float), vol.Clamp(min=0, max=6553)), vol.Required(CONF_ENTITIES): STATES_SCHEMA, }), ) async def create_service(call): """Create a scene.""" snapshot = call.data[CONF_SNAPSHOT] entities = call.data[CONF_ENTITIES] for entity_id in snapshot: state = hass.states.get(entity_id) if state is None: _LOGGER.warning( "Entity %s does not exist and therefore cannot be snapshotted", entity_id, ) continue entities[entity_id] = State(entity_id, state.state, state.attributes) if not entities: _LOGGER.warning("Empty scenes are not allowed") return scene_config = SCENECONFIG(None, call.data[CONF_SCENE_ID], None, entities) entity_id = f"{SCENE_DOMAIN}.{scene_config.name}" old = platform.entities.get(entity_id) if old is not None: if not old.from_service: _LOGGER.warning("The scene %s already exists", entity_id) return await platform.async_remove_entity(entity_id) async_add_entities( [HomeAssistantScene(hass, scene_config, from_service=True)]) hass.services.async_register(SCENE_DOMAIN, SERVICE_CREATE, create_service, CREATE_SCENE_SCHEMA)
| FEATURE_SET_DRY | FEATURE_SET_MOTOR_SPEED) FEATURE_FLAGS_AIRFRESH = (FEATURE_SET_BUZZER | FEATURE_SET_CHILD_LOCK | FEATURE_SET_LED | FEATURE_SET_LED_BRIGHTNESS | FEATURE_RESET_FILTER | FEATURE_SET_EXTRA_FEATURES) AIRPURIFIER_SERVICE_SCHEMA = vol.Schema( {vol.Optional(ATTR_ENTITY_ID): cv.entity_ids}) SERVICE_SCHEMA_LED_BRIGHTNESS = AIRPURIFIER_SERVICE_SCHEMA.extend({ vol.Required(ATTR_BRIGHTNESS): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=2)) }) SERVICE_SCHEMA_FAVORITE_LEVEL = AIRPURIFIER_SERVICE_SCHEMA.extend({ vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=17)) }) SERVICE_SCHEMA_FAN_LEVEL = AIRPURIFIER_SERVICE_SCHEMA.extend({ vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=3)) }) SERVICE_SCHEMA_VOLUME = AIRPURIFIER_SERVICE_SCHEMA.extend({ vol.Required(ATTR_VOLUME): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=100))
vol.All(vol.Coerce(int), vol.Range(min=1, max=12)), vol.Required(ATTR_WORK_TS, default=0): vol.All(vol.Coerce(int)) }) SERVICE_SCHEMA_DEL_MODES = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_DELMODES): vol.All(vol.Coerce(int), vol.Range(min=1, max=8)) }) SERVICE_SCHEMA_SET_VOICE = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_VOICE): vol.All(vol.Coerce(str), vol.Clamp('off', 'on')) }) SERVICE_SCHEMA_SET_MODE_SORT = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_MODE_SORT): vol.All(vol.Coerce(str)) }) ATTR_MODEL = "model" ATTR_PROFILE = "profile" SUCCESS = ["ok"] SERVICE_SCHEMA = vol.Schema({ # vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, })
class PhilipsGenericCoAPFan(PhilipsGenericCoAPFanBase): AVAILABLE_SPEEDS = { SPEED_OFF: {PHILIPS_POWER: "0"}, } AVAILABLE_ATTRIBUTES = [ # device information (ATTR_NAME, PHILIPS_NAME), (ATTR_TYPE, PHILIPS_TYPE), (ATTR_MODEL_ID, PHILIPS_MODEL_ID), (ATTR_PRODUCT_ID, PHILIPS_PRODUCT_ID), (ATTR_DEVICE_ID, PHILIPS_DEVICE_ID), (ATTR_DEVICE_VERSION, PHILIPS_DEVICE_VERSION), (ATTR_SOFTWARE_VERSION, PHILIPS_SOFTWARE_VERSION), (ATTR_WIFI_VERSION, PHILIPS_WIFI_VERSION), # device configuration (ATTR_LANGUAGE, PHILIPS_LANGUAGE), (ATTR_CHILD_LOCK, PHILIPS_CHILD_LOCK), (ATTR_LIGHT_BRIGHTNESS, PHILIPS_LIGHT_BRIGHTNESS), (ATTR_DISPLAY_BACKLIGHT, PHILIPS_DISPLAY_BACKLIGHT, PHILIPS_DISPLAY_BACKLIGHT_MAP), (ATTR_PREFERRED_INDEX, PHILIPS_PREFERRED_INDEX, PHILIPS_PREFERRED_INDEX_MAP), # filter information ( ATTR_FILTER_PRE_REMAINING, PHILIPS_FILTER_PRE_REMAINING, lambda x: str(timedelta(hours=x)), ), (ATTR_FILTER_HEPA_TYPE, PHILIPS_FILTER_HEPA_TYPE), ( ATTR_FILTER_HEPA_REMAINING, PHILIPS_FILTER_HEPA_REMAINING, lambda x: str(timedelta(hours=x)), ), (ATTR_FILTER_ACTIVE_CARBON_TYPE, PHILIPS_FILTER_ACTIVE_CARBON_TYPE), ( ATTR_FILTER_ACTIVE_CARBON_REMAINING, PHILIPS_FILTER_ACTIVE_CARBON_REMAINING, lambda x: str(timedelta(hours=x)), ), # device sensors (ATTR_RUNTIME, PHILIPS_RUNTIME, lambda x: str(timedelta(seconds=round(x / 1000)))), (ATTR_AIR_QUALITY_INDEX, PHILIPS_AIR_QUALITY_INDEX), (ATTR_INDOOR_ALLERGEN_INDEX, PHILIPS_INDOOR_ALLERGEN_INDEX), (ATTR_PM25, PHILIPS_PM25), ] SERVICE_SCHEMA_SET_LIGHT_BRIGHTNESS = vol.Schema( { vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_BRIGHTNESS): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=100)), } ) def register_services(self, async_register): async_register( domain=DOMAIN, service=SERVICE_SET_CHILD_LOCK_ON, service_func=self.async_set_child_lock_on, ) async_register( domain=DOMAIN, service=SERVICE_SET_CHILD_LOCK_OFF, service_func=self.async_set_child_lock_off, ) async_register( domain=DOMAIN, service=SERVICE_SET_DISPLAY_BACKLIGHT_ON, service_func=self.async_set_display_backlight_on, ) async_register( domain=DOMAIN, service=SERVICE_SET_DISPLAY_BACKLIGHT_OFF, service_func=self.async_set_display_backlight_off, ) async_register( domain=DOMAIN, service=SERVICE_SET_LIGHT_BRIGHTNESS, service_func=self.async_set_light_brightness, schema=self.SERVICE_SCHEMA_SET_LIGHT_BRIGHTNESS, ) async def async_set_child_lock_on(self): await self._client.set_control_value(PHILIPS_CHILD_LOCK, True) async def async_set_child_lock_off(self): await self._client.set_control_value(PHILIPS_CHILD_LOCK, False) async def async_set_display_backlight_on(self): await self._client.set_control_value(PHILIPS_DISPLAY_BACKLIGHT, "1") async def async_set_display_backlight_off(self): await self._client.set_control_value(PHILIPS_DISPLAY_BACKLIGHT, "0") async def async_set_light_brightness(self, brightness: int): await self._client.set_control_value(PHILIPS_LIGHT_BRIGHTNESS, brightness)
_LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = vol.Schema( vol.All( cv.deprecated(DOMAIN), { DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_UPDATE_INTERVAL): vol.All(cv.time_period, vol.Clamp(min=DEFAULT_UPDATE_INTERVAL)), vol.Optional(CONF_NAME, default={}): cv.schema_with_slug_keys(cv.string), vol.Optional(CONF_RESOURCES): vol.All(cv.ensure_list, [vol.In(RESOURCES)]), vol.Optional(CONF_REGION): cv.string, vol.Optional(CONF_SERVICE_URL): cv.string, vol.Optional(CONF_MUTABLE, default=True): cv.boolean, vol.Optional(CONF_SCANDINAVIAN_MILES, default=False): cv.boolean, }) }, ),
DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_DISTANCE_UNIT): vol.In([LENGTH_KILOMETERS, LENGTH_MILES]), vol.Optional(CONF_PRESSURE_UNIT): vol.In([PRESSURE_BAR, PRESSURE_PSI]), vol.Optional(CONF_DEBUG_DATA, default=False): cv.boolean, vol.Optional(CONF_PIN): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): (vol.All(vol.Coerce(int), vol.Clamp(min=MIN_SCAN_INTERVAL))), vol.Optional( CONF_HEALTH_UPDATE_INTERVAL, default=DEFAULT_HEATH_UPDATE_INTERVAL, ): vol.Coerce(int), }) }, extra=vol.ALLOW_EXTRA, ) async def async_setup(hass, config): """ JLR InControl uses config flow for configuration.
import logging _LOGGER = logging.getLogger(__name__) ATTR_ANGLE = 'angle' ATTR_ANION = 'anion' ATTR_INIT = 'init' SERVICE_SET_ANGLE = "yeelink_set_angle" SERVICE_SET_ANION = "yeelink_set_anion" SERVICE_SET_INIT = "yeelink_set_init" SET_SERVICE_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.entity_id}) SERVICE_SCHEMA_ANGLE = SET_SERVICE_SCHEMA.extend({ vol.Required(ATTR_ANGLE): vol.All(vol.Coerce(int), vol.Clamp(min=65, max=120)) }) SERVICE_SCHEMA_ANION = SET_SERVICE_SCHEMA.extend({ vol.Required(ATTR_ANION): vol.All(vol.Coerce(str), vol.Clamp('off', 'on')) }) SERVICE_SCHEMA_INIT = SET_SERVICE_SCHEMA.extend({ vol.Required(ATTR_INIT): vol.All(vol.Coerce(str), vol.Clamp('off', 'on')) }) YEELINKVEN_FAN_DEVICES = "yeelink.ven_fan.vf1"
ATTR_SPREAD = 'spread' ATTR_CHANGE = 'change' # aiolifx waveform modes WAVEFORM_SINE = 1 WAVEFORM_PULSE = 4 NEUTRAL_WHITE = 3500 LIFX_EFFECT_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(ATTR_POWER_ON, default=True): cv.boolean, }) LIFX_EFFECT_BREATHE_SCHEMA = LIFX_EFFECT_SCHEMA.extend({ ATTR_BRIGHTNESS: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)), ATTR_COLOR_NAME: cv.string, ATTR_RGB_COLOR: vol.All(vol.ExactSequence((cv.byte, cv.byte, cv.byte)), vol.Coerce(tuple)), vol.Optional(ATTR_PERIOD, default=1.0): vol.All(vol.Coerce(float), vol.Range(min=0.05)), vol.Optional(ATTR_CYCLES, default=1.0): vol.All(vol.Coerce(float), vol.Range(min=1)), }) LIFX_EFFECT_PULSE_SCHEMA = LIFX_EFFECT_BREATHE_SCHEMA LIFX_EFFECT_COLORLOOP_SCHEMA = LIFX_EFFECT_SCHEMA.extend({ ATTR_BRIGHTNESS: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)), vol.Optional(ATTR_PERIOD, default=60): vol.All(vol.Coerce(float), vol.Clamp(min=0.05)),
| FEATURE_SET_MOTOR_SPEED ) FEATURE_FLAGS_AIRFRESH = ( FEATURE_SET_BUZZER | FEATURE_SET_CHILD_LOCK | FEATURE_SET_LED | FEATURE_SET_LED_BRIGHTNESS | FEATURE_RESET_FILTER | FEATURE_SET_EXTRA_FEATURES ) AIRPURIFIER_SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids}) SERVICE_SCHEMA_LED_BRIGHTNESS = AIRPURIFIER_SERVICE_SCHEMA.extend( {vol.Required(ATTR_BRIGHTNESS): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=2))} ) SERVICE_SCHEMA_FAVORITE_LEVEL = AIRPURIFIER_SERVICE_SCHEMA.extend( {vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=17))} ) SERVICE_SCHEMA_FAN_LEVEL = AIRPURIFIER_SERVICE_SCHEMA.extend( {vol.Required(ATTR_LEVEL): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=3))} ) SERVICE_SCHEMA_VOLUME = AIRPURIFIER_SERVICE_SCHEMA.extend( {vol.Required(ATTR_VOLUME): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=100))} ) SERVICE_SCHEMA_EXTRA_FEATURES = AIRPURIFIER_SERVICE_SCHEMA.extend(
CONF_INDOOR_UNITS = 'indoor_units' CONF_INDOOR_UNIT_GLOBAL_NAME = "indoor_unit_global_name" MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) PLATFORMS = ["climate"] ADAPTERS_CONFIG = vol.Schema({ vol.Required(CONF_ADAPTER_HOST): cv.string, vol.Optional(CONF_ADAPTER_NAME, default='default'): cv.string, vol.Optional(CONF_ADAPTER_PORT, default=502): cv.port, vol.Optional(CONF_ADAPTER_SLAVE, default=1): vol.Clamp(min=1, max=63), }) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Optional(CONF_ADAPTERS, default=[]): vol.All(cv.ensure_list, [ADAPTERS_CONFIG]), }) }, extra=vol.ALLOW_EXTRA) async def async_setup(hass: HomeAssistant, config): """Establish connection with Daikin."""
CONF_GENDER, CONF_ENCODING, CONF_SPEED, CONF_PITCH, CONF_GAIN, CONF_PROFILES, CONF_TEXT_TYPE, ] GENDER_SCHEMA = vol.All(vol.Upper, vol.In(texttospeech.enums.SsmlVoiceGender.__members__)) VOICE_SCHEMA = cv.matches_regex(VOICE_REGEX) SCHEMA_ENCODING = vol.All(vol.Upper, vol.In(texttospeech.enums.AudioEncoding.__members__)) SPEED_SCHEMA = vol.All(vol.Coerce(float), vol.Clamp(min=MIN_SPEED, max=MAX_SPEED)) PITCH_SCHEMA = vol.All(vol.Coerce(float), vol.Clamp(min=MIN_PITCH, max=MAX_PITCH)) GAIN_SCHEMA = vol.All(vol.Coerce(float), vol.Clamp(min=MIN_GAIN, max=MAX_GAIN)) PROFILES_SCHEMA = vol.All(cv.ensure_list, [vol.In(SUPPORTED_PROFILES)]) TEXT_TYPE_SCHEMA = vol.All(vol.Lower, vol.In(SUPPORTED_TEXT_TYPES)) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_KEY_FILE): cv.string, vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORTED_LANGUAGES), vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): GENDER_SCHEMA, vol.Optional(CONF_VOICE, default=DEFAULT_VOICE): VOICE_SCHEMA,
SENSORS = [ "current_sleep", "current_sleep_fitness", "last_sleep", "bed_state", "bed_temp", "sleep_stage", ] SERVICE_HEAT_SET = "heat_set" ATTR_TARGET_HEAT = "target" ATTR_HEAT_DURATION = "duration" VALID_TARGET_HEAT = vol.All(vol.Coerce(int), vol.Clamp(min=-100, max=100)) VALID_DURATION = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=28800)) SERVICE_EIGHT_SCHEMA = vol.Schema({ ATTR_ENTITY_ID: cv.entity_ids, ATTR_TARGET_HEAT: VALID_TARGET_HEAT, ATTR_HEAT_DURATION: VALID_DURATION, }) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.All( cv.deprecated(CONF_PARTNER), vol.Schema({ vol.Required(CONF_USERNAME): cv.string,
CONF_CHILD_LOCK = 'lock' MIN_TEMP = 16 MAX_TEMP = 32 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_NAME): cv.string, vol.Required(CONF_TOKEN): cv.string, }) SERVICE_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, }) SERVICE_SCHEMA_SET_BUZZER = SERVICE_SCHEMA.extend({ vol.Required(CONF_BUZZER): vol.All(vol.Coerce(str), vol.Clamp('off', 'on')) }) SERVICE_SCHEMA_SET_BRIGHTNESS = SERVICE_SCHEMA.extend({ vol.Required(CONF_BRIGHTNESS): vol.All(vol.Coerce(int), vol.Range(min=0, max=2)), }) SERVICE_SCHEMA_SET_POWEROFF_TIME = SERVICE_SCHEMA.extend({ vol.Required(CONF_POWEROFF_TIME): vol.All(vol.Coerce(int), vol.Range(min=0, max=28800)), }) SERVICE_SCHEMA_SET_CHILD_LOCK = SERVICE_SCHEMA.extend({ vol.Required(CONF_CHILD_LOCK): vol.All(vol.Coerce(str), vol.Clamp('off', 'on')) }) SERVICE_TO_METHOD = { SERVICE_SET_BUZZER: {'method': 'async_set_buzzer', 'schema': SERVICE_SCHEMA_SET_BUZZER},
ATTR_CLEANING_TIME = 'cleaning_time' ATTR_DO_NOT_DISTURB = 'do_not_disturb' ATTR_MAIN_BRUSH_LEFT = 'main_brush_left' ATTR_SIDE_BRUSH_LEFT = 'side_brush_left' ATTR_FILTER_LEFT = 'filter_left' ATTR_CLEANING_COUNT = 'cleaning_count' ATTR_CLEANED_TOTAL_AREA = 'total_cleaned_area' ATTR_CLEANING_TOTAL_TIME = 'total_cleaning_time' ATTR_ERROR = 'error' ATTR_RC_DURATION = 'duration' ATTR_RC_ROTATION = 'rotation' ATTR_RC_VELOCITY = 'velocity' SERVICE_SCHEMA_REMOTE_CONTROL = VACUUM_SERVICE_SCHEMA.extend({ vol.Optional(ATTR_RC_VELOCITY): vol.All(vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29)), vol.Optional(ATTR_RC_ROTATION): vol.All(vol.Coerce(int), vol.Clamp(min=-179, max=179)), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }) SERVICE_TO_METHOD = { SERVICE_START_REMOTE_CONTROL: { 'method': 'async_remote_control_start' }, SERVICE_STOP_REMOTE_CONTROL: { 'method': 'async_remote_control_stop' }, SERVICE_MOVE_REMOTE_CONTROL: { 'method': 'async_remote_control_move',
] OPTIONAL_STATE_ATTRS = [ STATE_ATTR_SUNRISE, STATE_ATTR_SUNSET, STATE_ATTR_DAYLIGHT, STATE_ATTR_PREV_DAYLIGHT, STATE_ATTR_NEXT_DAYLIGHT ] STATE_ATTRS = DEFAULT_STATE_ATTRS + OPTIONAL_STATE_ATTRS CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Optional(CONF_MONITORED_CONDITIONS, default=DEFAULT_STATE_ATTRS): vol.All(cv.ensure_list, [vol.In(STATE_ATTRS)]), vol.Optional(CONF_SCAN_INTERVAL): vol.All(cv.time_period, vol.Clamp(min=MIN_SCAN_INTERVAL)) }) }, extra=vol.ALLOW_EXTRA) @asyncio.coroutine def async_setup(hass, config): """Track the state of the sun.""" _LOGGER.debug('config: {}'.format(config)) if config.get(CONF_ELEVATION) is not None: _LOGGER.warning( "Elevation is now configured in home assistant core. " "See https://home-assistant.io/docs/configuration/basic/") sun = Sun(hass, get_astral_location(hass), config[DOMAIN])
ATTR_REMINDER = "reminder" ATTR_EYECARE_MODE = "eyecare_mode" # Moonlight ATTR_SLEEP_ASSISTANT = "sleep_assistant" ATTR_SLEEP_OFF_TIME = "sleep_off_time" ATTR_TOTAL_ASSISTANT_SLEEP_TIME = "total_assistant_sleep_time" ATTR_BAND_SLEEP = "band_sleep" ATTR_BAND = "band" XIAOMI_MIIO_SERVICE_SCHEMA = vol.Schema( {vol.Optional(ATTR_ENTITY_ID): cv.entity_ids}) SERVICE_SCHEMA_SET_SCENE = XIAOMI_MIIO_SERVICE_SCHEMA.extend({ vol.Required(ATTR_SCENE): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=6)) }) SERVICE_SCHEMA_SET_DELAYED_TURN_OFF = XIAOMI_MIIO_SERVICE_SCHEMA.extend( {vol.Required(ATTR_TIME_PERIOD): cv.positive_time_period}) SERVICE_TO_METHOD = { SERVICE_SET_DELAYED_TURN_OFF: { "method": "async_set_delayed_turn_off", "schema": SERVICE_SCHEMA_SET_DELAYED_TURN_OFF, }, SERVICE_SET_SCENE: { "method": "async_set_scene", "schema": SERVICE_SCHEMA_SET_SCENE, }, SERVICE_REMINDER_ON: {
ATTR_GW_MAC = "gw_mac" ATTR_RINGTONE_ID = "ringtone_id" ATTR_RINGTONE_VOL = "ringtone_vol" TIME_TILL_UNAVAILABLE = timedelta(minutes=150) SERVICE_PLAY_RINGTONE = "play_ringtone" SERVICE_STOP_RINGTONE = "stop_ringtone" SERVICE_ADD_DEVICE = "add_device" SERVICE_REMOVE_DEVICE = "remove_device" SERVICE_SCHEMA_PLAY_RINGTONE = vol.Schema({ vol.Required(ATTR_RINGTONE_ID): vol.All(vol.Coerce(int), vol.NotIn([9, 14, 15, 16, 17, 18, 19])), vol.Optional(ATTR_RINGTONE_VOL): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=100)), }) SERVICE_SCHEMA_REMOVE_DEVICE = vol.Schema({ vol.Required(ATTR_DEVICE_ID): vol.All(cv.string, vol.Length(min=14, max=14)) }) def setup(hass, config): """Set up the Xiaomi component.""" def play_ringtone_service(call): """Service to play ringtone through Gateway.""" ring_id = call.data.get(ATTR_RINGTONE_ID) gateway = call.data.get(ATTR_GW_MAC)
# List of possible effects ATTR_EFFECT_LIST = "effect_list" # Apply an effect to the light, can be EFFECT_COLORLOOP. ATTR_EFFECT = "effect" EFFECT_COLORLOOP = "colorloop" EFFECT_RANDOM = "random" EFFECT_WHITE = "white" COLOR_GROUP = "Color descriptors" LIGHT_PROFILES_FILE = "light_profiles.csv" # Service call validation schemas VALID_TRANSITION = vol.All(vol.Coerce(float), vol.Clamp(min=0, max=6553)) VALID_BRIGHTNESS = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)) VALID_BRIGHTNESS_PCT = vol.All(vol.Coerce(float), vol.Range(min=0, max=100)) VALID_BRIGHTNESS_STEP = vol.All(vol.Coerce(int), vol.Clamp(min=-255, max=255)) VALID_BRIGHTNESS_STEP_PCT = vol.All(vol.Coerce(float), vol.Clamp(min=-100, max=100)) VALID_FLASH = vol.In([FLASH_SHORT, FLASH_LONG]) LIGHT_TURN_ON_SCHEMA = { vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string, ATTR_TRANSITION: VALID_TRANSITION, vol.Exclusive(ATTR_BRIGHTNESS, ATTR_BRIGHTNESS): VALID_BRIGHTNESS, vol.Exclusive(ATTR_BRIGHTNESS_PCT, ATTR_BRIGHTNESS): VALID_BRIGHTNESS_PCT, vol.Exclusive(ATTR_BRIGHTNESS_STEP, ATTR_BRIGHTNESS): VALID_BRIGHTNESS_STEP, vol.Exclusive(ATTR_BRIGHTNESS_STEP_PCT, ATTR_BRIGHTNESS): VALID_BRIGHTNESS_STEP_PCT, vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP): cv.string, vol.Exclusive(ATTR_RGB_COLOR, COLOR_GROUP): vol.All(
MIN_SCAN_INTERVAL, TESLA_COMPONENTS, ) _LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(cv.positive_int, vol.Clamp(min=MIN_SCAN_INTERVAL)), }) }, extra=vol.ALLOW_EXTRA, ) @callback def _async_save_tokens(hass, config_entry, access_token, refresh_token): hass.config_entries.async_update_entry( config_entry, data={ **config_entry.data, CONF_ACCESS_TOKEN: access_token, CONF_TOKEN: refresh_token, },
async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Xiaomi vacuum cleaner robot from a config entry.""" entities = [] if config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE: name = config_entry.title unique_id = config_entry.unique_id mirobo = MiroboVacuum( name, hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE], config_entry, unique_id, hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], ) entities.append(mirobo) platform = entity_platform.async_get_current_platform() platform.async_register_entity_service( SERVICE_START_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_start.__name__, ) platform.async_register_entity_service( SERVICE_STOP_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_stop.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL, { vol.Optional(ATTR_RC_VELOCITY): vol.All( vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29) ), vol.Optional(ATTR_RC_ROTATION): vol.All( vol.Coerce(int), vol.Clamp(min=-179, max=179) ), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL_STEP, { vol.Optional(ATTR_RC_VELOCITY): vol.All( vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29) ), vol.Optional(ATTR_RC_ROTATION): vol.All( vol.Coerce(int), vol.Clamp(min=-179, max=179) ), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move_step.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_ZONE, { vol.Required(ATTR_ZONE_ARRAY): vol.All( list, [ vol.ExactSequence( [ vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), ] ) ], ), vol.Required(ATTR_ZONE_REPEATER): vol.All( vol.Coerce(int), vol.Clamp(min=1, max=3) ), }, MiroboVacuum.async_clean_zone.__name__, ) platform.async_register_entity_service( SERVICE_GOTO, { vol.Required("x_coord"): vol.Coerce(int), vol.Required("y_coord"): vol.Coerce(int), }, MiroboVacuum.async_goto.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_SEGMENT, {vol.Required("segments"): vol.Any(vol.Coerce(int), [vol.Coerce(int)])}, MiroboVacuum.async_clean_segment.__name__, ) async_add_entities(entities, update_before_add=True)
async def async_step_init(self, user_input=None): """Handle options flow.""" if user_input is not None: return self.async_create_entry(title="", data=user_input) api_key = self.config_entry.data.get(CONF_API_KEY) st_dev = self.config_entry.data.get(CONF_DEVICE_ID) use_st = api_key and st_dev data_schema = vol.Schema( { vol.Optional( CONF_APP_LOAD_METHOD, default=self.config_entry.options.get( CONF_APP_LOAD_METHOD, AppLoadMethod.All.value), ): vol.In(APP_LOAD_METHODS), vol.Optional( CONF_APP_LAUNCH_METHOD, default=self.config_entry.options.get( CONF_APP_LAUNCH_METHOD, AppLaunchMethod.Standard.value), ): vol.In(APP_LAUNCH_METHODS), vol.Optional( CONF_DUMP_APPS, default=self.config_entry.options.get( CONF_DUMP_APPS, False), ): bool, }) if use_st: data_schema = data_schema.extend({ vol.Optional( CONF_USE_ST_STATUS_INFO, default=self.config_entry.options.get( CONF_USE_ST_STATUS_INFO, True), ): bool, vol.Optional( CONF_USE_ST_CHANNEL_INFO, default=self.config_entry.options.get( CONF_USE_ST_CHANNEL_INFO, True), ): bool, vol.Optional( CONF_SHOW_CHANNEL_NR, default=self.config_entry.options.get( CONF_SHOW_CHANNEL_NR, False), ): bool, vol.Optional( CONF_POWER_ON_METHOD, default=self.config_entry.options.get( CONF_POWER_ON_METHOD, PowerOnMethod.WOL.value), ): vol.In(POWER_ON_METHODS), }) data_schema = data_schema.extend( { vol.Optional( CONF_WOL_REPEAT, default=min( self.config_entry.options.get(CONF_WOL_REPEAT, 1), MAX_WOL_REPEAT, ), ): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=MAX_WOL_REPEAT)), vol.Optional( CONF_POWER_ON_DELAY, default=self.config_entry.options.get( CONF_POWER_ON_DELAY, DEFAULT_POWER_ON_DELAY), ): vol.All(vol.Coerce(int), vol.Clamp(min=0, max=60)), vol.Optional( CONF_USE_MUTE_CHECK, default=self.config_entry.options.get( CONF_USE_MUTE_CHECK, True), ): bool, vol.Optional( CONF_SYNC_TURN_OFF, default=self.config_entry.options.get( CONF_SYNC_TURN_OFF, ""), ): str, vol.Optional( CONF_SYNC_TURN_ON, default=self.config_entry.options.get( CONF_SYNC_TURN_ON, ""), ): str }) return self.async_show_form(step_id="init", data_schema=data_schema)
MESSAGE_TIMEOUT = 1 MESSAGE_RETRIES = 8 UNAVAILABLE_GRACE = 90 FIX_MAC_FW = AwesomeVersion("3.70") SERVICE_LIFX_SET_STATE = "set_state" ATTR_INFRARED = "infrared" ATTR_ZONES = "zones" ATTR_POWER = "power" LIFX_SET_STATE_SCHEMA = cv.make_entity_service_schema( { **LIGHT_TURN_ON_SCHEMA, ATTR_INFRARED: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)), ATTR_ZONES: vol.All(cv.ensure_list, [cv.positive_int]), ATTR_POWER: cv.boolean, } ) SERVICE_EFFECT_PULSE = "effect_pulse" SERVICE_EFFECT_COLORLOOP = "effect_colorloop" SERVICE_EFFECT_STOP = "effect_stop" ATTR_POWER_ON = "power_on" ATTR_PERIOD = "period" ATTR_CYCLES = "cycles" ATTR_SPREAD = "spread" ATTR_CHANGE = "change"
LIGHT_PROFILES_FILE = "light_profiles.csv" PROP_TO_ATTR = { 'brightness': ATTR_BRIGHTNESS, 'color_temp': ATTR_COLOR_TEMP, 'min_mireds': ATTR_MIN_MIREDS, 'max_mireds': ATTR_MAX_MIREDS, 'rgb_color': ATTR_RGB_COLOR, 'xy_color': ATTR_XY_COLOR, 'white_value': ATTR_WHITE_VALUE, 'effect_list': ATTR_EFFECT_LIST, 'effect': ATTR_EFFECT, } # Service call validation schemas VALID_TRANSITION = vol.All(vol.Coerce(float), vol.Clamp(min=0, max=6553)) VALID_BRIGHTNESS = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)) VALID_BRIGHTNESS_PCT = vol.All(vol.Coerce(float), vol.Range(min=0, max=100)) LIGHT_TURN_ON_SCHEMA = vol.Schema({ ATTR_ENTITY_ID: cv.entity_ids, vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string, ATTR_TRANSITION: VALID_TRANSITION, ATTR_BRIGHTNESS: VALID_BRIGHTNESS, ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT, vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP):
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Xiaomi vacuum cleaner robot platform.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config[CONF_HOST] token = config[CONF_TOKEN] name = config[CONF_NAME] # Create handler _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5]) vacuum = Vacuum(host, token) mirobo = MiroboVacuum(name, vacuum) hass.data[DATA_KEY][host] = mirobo async_add_entities([mirobo], update_before_add=True) platform = entity_platform.current_platform.get() platform.async_register_entity_service( SERVICE_START_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_start.__name__, ) platform.async_register_entity_service( SERVICE_STOP_REMOTE_CONTROL, {}, MiroboVacuum.async_remote_control_stop.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL, { vol.Optional(ATTR_RC_VELOCITY): vol.All(vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29)), vol.Optional(ATTR_RC_ROTATION): vol.All(vol.Coerce(int), vol.Clamp(min=-179, max=179)), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move.__name__, ) platform.async_register_entity_service( SERVICE_MOVE_REMOTE_CONTROL_STEP, { vol.Optional(ATTR_RC_VELOCITY): vol.All(vol.Coerce(float), vol.Clamp(min=-0.29, max=0.29)), vol.Optional(ATTR_RC_ROTATION): vol.All(vol.Coerce(int), vol.Clamp(min=-179, max=179)), vol.Optional(ATTR_RC_DURATION): cv.positive_int, }, MiroboVacuum.async_remote_control_move_step.__name__, ) platform.async_register_entity_service( SERVICE_CLEAN_ZONE, { vol.Required(ATTR_ZONE_ARRAY): vol.All( list, [ vol.ExactSequence([ vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), vol.Coerce(int), ]) ], ), vol.Required(ATTR_ZONE_REPEATER): vol.All(vol.Coerce(int), vol.Clamp(min=1, max=3)), }, MiroboVacuum.async_clean_zone.__name__, ) platform.async_register_entity_service( SERVICE_GOTO, { vol.Required("x_coord"): vol.Coerce(int), vol.Required("y_coord"): vol.Coerce(int), }, MiroboVacuum.async_goto.__name__, )