CONF_SLOT = "slot" CONF_COMMANDS = "commands" DEFAULT_TIMEOUT = 10 DEFAULT_SLOT = 1 COMMAND_SCHEMA = vol.Schema( {vol.Required(CONF_COMMAND): vol.All(cv.ensure_list, [cv.string])} ) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Optional(CONF_NAME): cv.string, vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.All( int, vol.Range(min=0) ), vol.Optional(CONF_SLOT, default=DEFAULT_SLOT): vol.All( int, vol.Range(min=1, max=1000000) ), vol.Required(CONF_TOKEN): vol.All(str, vol.Length(min=32, max=32)), vol.Optional(CONF_COMMANDS, default={}): cv.schema_with_slug_keys( COMMAND_SCHEMA ), }, extra=vol.ALLOW_EXTRA, ) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Xiaomi IR Remote (Chuangmi IR) platform."""
"open_tilt": SUPPORT_OPEN_TILT, "set_position": SUPPORT_SET_POSITION, "set_tilt_position": SUPPORT_SET_TILT_POSITION, "stop_tilt": SUPPORT_STOP_TILT, "stop": SUPPORT_STOP, "up": SUPPORT_OPEN, } ELERO_COVER_DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(ELERO_COVER_DEVICE_CLASSES)) SUPPORTED_FEATURES_SCHEMA = vol.All(cv.ensure_list, [vol.In(SUPPORTED_FEATURES)]) # It is needed because of the transmitter has a channel handling bug. CHANNEL_NUMBERS_SCHEMA = vol.All(vol.Coerce(int), vol.Range(min=1, max=15)) # Validation of the user's configuration. COVER_SCHEMA = vol.Schema({ vol.Required(CONF_CHANNEL): CHANNEL_NUMBERS_SCHEMA, vol.Required(CONF_DEVICE_CLASS): ELERO_COVER_DEVICE_CLASSES_SCHEMA, vol.Required(CONF_NAME): str, vol.Required(CONF_SUPPORTED_FEATURES): SUPPORTED_FEATURES_SCHEMA, vol.Required(CONF_TRANSMITTER_SERIAL_NUMBER): str, }) # Validation of the user's configuration. PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_COVERS): vol.Schema({cv.slug: COVER_SCHEMA}), })
| SUPPORT_TURN_OFF | SUPPORT_SELECT_SOURCE) ZONE_SCHEMA = vol.Schema({vol.Required(CONF_NAME): cv.string}) SOURCE_SCHEMA = vol.Schema({vol.Required(CONF_NAME): cv.string}) CONF_ZONES = "zones" CONF_SOURCES = "sources" DATA_MONOPRICE = "monoprice" # Valid zone ids: 11-16 or 21-26 or 31-36 ZONE_IDS = vol.All( vol.Coerce(int), vol.Any(vol.Range(min=11, max=16), vol.Range(min=21, max=26), vol.Range(min=31, max=36)), ) # Valid source ids: 1-6 SOURCE_IDS = vol.All(vol.Coerce(int), vol.Range(min=1, max=6)) MEDIA_PLAYER_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.comp_entity_ids}) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_PORT): cv.string, vol.Required(CONF_ZONES): vol.Schema({ZONE_IDS: ZONE_SCHEMA}), vol.Required(CONF_SOURCES): vol.Schema({SOURCE_IDS: SOURCE_SCHEMA}),
DEFAULT_VOLUME = 0 DEFAULT_PITCH = "default" DEFAULT_CONTOUR = "" DEFAULT_REGION = "eastus" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORTED_LANGUAGES), vol.Optional(CONF_GENDER, default=DEFAULT_GENDER): vol.In(GENDERS), vol.Optional(CONF_TYPE, default=DEFAULT_TYPE): cv.string, vol.Optional(CONF_RATE, default=DEFAULT_RATE): vol.All(vol.Coerce(int), vol.Range(-100, 100)), vol.Optional(CONF_VOLUME, default=DEFAULT_VOLUME): vol.All(vol.Coerce(int), vol.Range(-100, 100)), vol.Optional(CONF_PITCH, default=DEFAULT_PITCH): cv.string, vol.Optional(CONF_CONTOUR, default=DEFAULT_CONTOUR): cv.string, vol.Optional(CONF_REGION, default=DEFAULT_REGION): cv.string, }) def get_engine(hass, config, discovery_info=None): """Set up Microsoft speech component.""" return MicrosoftProvider( config[CONF_API_KEY],
DEFAULT_TIMEOUT = 20 DEFAULT_CYCLETIME = 2 MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string, vol.Optional(CONF_PASSWORD, default=DEFAULT_PASSWORD): cv.string, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.All(vol.Coerce(int), vol.Range(min=1, max=600)), vol.Optional(CONF_CYCLETIME, default=DEFAULT_CYCLETIME): vol.All(vol.Coerce(int), vol.Range(min=1, max=600)), }) def setup_platform(hass, config, add_entities, discovery_info=None): """Find and return DIN III Relay switch.""" import dlipower host = config.get(CONF_HOST) controller_name = config.get(CONF_NAME) user = config.get(CONF_USERNAME) pswd = config.get(CONF_PASSWORD) tout = config.get(CONF_TIMEOUT) cycl = config.get(CONF_CYCLETIME)
class ClimateSchema: """Voluptuous schema for KNX climate devices.""" CONF_SETPOINT_SHIFT_ADDRESS = "setpoint_shift_address" CONF_SETPOINT_SHIFT_STATE_ADDRESS = "setpoint_shift_state_address" CONF_SETPOINT_SHIFT_MODE = "setpoint_shift_mode" CONF_SETPOINT_SHIFT_MAX = "setpoint_shift_max" CONF_SETPOINT_SHIFT_MIN = "setpoint_shift_min" CONF_TEMPERATURE_ADDRESS = "temperature_address" CONF_TEMPERATURE_STEP = "temperature_step" CONF_TARGET_TEMPERATURE_ADDRESS = "target_temperature_address" CONF_TARGET_TEMPERATURE_STATE_ADDRESS = "target_temperature_state_address" CONF_OPERATION_MODE_ADDRESS = "operation_mode_address" CONF_OPERATION_MODE_STATE_ADDRESS = "operation_mode_state_address" CONF_CONTROLLER_STATUS_ADDRESS = "controller_status_address" CONF_CONTROLLER_STATUS_STATE_ADDRESS = "controller_status_state_address" CONF_CONTROLLER_MODE_ADDRESS = "controller_mode_address" CONF_CONTROLLER_MODE_STATE_ADDRESS = "controller_mode_state_address" CONF_HEAT_COOL_ADDRESS = "heat_cool_address" CONF_HEAT_COOL_STATE_ADDRESS = "heat_cool_state_address" CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS = ( "operation_mode_frost_protection_address") CONF_OPERATION_MODE_NIGHT_ADDRESS = "operation_mode_night_address" CONF_OPERATION_MODE_COMFORT_ADDRESS = "operation_mode_comfort_address" CONF_OPERATION_MODE_STANDBY_ADDRESS = "operation_mode_standby_address" CONF_OPERATION_MODES = "operation_modes" CONF_CONTROLLER_MODES = "controller_modes" CONF_ON_OFF_ADDRESS = "on_off_address" CONF_ON_OFF_STATE_ADDRESS = "on_off_state_address" CONF_ON_OFF_INVERT = "on_off_invert" CONF_MIN_TEMP = "min_temp" CONF_MAX_TEMP = "max_temp" CONF_CREATE_TEMPERATURE_SENSORS = "create_temperature_sensors" DEFAULT_NAME = "KNX Climate" DEFAULT_SETPOINT_SHIFT_MODE = "DPT6010" DEFAULT_SETPOINT_SHIFT_MAX = 6 DEFAULT_SETPOINT_SHIFT_MIN = -6 DEFAULT_TEMPERATURE_STEP = 0.1 DEFAULT_ON_OFF_INVERT = False SCHEMA = vol.All( cv.deprecated("setpoint_shift_step", replacement_key=CONF_TEMPERATURE_STEP), vol.Schema({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_SETPOINT_SHIFT_MODE, default=DEFAULT_SETPOINT_SHIFT_MODE): vol.All(vol.Upper, cv.enum(SetpointShiftMode)), vol.Optional(CONF_SETPOINT_SHIFT_MAX, default=DEFAULT_SETPOINT_SHIFT_MAX): vol.All(int, vol.Range(min=0, max=32)), vol.Optional(CONF_SETPOINT_SHIFT_MIN, default=DEFAULT_SETPOINT_SHIFT_MIN): vol.All(int, vol.Range(min=-32, max=0)), vol.Optional(CONF_TEMPERATURE_STEP, default=DEFAULT_TEMPERATURE_STEP): vol.All(float, vol.Range(min=0, max=2)), vol.Required(CONF_TEMPERATURE_ADDRESS): ga_list_validator, vol.Required(CONF_TARGET_TEMPERATURE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_TARGET_TEMPERATURE_ADDRESS): ga_list_validator, vol.Optional(CONF_SETPOINT_SHIFT_ADDRESS): ga_list_validator, vol.Optional(CONF_SETPOINT_SHIFT_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_STATUS_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_STATUS_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_MODE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_MODE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_HEAT_COOL_ADDRESS): ga_list_validator, vol.Optional(CONF_HEAT_COOL_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_NIGHT_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_COMFORT_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_STANDBY_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT): cv.boolean, vol.Optional(CONF_OPERATION_MODES): vol.All(cv.ensure_list, [vol.In({**PRESET_MODES})]), vol.Optional(CONF_CONTROLLER_MODES): vol.All(cv.ensure_list, [vol.In({**CONTROLLER_MODES})]), vol.Optional(CONF_MIN_TEMP): vol.Coerce(float), vol.Optional(CONF_MAX_TEMP): vol.Coerce(float), vol.Optional(CONF_CREATE_TEMPERATURE_SENSORS, default=False): cv.boolean, }), )
CONF_MAX_CT = 'max_colortemp' DEFAULT_MAX_CT = 5500 CONF_SUNRISE_OFFSET = 'sunrise_offset' CONF_SUNSET_OFFSET = 'sunset_offset' CONF_SUNRISE_TIME = 'sunrise_time' CONF_SUNSET_TIME = 'sunset_time' CONF_INTERVAL = 'interval' DEFAULT_INTERVAL = 300 DEFAULT_TRANSITION = 60 CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Optional(CONF_MIN_CT, default=DEFAULT_MIN_CT): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)), vol.Optional(CONF_MAX_CT, default=DEFAULT_MAX_CT): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)), vol.Optional(CONF_SUNRISE_OFFSET): cv.time_period_str, vol.Optional(CONF_SUNSET_OFFSET): cv.time_period_str, vol.Optional(CONF_SUNRISE_TIME): cv.time, vol.Optional(CONF_SUNSET_TIME): cv.time, vol.Optional(CONF_LATITUDE): cv.latitude, vol.Optional(CONF_LONGITUDE): cv.longitude, vol.Optional(CONF_ELEVATION):
def __init__(self, config_entry): self.config_entry = config_entry _LOGGER.debug(f"{DOMAIN} EufySecurityOptionFlowHandler - {config_entry.data}") self.schema = vol.Schema( { vol.Optional( CONF_SYNC_INTERVAL, default=self.config_entry.options.get( CONF_SYNC_INTERVAL, DEFAULT_SYNC_INTERVAL ), ): vol.All(vol.Coerce(int), vol.Range(min=1, max=9999)), vol.Optional( CONF_USE_RTSP_SERVER_ADDON, default=self.config_entry.options.get( CONF_USE_RTSP_SERVER_ADDON, DEFAULT_USE_RTSP_SERVER_ADDON ), ): bool, vol.Optional( CONF_RTSP_SERVER_ADDRESS, default=self.config_entry.options.get( CONF_RTSP_SERVER_ADDRESS, config_entry.data.get(CONF_HOST) ), ): str, vol.Optional( CONF_RTSP_SERVER_PORT, default=self.config_entry.options.get( CONF_RTSP_SERVER_PORT, DEFAULT_RTSP_SERVER_PORT ), ): int, vol.Optional( CONF_FFMPEG_ANALYZE_DURATION, default=self.config_entry.options.get( CONF_FFMPEG_ANALYZE_DURATION, DEFAULT_FFMPEG_ANALYZE_DURATION ), ): vol.All(vol.Coerce(float), vol.Range(min=1, max=5)), vol.Optional( CONF_AUTO_START_STREAM, default=self.config_entry.options.get( CONF_AUTO_START_STREAM, DEFAULT_AUTO_START_STREAM ), ): bool, vol.Optional( CONF_FIX_BINARY_SENSOR_STATE, default=self.config_entry.options.get( CONF_FIX_BINARY_SENSOR_STATE, DEFAULT_FIX_BINARY_SENSOR_STATE ), ): bool, vol.Optional( CONF_MAP_EXTRA_ALARM_MODES, default=self.config_entry.options.get( CONF_MAP_EXTRA_ALARM_MODES, DEFAULT_MAP_EXTRA_ALARM_MODES ), ): bool, vol.Optional( CONF_NAME_FOR_CUSTOM1, default=self.config_entry.options.get( CONF_NAME_FOR_CUSTOM1, DEFAULT_NAME_FOR_CUSTOM1 ), ): str, vol.Optional( CONF_NAME_FOR_CUSTOM2, default=self.config_entry.options.get( CONF_NAME_FOR_CUSTOM2, DEFAULT_NAME_FOR_CUSTOM2 ), ): str, vol.Optional( CONF_NAME_FOR_CUSTOM3, default=self.config_entry.options.get( CONF_NAME_FOR_CUSTOM3, DEFAULT_NAME_FOR_CUSTOM3 ), ): str, } )
SERVICE_PERMIT = "permit" SERVICE_REMOVE = "remove" SERVICE_SET_ZIGBEE_CLUSTER_ATTRIBUTE = "set_zigbee_cluster_attribute" SERVICE_ISSUE_ZIGBEE_CLUSTER_COMMAND = "issue_zigbee_cluster_command" SERVICE_DIRECT_ZIGBEE_BIND = "issue_direct_zigbee_bind" SERVICE_DIRECT_ZIGBEE_UNBIND = "issue_direct_zigbee_unbind" SERVICE_ZIGBEE_BIND = "service_zigbee_bind" IEEE_SERVICE = "ieee_based_service" SERVICE_SCHEMAS = { SERVICE_PERMIT: vol.Schema({ vol.Optional(ATTR_IEEE_ADDRESS, default=None): convert_ieee, vol.Optional(ATTR_DURATION, default=60): vol.All(vol.Coerce(int), vol.Range(0, 254)), }), IEEE_SERVICE: vol.Schema({vol.Required(ATTR_IEEE_ADDRESS): convert_ieee}), SERVICE_SET_ZIGBEE_CLUSTER_ATTRIBUTE: vol.Schema({ vol.Required(ATTR_IEEE): convert_ieee, vol.Required(ATTR_ENDPOINT_ID): cv.positive_int, vol.Required(ATTR_CLUSTER_ID): cv.positive_int, vol.Optional(ATTR_CLUSTER_TYPE, default=CLUSTER_TYPE_IN): cv.string, vol.Required(ATTR_ATTRIBUTE): cv.positive_int, vol.Required(ATTR_VALUE): cv.string, vol.Optional(ATTR_MANUFACTURER): cv.positive_int, }), SERVICE_ISSUE_ZIGBEE_CLUSTER_COMMAND: vol.Schema({
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_MONITORED_CONDITIONS): vol.All( cv.ensure_list, [vol.In(SENSOR_TYPES)] ), vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_UNITS): vol.In(ALLOWED_UNITS), vol.Optional(CONF_LANGUAGE, default=DEFAULT_LANGUAGE): vol.In(LANGUAGE_CODES), vol.Inclusive( CONF_LATITUDE, "coordinates", "Latitude and longitude must exist together" ): cv.latitude, vol.Inclusive( CONF_LONGITUDE, "coordinates", "Latitude and longitude must exist together" ): cv.longitude, vol.Optional(CONF_FORECAST): vol.All(cv.ensure_list, [vol.Range(min=0, max=7)]), vol.Optional(CONF_HOURLY_FORECAST): vol.All( cv.ensure_list, [vol.Range(min=0, max=48)] ), } ) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Dark Sky sensor.""" latitude = config.get(CONF_LATITUDE, hass.config.latitude) longitude = config.get(CONF_LONGITUDE, hass.config.longitude) language = config.get(CONF_LANGUAGE) interval = config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL) if CONF_UNITS in config:
SERVICE_DISABLE_MOTION_RECORDING = 'amcrest_disable_motion_recording' SERVICE_GOTO_PRESET = 'amcrest_goto_preset' SERVICE_SET_COLOR_BW = 'amcrest_set_color_bw' SERVICE_START_TOUR = 'amcrest_tour_on' SERVICE_STOP_TOUR = 'amcrest_tour_off' ATTR_PRESET = 'preset' ATTR_COLOR_BW = 'color_bw' CBW_COLOR = 'color' CBW_AUTO = 'auto' CBW_BW = 'bw' CBW = [CBW_COLOR, CBW_AUTO, CBW_BW] SERVICE_GOTO_PRESET_SCHEMA = CAMERA_SERVICE_SCHEMA.extend({ vol.Required(ATTR_PRESET): vol.All(vol.Coerce(int), vol.Range(min=1)), }) SERVICE_SET_COLOR_BW_SCHEMA = CAMERA_SERVICE_SCHEMA.extend({ vol.Required(ATTR_COLOR_BW): vol.In(CBW), }) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up an Amcrest IP Camera.""" if discovery_info is None: return device_name = discovery_info[CONF_NAME] amcrest = hass.data[DATA_AMCREST][device_name]
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_MIN_TEMP, default=16): vol.Coerce(int), vol.Optional(CONF_MAX_TEMP, default=30): vol.Coerce(int), }) SERVICE_LEARN_COMMAND = "xiaomi_miio_learn_command" SERVICE_SEND_COMMAND = "xiaomi_miio_send_command" SERVICE_SCHEMA = vol.Schema({vol.Optional(ATTR_ENTITY_ID): cv.entity_ids}) SERVICE_SCHEMA_LEARN_COMMAND = SERVICE_SCHEMA.extend({ vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.All(int, vol.Range(min=0)), vol.Optional(CONF_SLOT, default=DEFAULT_SLOT): vol.All(int, vol.Range(min=2, max=1000000)), }) SERVICE_SCHEMA_SEND_COMMAND = SERVICE_SCHEMA.extend( {vol.Optional(CONF_COMMAND): cv.string}) SERVICE_TO_METHOD = { SERVICE_LEARN_COMMAND: { "method": "async_learn_command", "schema": SERVICE_SCHEMA_LEARN_COMMAND, }, SERVICE_SEND_COMMAND: { "method": "async_send_command", "schema": SERVICE_SCHEMA_SEND_COMMAND,
import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml.components import sensor from esphomeyaml.components.dallas import DallasComponent from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \ CONF_RESOLUTION, CONF_UPDATE_INTERVAL from esphomeyaml.helpers import HexIntLiteral, get_variable PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({ vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int, vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int, vol.Optional(CONF_DALLAS_ID): cv.variable_id, vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=8, max=12)), }).extend(sensor.SENSOR_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX)) def to_code(config): hub = get_variable(config.get(CONF_DALLAS_ID), DallasComponent) update_interval = config.get(CONF_UPDATE_INTERVAL) if CONF_RESOLUTION in config and update_interval is None: update_interval = 10000 if CONF_ADDRESS in config: address = HexIntLiteral(config[CONF_ADDRESS]) rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, update_interval, config.get(CONF_RESOLUTION)) else: rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX], update_interval, config.get(CONF_RESOLUTION)) sensor.register_sensor(rhs, config)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Xiaomi IR Remote (Chuangmi IR) platform.""" host = config[CONF_HOST] token = config[CONF_TOKEN] # Create handler _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5]) # The Chuang Mi IR Remote Controller wants to be re-discovered every # 5 minutes. As long as polling is disabled the device should be # re-discovered (lazy_discover=False) in front of every command. device = ChuangmiIr(host, token, lazy_discover=False) # Check that we can communicate with device. try: device_info = await hass.async_add_executor_job(device.info) model = device_info.model unique_id = f"{model}-{device_info.mac_address}" _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) except DeviceException as ex: _LOGGER.error("Device unavailable or token incorrect: %s", ex) raise PlatformNotReady if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} friendly_name = config.get(CONF_NAME, f"xiaomi_miio_{host.replace('.', '_')}") slot = config.get(CONF_SLOT) timeout = config.get(CONF_TIMEOUT) xiaomi_miio_remote = XiaomiMiioRemote( friendly_name, device, unique_id, slot, timeout, config.get(CONF_COMMANDS) ) hass.data[DATA_KEY][host] = xiaomi_miio_remote async_add_entities([xiaomi_miio_remote]) async def async_service_led_off_handler(entity, service): """Handle set_led_off command.""" await hass.async_add_executor_job(entity.device.set_indicator_led, False) async def async_service_led_on_handler(entity, service): """Handle set_led_on command.""" await hass.async_add_executor_job(entity.device.set_indicator_led, True) async def async_service_learn_handler(entity, service): """Handle a learn command.""" device = entity.device slot = service.data.get(CONF_SLOT, entity.slot) await hass.async_add_executor_job(device.learn, slot) timeout = service.data.get(CONF_TIMEOUT, entity.timeout) _LOGGER.info("Press the key you want Home Assistant to learn") start_time = utcnow() while (utcnow() - start_time) < timedelta(seconds=timeout): message = await hass.async_add_executor_job(device.read, slot) _LOGGER.debug("Message received from device: '%s'", message) if "code" in message and message["code"]: log_msg = "Received command is: {}".format(message["code"]) _LOGGER.info(log_msg) hass.components.persistent_notification.async_create( log_msg, title="Xiaomi Miio Remote" ) return if "error" in message and message["error"]["message"] == "learn timeout": await hass.async_add_executor_job(device.learn, slot) await asyncio.sleep(1) _LOGGER.error("Timeout. No infrared command captured") hass.components.persistent_notification.async_create( "Timeout. No infrared command captured", title="Xiaomi Miio Remote" ) platform = entity_platform.current_platform.get() platform.async_register_entity_service( SERVICE_LEARN, { vol.Optional(CONF_TIMEOUT, default=10): vol.All(int, vol.Range(min=0)), vol.Optional(CONF_SLOT, default=1): vol.All( int, vol.Range(min=1, max=1000000) ), }, async_service_learn_handler, ) platform.async_register_entity_service( SERVICE_SET_LED_ON, {}, async_service_led_on_handler, ) platform.async_register_entity_service( SERVICE_SET_LED_OFF, {}, async_service_led_off_handler, )
_VALID_QOS_SCHEMA = vol.All(vol.Coerce(int), vol.In([0, 1, 2])) _HBMQTT_CONFIG_SCHEMA = vol.Schema(dict) CLIENT_KEY_AUTH_MSG = 'client_key and client_cert must both be present in ' \ 'the mqtt broker config' CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ vol.Optional(CONF_CLIENT_ID): cv.string, vol.Optional(CONF_KEEPALIVE, default=DEFAULT_KEEPALIVE): vol.All(vol.Coerce(int), vol.Range(min=15)), vol.Optional(CONF_BROKER): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_CERTIFICATE): cv.isfile, vol.Inclusive(CONF_CLIENT_KEY, 'client_key_auth', msg=CLIENT_KEY_AUTH_MSG): cv.isfile, vol.Inclusive(CONF_CLIENT_CERT,
class ButtonSchema(KNXPlatformSchema): """Voluptuous schema for KNX buttons.""" PLATFORM = Platform.BUTTON CONF_VALUE = "value" DEFAULT_NAME = "KNX Button" payload_or_value_msg = f"Please use only one of `{CONF_PAYLOAD}` or `{CONF_VALUE}`" length_or_type_msg = ( f"Please use only one of `{CONF_PAYLOAD_LENGTH}` or `{CONF_TYPE}`") ENTITY_SCHEMA = vol.All( vol.Schema({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Required(KNX_ADDRESS): ga_validator, vol.Exclusive(CONF_PAYLOAD, "payload_or_value", msg=payload_or_value_msg): object, vol.Exclusive(CONF_VALUE, "payload_or_value", msg=payload_or_value_msg): object, vol.Exclusive(CONF_PAYLOAD_LENGTH, "length_or_type", msg=length_or_type_msg): object, vol.Exclusive(CONF_TYPE, "length_or_type", msg=length_or_type_msg): object, vol.Optional(CONF_ENTITY_CATEGORY): ENTITY_CATEGORIES_SCHEMA, }), vol.Any( vol.Schema( # encoded value { vol.Required(CONF_VALUE): vol.Any(int, float, str), vol.Required(CONF_TYPE): sensor_type_validator, }, extra=vol.ALLOW_EXTRA, ), vol.Schema( # raw payload - default is DPT 1 style True { vol.Optional(CONF_PAYLOAD, default=1): cv.positive_int, vol.Optional(CONF_PAYLOAD_LENGTH, default=0): vol.All(vol.Coerce(int), vol.Range(min=0, max=14)), vol.Optional(CONF_VALUE): None, vol.Optional(CONF_TYPE): None, }, extra=vol.ALLOW_EXTRA, ), ), # calculate raw CONF_PAYLOAD and CONF_PAYLOAD_LENGTH # from CONF_VALUE and CONF_TYPE if given and check payload size button_payload_sub_validator, )
CONF_RESET_AFTER, CONF_STATE_ADDRESS, CONF_SYNC_STATE, CONTROLLER_MODES, KNX_ADDRESS, PRESET_MODES, ColorTempModes, ) ################## # KNX VALIDATORS ################## ga_validator = vol.Any( cv.matches_regex(GroupAddress.ADDRESS_RE.pattern), vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), msg= "value does not match pattern for KNX group address '<main>/<middle>/<sub>', '<main>/<sub>' or '<free>' (eg.'1/2/3', '9/234', '123')", ) ga_list_validator = vol.All(cv.ensure_list, [ga_validator]) ia_validator = vol.Any( cv.matches_regex(IndividualAddress.ADDRESS_RE.pattern), vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), msg= "value does not match pattern for KNX individual address '<area>.<line>.<device>' (eg.'1.1.100')", ) sync_state_validator = vol.Any( vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), cv.boolean,
class ClimateSchema(KNXPlatformSchema): """Voluptuous schema for KNX climate devices.""" PLATFORM = Platform.CLIMATE CONF_ACTIVE_STATE_ADDRESS = "active_state_address" CONF_SETPOINT_SHIFT_ADDRESS = "setpoint_shift_address" CONF_SETPOINT_SHIFT_STATE_ADDRESS = "setpoint_shift_state_address" CONF_SETPOINT_SHIFT_MODE = "setpoint_shift_mode" CONF_SETPOINT_SHIFT_MAX = "setpoint_shift_max" CONF_SETPOINT_SHIFT_MIN = "setpoint_shift_min" CONF_TEMPERATURE_ADDRESS = "temperature_address" CONF_TEMPERATURE_STEP = "temperature_step" CONF_TARGET_TEMPERATURE_ADDRESS = "target_temperature_address" CONF_TARGET_TEMPERATURE_STATE_ADDRESS = "target_temperature_state_address" CONF_OPERATION_MODE_ADDRESS = "operation_mode_address" CONF_OPERATION_MODE_STATE_ADDRESS = "operation_mode_state_address" CONF_CONTROLLER_STATUS_ADDRESS = "controller_status_address" CONF_CONTROLLER_STATUS_STATE_ADDRESS = "controller_status_state_address" CONF_CONTROLLER_MODE_ADDRESS = "controller_mode_address" CONF_CONTROLLER_MODE_STATE_ADDRESS = "controller_mode_state_address" CONF_COMMAND_VALUE_STATE_ADDRESS = "command_value_state_address" CONF_HEAT_COOL_ADDRESS = "heat_cool_address" CONF_HEAT_COOL_STATE_ADDRESS = "heat_cool_state_address" CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS = ( "operation_mode_frost_protection_address") CONF_OPERATION_MODE_NIGHT_ADDRESS = "operation_mode_night_address" CONF_OPERATION_MODE_COMFORT_ADDRESS = "operation_mode_comfort_address" CONF_OPERATION_MODE_STANDBY_ADDRESS = "operation_mode_standby_address" CONF_OPERATION_MODES = "operation_modes" CONF_CONTROLLER_MODES = "controller_modes" CONF_DEFAULT_CONTROLLER_MODE = "default_controller_mode" CONF_ON_OFF_ADDRESS = "on_off_address" CONF_ON_OFF_STATE_ADDRESS = "on_off_state_address" CONF_ON_OFF_INVERT = "on_off_invert" CONF_MIN_TEMP = "min_temp" CONF_MAX_TEMP = "max_temp" DEFAULT_NAME = "KNX Climate" DEFAULT_SETPOINT_SHIFT_MODE = "DPT6010" DEFAULT_SETPOINT_SHIFT_MAX = 6 DEFAULT_SETPOINT_SHIFT_MIN = -6 DEFAULT_TEMPERATURE_STEP = 0.1 DEFAULT_ON_OFF_INVERT = False ENTITY_SCHEMA = vol.All( # deprecated since September 2020 cv.deprecated("setpoint_shift_step", replacement_key=CONF_TEMPERATURE_STEP), # deprecated since 2021.6 cv.deprecated("create_temperature_sensors"), vol.Schema({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_SETPOINT_SHIFT_MAX, default=DEFAULT_SETPOINT_SHIFT_MAX): vol.All(int, vol.Range(min=0, max=32)), vol.Optional(CONF_SETPOINT_SHIFT_MIN, default=DEFAULT_SETPOINT_SHIFT_MIN): vol.All(int, vol.Range(min=-32, max=0)), vol.Optional(CONF_TEMPERATURE_STEP, default=DEFAULT_TEMPERATURE_STEP): vol.All(float, vol.Range(min=0, max=2)), vol.Required(CONF_TEMPERATURE_ADDRESS): ga_list_validator, vol.Required(CONF_TARGET_TEMPERATURE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_TARGET_TEMPERATURE_ADDRESS): ga_list_validator, vol.Inclusive( CONF_SETPOINT_SHIFT_ADDRESS, "setpoint_shift", msg="'setpoint_shift_address' and 'setpoint_shift_state_address' " "are required for setpoint_shift configuration", ): ga_list_validator, vol.Inclusive( CONF_SETPOINT_SHIFT_STATE_ADDRESS, "setpoint_shift", msg="'setpoint_shift_address' and 'setpoint_shift_state_address' " "are required for setpoint_shift configuration", ): ga_list_validator, vol.Optional(CONF_SETPOINT_SHIFT_MODE): vol.Maybe(vol.All(vol.Upper, cv.enum(SetpointShiftMode))), vol.Optional(CONF_ACTIVE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_COMMAND_VALUE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_STATUS_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_STATUS_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_MODE_ADDRESS): ga_list_validator, vol.Optional(CONF_CONTROLLER_MODE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_HEAT_COOL_ADDRESS): ga_list_validator, vol.Optional(CONF_HEAT_COOL_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_NIGHT_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_COMFORT_ADDRESS): ga_list_validator, vol.Optional(CONF_OPERATION_MODE_STANDBY_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT): cv.boolean, vol.Optional(CONF_OPERATION_MODES): vol.All(cv.ensure_list, [vol.In(PRESET_MODES)]), vol.Optional(CONF_CONTROLLER_MODES): vol.All(cv.ensure_list, [vol.In(CONTROLLER_MODES)]), vol.Optional(CONF_DEFAULT_CONTROLLER_MODE, default=HVAC_MODE_HEAT): vol.In(HVAC_MODES), vol.Optional(CONF_MIN_TEMP): vol.Coerce(float), vol.Optional(CONF_MAX_TEMP): vol.Coerce(float), vol.Optional(CONF_ENTITY_CATEGORY): ENTITY_CATEGORIES_SCHEMA, }), )
class LightSchema: """Voluptuous schema for KNX lights.""" CONF_STATE_ADDRESS = CONF_STATE_ADDRESS CONF_BRIGHTNESS_ADDRESS = "brightness_address" CONF_BRIGHTNESS_STATE_ADDRESS = "brightness_state_address" CONF_COLOR_ADDRESS = "color_address" CONF_COLOR_STATE_ADDRESS = "color_state_address" CONF_COLOR_TEMP_ADDRESS = "color_temperature_address" CONF_COLOR_TEMP_STATE_ADDRESS = "color_temperature_state_address" CONF_COLOR_TEMP_MODE = "color_temperature_mode" CONF_RGBW_ADDRESS = "rgbw_address" CONF_RGBW_STATE_ADDRESS = "rgbw_state_address" CONF_MIN_KELVIN = "min_kelvin" CONF_MAX_KELVIN = "max_kelvin" DEFAULT_NAME = "KNX Light" DEFAULT_COLOR_TEMP_MODE = "absolute" DEFAULT_MIN_KELVIN = 2700 # 370 mireds DEFAULT_MAX_KELVIN = 6000 # 166 mireds CONF_INDIVIDUAL_COLORS = "individual_colors" CONF_RED = "red" CONF_GREEN = "green" CONF_BLUE = "blue" CONF_WHITE = "white" COLOR_SCHEMA = vol.Schema({ vol.Optional(KNX_ADDRESS): ga_list_validator, vol.Optional(CONF_STATE_ADDRESS): ga_list_validator, vol.Required(CONF_BRIGHTNESS_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_list_validator, }) SCHEMA = vol.All( vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(KNX_ADDRESS): ga_list_validator, vol.Optional(CONF_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_list_validator, vol.Exclusive(CONF_INDIVIDUAL_COLORS, "color"): { vol.Inclusive(CONF_RED, "colors"): COLOR_SCHEMA, vol.Inclusive(CONF_GREEN, "colors"): COLOR_SCHEMA, vol.Inclusive(CONF_BLUE, "colors"): COLOR_SCHEMA, vol.Optional(CONF_WHITE): COLOR_SCHEMA, }, vol.Exclusive(CONF_COLOR_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_COLOR_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_COLOR_TEMP_ADDRESS): ga_list_validator, vol.Optional(CONF_COLOR_TEMP_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_COLOR_TEMP_MODE, default=DEFAULT_COLOR_TEMP_MODE): vol.All(vol.Upper, cv.enum(ColorTempModes)), vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_RGBW_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All(vol.Coerce(int), vol.Range(min=1)), vol.Optional(CONF_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All(vol.Coerce(int), vol.Range(min=1)), }), vol.Any( # either global "address" or all addresses for individual colors are required vol.Schema( { vol.Required(CONF_INDIVIDUAL_COLORS): { vol.Required(CONF_RED): { vol.Required(KNX_ADDRESS): object }, vol.Required(CONF_GREEN): { vol.Required(KNX_ADDRESS): object }, vol.Required(CONF_BLUE): { vol.Required(KNX_ADDRESS): object }, }, }, extra=vol.ALLOW_EXTRA, ), vol.Schema( { vol.Required(KNX_ADDRESS): object, }, extra=vol.ALLOW_EXTRA, ), ), )
class LightSchema(KNXPlatformSchema): """Voluptuous schema for KNX lights.""" PLATFORM = Platform.LIGHT CONF_STATE_ADDRESS = CONF_STATE_ADDRESS CONF_BRIGHTNESS_ADDRESS = "brightness_address" CONF_BRIGHTNESS_STATE_ADDRESS = "brightness_state_address" CONF_COLOR_ADDRESS = "color_address" CONF_COLOR_STATE_ADDRESS = "color_state_address" CONF_COLOR_TEMP_ADDRESS = "color_temperature_address" CONF_COLOR_TEMP_STATE_ADDRESS = "color_temperature_state_address" CONF_COLOR_TEMP_MODE = "color_temperature_mode" CONF_HUE_ADDRESS = "hue_address" CONF_HUE_STATE_ADDRESS = "hue_state_address" CONF_RGBW_ADDRESS = "rgbw_address" CONF_RGBW_STATE_ADDRESS = "rgbw_state_address" CONF_SATURATION_ADDRESS = "saturation_address" CONF_SATURATION_STATE_ADDRESS = "saturation_state_address" CONF_XYY_ADDRESS = "xyy_address" CONF_XYY_STATE_ADDRESS = "xyy_state_address" CONF_MIN_KELVIN = "min_kelvin" CONF_MAX_KELVIN = "max_kelvin" DEFAULT_NAME = "KNX Light" DEFAULT_COLOR_TEMP_MODE = "absolute" DEFAULT_MIN_KELVIN = 2700 # 370 mireds DEFAULT_MAX_KELVIN = 6000 # 166 mireds CONF_INDIVIDUAL_COLORS = "individual_colors" CONF_RED = "red" CONF_GREEN = "green" CONF_BLUE = "blue" CONF_WHITE = "white" _hs_color_inclusion_msg = ( "'hue_address', 'saturation_address' and 'brightness_address'" " are required for hs_color configuration") HS_COLOR_SCHEMA = { vol.Optional(CONF_HUE_ADDRESS): ga_list_validator, vol.Optional(CONF_HUE_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_SATURATION_ADDRESS): ga_list_validator, vol.Optional(CONF_SATURATION_STATE_ADDRESS): ga_list_validator, } INDIVIDUAL_COLOR_SCHEMA = vol.Schema({ vol.Optional(KNX_ADDRESS): ga_list_validator, vol.Optional(CONF_STATE_ADDRESS): ga_list_validator, vol.Required(CONF_BRIGHTNESS_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_list_validator, }) ENTITY_SCHEMA = vol.All( vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(KNX_ADDRESS): ga_list_validator, vol.Optional(CONF_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_ADDRESS): ga_list_validator, vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_list_validator, vol.Exclusive(CONF_INDIVIDUAL_COLORS, "color"): { vol.Inclusive( CONF_RED, "individual_colors", msg="'red', 'green' and 'blue' are required for individual colors configuration", ): INDIVIDUAL_COLOR_SCHEMA, vol.Inclusive( CONF_GREEN, "individual_colors", msg="'red', 'green' and 'blue' are required for individual colors configuration", ): INDIVIDUAL_COLOR_SCHEMA, vol.Inclusive( CONF_BLUE, "individual_colors", msg="'red', 'green' and 'blue' are required for individual colors configuration", ): INDIVIDUAL_COLOR_SCHEMA, vol.Optional(CONF_WHITE): INDIVIDUAL_COLOR_SCHEMA, }, vol.Exclusive(CONF_COLOR_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_COLOR_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_COLOR_TEMP_ADDRESS): ga_list_validator, vol.Optional(CONF_COLOR_TEMP_STATE_ADDRESS): ga_list_validator, vol.Optional( CONF_COLOR_TEMP_MODE, default=DEFAULT_COLOR_TEMP_MODE ): vol.All(vol.Upper, cv.enum(ColorTempModes)), **HS_COLOR_SCHEMA, vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_RGBW_STATE_ADDRESS): ga_list_validator, vol.Exclusive(CONF_XYY_ADDRESS, "color"): ga_list_validator, vol.Optional(CONF_XYY_STATE_ADDRESS): ga_list_validator, vol.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All( vol.Coerce(int), vol.Range(min=1) ), vol.Optional(CONF_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All( vol.Coerce(int), vol.Range(min=1) ), vol.Optional(CONF_ENTITY_CATEGORY): ENTITY_CATEGORIES_SCHEMA, } ), vol.Any( vol.Schema( {vol.Required(KNX_ADDRESS): object}, extra=vol.ALLOW_EXTRA, ), vol.Schema( # brightness addresses are required in INDIVIDUAL_COLOR_SCHEMA {vol.Required(CONF_INDIVIDUAL_COLORS): object}, extra=vol.ALLOW_EXTRA, ), msg="either 'address' or 'individual_colors' is required", ), vol.Any( vol.Schema( # 'brightness' is non-optional for hs-color { vol.Inclusive( CONF_BRIGHTNESS_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg ): object, vol.Inclusive( CONF_HUE_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg ): object, vol.Inclusive( CONF_SATURATION_ADDRESS, "hs_color", msg=_hs_color_inclusion_msg ): object, }, extra=vol.ALLOW_EXTRA, ), vol.Schema( # hs-colors not used { vol.Optional(CONF_HUE_ADDRESS): None, vol.Optional(CONF_SATURATION_ADDRESS): None, }, extra=vol.ALLOW_EXTRA, ), msg=_hs_color_inclusion_msg, ), )
class AdalightDevice(Device): """Adalight device support""" CONFIG_SCHEMA = vol.Schema({ vol.Required( "com_port", description="COM port for Adalight compatible device", ): vol.In(list(AvailableCOMPorts.available_ports)), vol.Required("baudrate", description="baudrate", default=500000): vol.All(vol.Coerce(int), vol.Range(min=115200)), vol.Required( "pixel_count", description="Number of individual pixels", ): vol.All(vol.Coerce(int), vol.Range(min=1)), vol.Required("color_order", description="Color order", default="RGB"): vol.In(list(COLOR_ORDERS.keys())), }) def __init__(self, ledfx, config): super().__init__(ledfx, config) self.serial = None self.baudrate = self._config["baudrate"] self.com_port = self._config["com_port"] self.color_order = COLOR_ORDERS[self._config["color_order"]] # adalight header # Byte Value # 0 'A' (0x41) # 1 'd' (0x64) # 2 'a' (0x61) # 3 pixel count, high byte # 4 pixel count, low byte # 5 Checksum (high byte XOR low byte XOR 0x55) buffer_size = 6 + self.pixel_count * 3 self.buffer = bytearray(buffer_size) self.buffer[0] = ord("A") self.buffer[1] = ord("d") self.buffer[2] = ord("a") pixel_count_in_bytes = (self.pixel_count).to_bytes(2, byteorder="big") self.buffer[3] = pixel_count_in_bytes[0] self.buffer[4] = pixel_count_in_bytes[1] self.buffer[5] = self.buffer[3] ^ self.buffer[4] ^ 0x55 def activate(self): try: self.serial = serial.Serial(self.com_port, self.baudrate) if self.serial.isOpen: super().activate() except serial.SerialException: _LOGGER.critical( "Serial Error: Please ensure your device is connected, functioning and the correct COM port is selected." ) # Todo: Trigger the UI to refresh after the clear effect call. Currently it still shows as active. self.clear_effect() def deactivate(self): super().deactivate() self.serial.close() @property def pixel_count(self): return int(self._config["pixel_count"]) def flush(self, data): byteData = data.astype(np.dtype("B")) i = 3 for rgb in byteData: i += 3 rgb_bytes = rgb.tobytes() self.buffer[i], self.buffer[i + 1], self.buffer[i + 2] = ( rgb_bytes[0], rgb_bytes[1], rgb_bytes[2], ) if self.color_order == ColorOrder.RGB: continue elif self.color_order == ColorOrder.GRB: self.swap(self.buffer, i, i + 1) elif self.color_order == ColorOrder.BGR: self.swap(self.buffer, i, i + 2) elif self.color_order == ColorOrder.RBG: self.swap(self.buffer, i + 1, i + 2) elif self.color_order == ColorOrder.BRG: self.swap(self.buffer, i, i + 1) self.swap(self.buffer, i + 1, i + 2) elif self.color_order == ColorOrder.GBR: self.swap(self.buffer, i, i + 1) self.swap(self.buffer, i, i + 2) try: self.serial.write(self.buffer) except serial.SerialException: _LOGGER.critical( "Serial Connection Interrupted. Please check connections and ensure your device is functioning correctly." ) self.deactivate() def swap(self, array, pos1, pos2): array[pos1], array[pos2] = array[pos2], array[pos1]
vol.Optional(CONF_I2C_ADDRESS, default=DEFAULT_I2C_ADDRESS): cv.positive_int, vol.Optional(CONF_MONITORED_CONDITIONS, default=DEFAULT_MONITORED): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.Optional(CONF_I2C_BUS, default=DEFAULT_I2C_BUS): cv.positive_int, vol.Optional(CONF_OVERSAMPLING_TEMP, default=DEFAULT_OVERSAMPLING_TEMP): vol.All(vol.Coerce(int), vol.In(OVERSAMPLING_VALUES)), vol.Optional(CONF_OVERSAMPLING_PRES, default=DEFAULT_OVERSAMPLING_PRES): vol.All(vol.Coerce(int), vol.In(OVERSAMPLING_VALUES)), vol.Optional(CONF_OVERSAMPLING_HUM, default=DEFAULT_OVERSAMPLING_HUM): vol.All(vol.Coerce(int), vol.In(OVERSAMPLING_VALUES)), vol.Optional(CONF_FILTER_SIZE, default=DEFAULT_FILTER_SIZE): vol.All(vol.Coerce(int), vol.In(FILTER_VALUES)), vol.Optional(CONF_GAS_HEATER_TEMP, default=DEFAULT_GAS_HEATER_TEMP): vol.All(vol.Coerce(int), vol.Range(200, 400)), vol.Optional(CONF_GAS_HEATER_DURATION, default=DEFAULT_GAS_HEATER_DURATION): vol.All(vol.Coerce(int), vol.Range(1, 4032)), vol.Optional(CONF_AQ_BURN_IN_TIME, default=DEFAULT_AQ_BURN_IN_TIME): cv.positive_int, vol.Optional(CONF_AQ_HUM_BASELINE, default=DEFAULT_AQ_HUM_BASELINE): vol.All(vol.Coerce(int), vol.Range(1, 100)), vol.Optional(CONF_AQ_HUM_WEIGHTING, default=DEFAULT_AQ_HUM_WEIGHTING): vol.All(vol.Coerce(int), vol.Range(1, 100)), vol.Optional(CONF_TEMP_OFFSET, default=DEFAULT_TEMP_OFFSET): vol.All(vol.Coerce(float), vol.Range(-100.0, 100.0)), }) async def async_setup_platform(hass, config,
_LOGGER.setLevel(logging.DEBUG) # TODO: remove for production SCAN_INTERVAL_DEFAULT = timedelta(seconds=300) SCAN_INTERVAL_MINIMUM = timedelta(seconds=10) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { vol.Required("serial_port"): cv.string, vol.Required("packet_log"): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=SCAN_INTERVAL_DEFAULT): vol.All(cv.time_period, vol.Range(min=SCAN_INTERVAL_MINIMUM)), vol.Optional("schema"): dict, # vol.Optional("allow_list"): list, vol.Optional("ignore_list"): list, vol.Optional("max_zones", default=12): vol.Any(None, int), }, # extra=vol.ALLOW_EXTRA, # TODO: remove for production ) }, extra=vol.ALLOW_EXTRA, )
DEFAULT_RADIUS_IN_KM = 50.0 DEFAULT_UNIT_OF_MEASUREMENT = 'km' SCAN_INTERVAL = timedelta(minutes=5) SIGNAL_DELETE_ENTITY = 'ign_sismologia_delete_{}' SIGNAL_UPDATE_ENTITY = 'ign_sismologia_update_{}' SOURCE = 'ign_sismologia' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_LATITUDE): cv.latitude, vol.Optional(CONF_LONGITUDE): cv.longitude, vol.Optional(CONF_RADIUS, default=DEFAULT_RADIUS_IN_KM): vol.Coerce(float), vol.Optional(CONF_MINIMUM_MAGNITUDE, default=DEFAULT_MINIMUM_MAGNITUDE): vol.All(vol.Coerce(float), vol.Range(min=0)) }) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the IGN Sismologia Feed platform.""" scan_interval = config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL) coordinates = (config.get(CONF_LATITUDE, hass.config.latitude), config.get(CONF_LONGITUDE, hass.config.longitude)) radius_in_km = config[CONF_RADIUS] minimum_magnitude = config[CONF_MINIMUM_MAGNITUDE] # Initialize the entity manager. feed = IgnSismologiaFeedEntityManager( hass, add_entities, scan_interval, coordinates, radius_in_km, minimum_magnitude)
async def async_setup(hass, config): """Track states and offer events for covers.""" component = hass.data[DOMAIN] = EntityComponent( _LOGGER, DOMAIN, hass, SCAN_INTERVAL ) await component.async_setup(config) component.async_register_entity_service( SERVICE_OPEN_COVER, {}, "async_open_cover", [SUPPORT_OPEN] ) component.async_register_entity_service( SERVICE_CLOSE_COVER, {}, "async_close_cover", [SUPPORT_CLOSE] ) component.async_register_entity_service( SERVICE_SET_COVER_POSITION, { vol.Required(ATTR_POSITION): vol.All( vol.Coerce(int), vol.Range(min=0, max=100) ) }, "async_set_cover_position", [SUPPORT_SET_POSITION], ) component.async_register_entity_service( SERVICE_STOP_COVER, {}, "async_stop_cover", [SUPPORT_STOP] ) component.async_register_entity_service( SERVICE_TOGGLE, {}, "async_toggle", [SUPPORT_OPEN | SUPPORT_CLOSE] ) component.async_register_entity_service( SERVICE_OPEN_COVER_TILT, {}, "async_open_cover_tilt", [SUPPORT_OPEN_TILT] ) component.async_register_entity_service( SERVICE_CLOSE_COVER_TILT, {}, "async_close_cover_tilt", [SUPPORT_CLOSE_TILT] ) component.async_register_entity_service( SERVICE_STOP_COVER_TILT, {}, "async_stop_cover_tilt", [SUPPORT_STOP_TILT] ) component.async_register_entity_service( SERVICE_SET_COVER_TILT_POSITION, { vol.Required(ATTR_TILT_POSITION): vol.All( vol.Coerce(int), vol.Range(min=0, max=100) ) }, "async_set_cover_tilt_position", [SUPPORT_SET_TILT_POSITION], ) component.async_register_entity_service( SERVICE_TOGGLE_COVER_TILT, {}, "async_toggle_tilt", [SUPPORT_OPEN_TILT | SUPPORT_CLOSE_TILT], ) return True
from .const import DATA_INSTANCE from .models import Base, Events, RecorderRuns, States from .util import session_scope _LOGGER = logging.getLogger(__name__) DOMAIN = "recorder" SERVICE_PURGE = "purge" ATTR_KEEP_DAYS = "keep_days" ATTR_REPACK = "repack" SERVICE_PURGE_SCHEMA = vol.Schema( { vol.Optional(ATTR_KEEP_DAYS): vol.All(vol.Coerce(int), vol.Range(min=0)), vol.Optional(ATTR_REPACK, default=False): cv.boolean, } ) DEFAULT_URL = "sqlite:///{hass_config_path}" DEFAULT_DB_FILE = "home-assistant_v2.db" CONF_DB_URL = "db_url" CONF_PURGE_KEEP_DAYS = "purge_keep_days" CONF_PURGE_INTERVAL = "purge_interval" CONF_EVENT_TYPES = "event_types" CONNECT_RETRY_WAIT = 3 FILTER_SCHEMA = vol.Schema(
SENSOR_TYPES = { SENSOR_TEMPERATURE: ['Temperature', None], SENSOR_HUMIDITY: ['Humidity', '%'] } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_SENSOR): cv.string, vol.Required(CONF_PIN): cv.string, vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_TEMPERATURE_OFFSET, default=0): vol.All(vol.Coerce(float), vol.Range(min=-100, max=100)), vol.Optional(CONF_HUMIDITY_OFFSET, default=0): vol.All(vol.Coerce(float), vol.Range(min=-100, max=100)) }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the DHT sensor.""" # pylint: disable=import-error import Adafruit_DHT SENSOR_TYPES[SENSOR_TEMPERATURE][1] = hass.config.units.temperature_unit available_sensors = { "DHT11": Adafruit_DHT.DHT11, "DHT22": Adafruit_DHT.DHT22, "AM2302": Adafruit_DHT.AM2302
class Effect(BaseRegistry): """ Manages an effect """ NAME = "" _pixels = None _dirty = False _config = None _active = False # Basic effect properties that can be applied to all effects CONFIG_SCHEMA = vol.Schema({ vol.Optional('blur', description='Amount to blur the effect', default=0.0): vol.All(vol.Coerce(float), vol.Range(min=0.0, max=10)), vol.Optional('flip', description='Flip the effect', default=False): bool, vol.Optional('mirror', description='Mirror the effect', default=False): bool, vol.Optional('brightness', description='Brightness of strip', default=1.0): vol.All(vol.Coerce(float), vol.Range(min=0.0, max=1.0)), }) def __init__(self, ledfx, config): self._ledfx = ledfx self._dirty_callback = None self.update_config(config) def __del__(self): if self._active: self.deactivate() def activate(self, pixel_count): """Attaches an output channel to the effect""" self._pixels = np.zeros((pixel_count, 3)) self._active = True _LOGGER.info("Effect {} activated.".format(self.NAME)) def deactivate(self): """Detaches an output channel from the effect""" self._pixels = None self._active = False _LOGGER.info("Effect {} deactivated.".format(self.NAME)) def update_config(self, config): # TODO: Sync locks to ensure everything is thread safe validated_config = type(self).schema()(config) self._config = validated_config def inherited(cls, method): if hasattr(cls, method) and hasattr(super(cls, cls), method): return cls.foo == super(cls).foo return False # Iterate all the base classes and check to see if there is a custom # implementation of config updates. If to notify the base class. valid_classes = list(type(self).__bases__) valid_classes.append(type(self)) for base in valid_classes: if base.config_updated != super(base, base).config_updated: base.config_updated(self, self._config) _LOGGER.info("Effect {} config updated to {}.".format( self.NAME, validated_config)) def config_updated(self, config): """ Optional event for when an effect's config is updated. This should be used by the subclass only if they need to build up complex properties off the configuration, otherwise the config should just be referenced in the effect's loop directly """ pass @property def is_active(self): """Return if the effect is currently active""" return self._active @property def pixels(self): """Returns the pixels for the channel""" if not self._active: raise Exception( 'Attempting to access pixels before effect is active') return np.copy(self._pixels) @pixels.setter def pixels(self, pixels): """Sets the pixels for the channel""" if not self._active: _LOGGER.warning( 'Attempting to set pixels before effect is active. Dropping.') return if isinstance(pixels, tuple): self._pixels = np.copy(pixels) elif isinstance(pixels, np.ndarray): # Apply some of the base output filters if necessary if self._config['blur'] != 0.0: pixels = blur_pixels(pixels=pixels, sigma=self._config['blur']) if self._config['flip']: pixels = flip_pixels(pixels) if self._config['mirror']: pixels = mirror_pixels(pixels) if self._config['brightness']: pixels = brightness_pixels(pixels, self._config['brightness']) self._pixels = np.copy(pixels) else: raise TypeError() self._dirty = True if self._dirty_callback: self._dirty_callback() def setDirtyCallback(self, callback): self._dirty_callback = callback @property def pixel_count(self): """Returns the number of pixels for the channel""" return len(self.pixels) @property def name(self): return self.NAME
DEFAULT_BRIGHTNESS_SCALE = 255 DEFAULT_NAME = "MQTT Light" DEFAULT_OPTIMISTIC = False DEFAULT_PAYLOAD_OFF = "OFF" DEFAULT_PAYLOAD_ON = "ON" DEFAULT_WHITE_VALUE_SCALE = 255 DEFAULT_ON_COMMAND_TYPE = "last" VALUES_ON_COMMAND_TYPE = ["first", "last", "brightness"] PLATFORM_SCHEMA_BASIC = (mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_BRIGHTNESS_COMMAND_TOPIC): mqtt.valid_publish_topic, vol.Optional(CONF_BRIGHTNESS_SCALE, default=DEFAULT_BRIGHTNESS_SCALE): vol.All(vol.Coerce(int), vol.Range(min=1)), vol.Optional(CONF_BRIGHTNESS_STATE_TOPIC): mqtt.valid_subscribe_topic, vol.Optional(CONF_BRIGHTNESS_VALUE_TEMPLATE): cv.template, vol.Optional(CONF_COLOR_TEMP_COMMAND_TEMPLATE): cv.template, vol.Optional(CONF_COLOR_TEMP_COMMAND_TOPIC): mqtt.valid_publish_topic, vol.Optional(CONF_COLOR_TEMP_STATE_TOPIC): mqtt.valid_subscribe_topic, vol.Optional(CONF_COLOR_TEMP_VALUE_TEMPLATE): cv.template, vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA, vol.Optional(CONF_EFFECT_COMMAND_TOPIC):
DEFAULT_NAME = "BMP280" SCAN_INTERVAL = timedelta(seconds=15) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=3) MIN_I2C_ADDRESS = 0x76 MAX_I2C_ADDRESS = 0x77 CONF_I2C_ADDRESS = "i2c_address" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Required(CONF_I2C_ADDRESS): vol.All(vol.Coerce(int), vol.Range(min=MIN_I2C_ADDRESS, max=MAX_I2C_ADDRESS)), }) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the sensor platform.""" try: # initializing I2C bus using the auto-detected pins i2c = I2C(board.SCL, board.SDA) # initializing the sensor bmp280 = Adafruit_BMP280_I2C(i2c, address=config[CONF_I2C_ADDRESS]) except ValueError as error: # this usually happens when the board is I2C capable, but the device can't be found at the configured address if str(error.args[0]).startswith("No I2C device at address"): _LOGGER.error( "%s. Hint: Check wiring and make sure that the SDO pin is tied to either ground (0x76) or VCC (0x77)",