def merge_packages_config(config, packages): """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue component = get_component(comp_name) if component is None: _log_pkg_error(pack_name, comp_name, config, "does not exist") continue if hasattr(component, 'PLATFORM_SCHEMA'): config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if hasattr(component, 'CONFIG_SCHEMA'): merge_type, _ = _identify_config_schema(component) if merge_type == 'list': config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if merge_type == 'dict': if not isinstance(comp_conf, dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.") continue for key, val in comp_conf.items(): if key in config[comp_name]: _log_pkg_error(pack_name, comp_name, config, "duplicate key '{}'".format(key)) continue config[comp_name][key] = val continue # The last merge type are sections that may occur only once if comp_name in config: _log_pkg_error( pack_name, comp_name, config, "may occur only once" " and it already exist in your main configuration") continue config[comp_name] = comp_conf return config
def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup the pilight platform.""" # Find and return switches controlled by pilight switches = config.get("switches", {}) devices = [] for dev_name, properties in switches.items(): devices.append( PilightSwitch( hass, properties.get("name", dev_name), properties.get("on_code"), properties.get("off_code"), ensure_list(properties.get("on_code_receive", False)), ensure_list(properties.get("off_code_receive", False)), ) ) add_devices_callback(devices)
def _recursive_merge( conf: Dict[str, Any], package: Dict[str, Any]) -> Union[bool, str]: """Merge package into conf, recursively.""" error = False # type: Union[bool, str] for key, pack_conf in package.items(): if isinstance(pack_conf, dict): if not pack_conf: continue conf[key] = conf.get(key, OrderedDict()) error = _recursive_merge(conf=conf[key], package=pack_conf) elif isinstance(pack_conf, list): if not pack_conf: continue conf[key] = cv.ensure_list(conf.get(key)) conf[key].extend(cv.ensure_list(pack_conf)) else: if conf.get(key) is not None: return key conf[key] = pack_conf return error
def send_code(call): """Send RF code to the pilight-daemon.""" message_data = call.data # Patch data because of bug: # https://github.com/pilight/pilight/issues/296 # Protocol has to be in a list otherwise segfault in pilight-daemon message_data['protocol'] = ensure_list(message_data['protocol']) try: pilight_client.send_code(message_data) except IOError: _LOGGER.error('Pilight send failed for %s', str(message_data))
DOMAIN = 'hue' _LOGGER = logging.getLogger(__name__) SCAN_INTERVAL = timedelta(seconds=5) # Device icon / attrs MODELS = ['SML', 'RWL', 'ZGP', 'GEO'] MODELS_ATTRS = { 'SML': {'icon': 'mdi:run-fast', 'attrs': ['light_level', 'battery', 'last_updated', 'lux', 'dark', 'daylight', 'temperature']}, 'RWL': {'icon': 'mdi:remote', 'attrs': ['battery', 'last_updated']}, 'ZGP': {'icon': 'mdi:remote', 'attrs': ['battery', 'last_updated']}, 'GEO': {'icon': 'mdi:cellphone', 'attrs': []}} PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_DEVICES): cv.ensure_list(MODELS), }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Hue sensors.""" import hue_sensors as hs url = hass.data[DOMAIN] + '/sensors' data = HueSensorData(url, hs.parse_hue_api_response) data.update() sensors = [] models = config.get(CONF_DEVICES) for key in data.data.keys(): if not models or data.data[key]['model'] in models: sensors.append(HueSensor(key, data)) add_devices(sensors, True)
OFF_STATES = [STATE_IDLE, STATE_OFF, STATE_UNAVAILABLE] ATTRS_SCHEMA = cv.schema_with_slug_keys(cv.string) CMD_SCHEMA = cv.schema_with_slug_keys(cv.SERVICE_SCHEMA) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_CHILDREN, default=[]): cv.entity_ids, vol.Optional(CONF_COMMANDS, default={}): CMD_SCHEMA, vol.Optional(CONF_ATTRS, default={}): vol.Or(cv.ensure_list(ATTRS_SCHEMA), ATTRS_SCHEMA), vol.Optional(CONF_STATE_TEMPLATE): cv.template, }, extra=vol.REMOVE_EXTRA, ) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the universal media players.""" player = UniversalMediaPlayer( hass, config.get(CONF_NAME),
CONF_STREET = "street" CONF_REFRESH_RATE = 'refreshRate' CONF_MAX_COUNT = 'maxCount' MANIFEST = json.load( open("%s/manifest.json" % os.path.dirname(os.path.realpath(__file__)))) DOMAIN = MANIFEST["domain"] VERSION = MANIFEST["version"] DEFAULT_NAME = MANIFEST["name"] PLATFORM = "binary_sensor" DEFAULT_METHOD = 'GET' DEFAULT_VERIFY_SSL = True ISSUE_URL = "https://github.com/konikvranik/hacs_cez/issues" SCHEMA = { vol.Required(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Required(CONF_STREET): cv.ensure_list(vol.Any(list, cv.string)), vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, vol.Optional(CONF_FORCE_UPDATE, default=True): cv.boolean, vol.Optional(CONF_REFRESH_RATE, default=86400): vol.All(vol.Coerce(int)), vol.Optional(CONF_MAX_COUNT, default=5): vol.All(vol.Coerce(int)), } SERVICE = 'refresh' CONFIG_SCHEMA = vol.Schema({vol.Optional(DOMAIN): vol.Schema(SCHEMA)}, extra=ALLOW_EXTRA) _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, entry): """Set up ESPHome binary sensors based on a config entry."""
async def merge_packages_config( hass: HomeAssistant, config: Dict, packages: Dict[str, Any], _log_pkg_error: Callable = _log_pkg_error, ) -> Dict: """Merge packages into the top-level configuration. Mutate config.""" PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue # If component name is given with a trailing description, remove it # when looking for component domain = comp_name.split(" ")[0] try: integration = await async_get_integration_with_requirements( hass, domain ) component = integration.get_component() except (IntegrationNotFound, RequirementsNotFound, ImportError) as ex: _log_pkg_error(pack_name, comp_name, config, str(ex)) continue merge_list = hasattr(component, "PLATFORM_SCHEMA") if not merge_list and hasattr(component, "CONFIG_SCHEMA"): merge_type, _ = _identify_config_schema(component) merge_list = merge_type == "list" if merge_list: config[comp_name] = cv.remove_falsy( cv.ensure_list(config.get(comp_name)) + cv.ensure_list(comp_conf) ) continue if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Expected a dict." ) continue if comp_name not in config or config[comp_name] is None: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.", ) continue error = _recursive_merge(conf=config[comp_name], package=comp_conf) if error: _log_pkg_error( pack_name, comp_name, config, f"has duplicate key '{error}'" ) return config
DIAL_CONFIG_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(ATTR_MIN_VALUE): vol.Coerce(int), vol.Optional(ATTR_MAX_VALUE): vol.Coerce(int), vol.Optional(ATTR_MIN_POSITION): cv.positive_int, vol.Optional(ATTR_MAX_POSITION): cv.positive_int, vol.Optional(ATTR_ROTATION): vol.In(ROTATIONS), vol.Optional(ATTR_SCALE): vol.In(SCALES), vol.Optional(ATTR_TICKS): cv.positive_int }) DIAL_STATE_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, vol.Required(ATTR_VALUE): vol.Coerce(int), vol.Optional(ATTR_LABELS): cv.ensure_list(cv.string) }) WINK_COMPONENTS = [ 'binary_sensor', 'sensor', 'light', 'switch', 'lock', 'cover', 'climate', 'fan', 'alarm_control_panel', 'scene', 'water_heater' ] WINK_HUBS = [] def _request_app_setup(hass, config): """Assist user with configuring the Wink dev application.""" hass.data[DOMAIN]['configurator'] = True configurator = hass.components.configurator
async def merge_packages_config( hass: HomeAssistant, config: dict, packages: dict[str, Any], _log_pkg_error: Callable = _log_pkg_error, ) -> dict: """Merge packages into the top-level configuration. Mutate config.""" PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue # If component name is given with a trailing description, remove it # when looking for component domain = comp_name.split(" ")[0] try: integration = await async_get_integration_with_requirements( hass, domain) component = integration.get_component() except INTEGRATION_LOAD_EXCEPTIONS as ex: _log_pkg_error(pack_name, comp_name, config, str(ex)) continue try: config_platform: ModuleType | None = integration.get_platform( "config") # Test if config platform has a config validator if not hasattr(config_platform, "async_validate_config"): config_platform = None except ImportError: config_platform = None merge_list = False # If integration has a custom config validator, it needs to provide a hint. if config_platform is not None: merge_list = config_platform.PACKAGE_MERGE_HINT == "list" # type: ignore[attr-defined] if not merge_list: merge_list = hasattr(component, "PLATFORM_SCHEMA") if not merge_list and hasattr(component, "CONFIG_SCHEMA"): merge_list = _identify_config_schema(component) == "list" if merge_list: config[comp_name] = cv.remove_falsy( cv.ensure_list(config.get(comp_name)) + cv.ensure_list(comp_conf)) continue if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config or config[comp_name] is None: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.", ) continue error = _recursive_merge(conf=config[comp_name], package=comp_conf) if error: _log_pkg_error(pack_name, comp_name, config, f"has duplicate key '{error}'") return config
name: Name to identify appliance/device eg. Living Room Lamp (required) key: Auth key, if different from platform key (optional) ''' SWITCH_SCHEMA = vol.Schema({ vol.Required(CONF_UUID): cv.string, vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_KEY): cv.string, }) ''' switches: [] one or more SWITCH_SCHEMA (required) key: Auth key to use for all appliances/devices (optional) validate: validate key for incomming requests (default: True) ''' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_SWITCHES): cv.ensure_list(SWITCH_SCHEMA), vol.Optional(CONF_KEY): cv.string, vol.Optional(CONF_VALIDATE, default=True): cv.boolean, }) def setup_platform(hass, config, add_entities, discovery_info=None): switches = [] for swConfig in config[CONF_SWITCHES]: switches.append( MerossSwitch( hass.components.mqtt, swConfig[CONF_UUID], next(
DIAL_CONFIG_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, vol.Optional(ATTR_MIN_VALUE): vol.Coerce(int), vol.Optional(ATTR_MAX_VALUE): vol.Coerce(int), vol.Optional(ATTR_MIN_POSITION): cv.positive_int, vol.Optional(ATTR_MAX_POSITION): cv.positive_int, vol.Optional(ATTR_ROTATION): vol.In(ROTATIONS), vol.Optional(ATTR_SCALE): vol.In(SCALES), vol.Optional(ATTR_TICKS): cv.positive_int, }) DIAL_STATE_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, vol.Required(ATTR_VALUE): vol.Coerce(int), vol.Optional(ATTR_LABELS): cv.ensure_list(cv.string), }) WINK_COMPONENTS = [ 'binary_sensor', 'sensor', 'light', 'switch', 'lock', 'cover', 'climate', 'fan', 'alarm_control_panel', 'scene', 'water_heater' ] WINK_HUBS = [] def _request_app_setup(hass, config): """Assist user with configuring the Wink dev application.""" hass.data[DOMAIN]['configurator'] = True configurator = hass.components.configurator
from homeassistant import config_entries from homeassistant.const import CONF_NAME, CONF_TIMEOUT from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from .const import ATTR_TARIFF, DEFAULT_NAME, DEFAULT_TIMEOUT, DOMAIN, PLATFORM, TARIFFS UI_CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_NAME, default=DEFAULT_NAME): str, vol.Required(ATTR_TARIFF, default=TARIFFS[1]): vol.In(TARIFFS), }) SENSOR_SCHEMA = UI_CONFIG_SCHEMA.extend( {vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int}) CONFIG_SCHEMA = vol.Schema({DOMAIN: cv.ensure_list(SENSOR_SCHEMA)}, extra=vol.ALLOW_EXTRA) async def async_setup(hass: HomeAssistant, config: dict): """ Set up the electricity price sensor from configuration.yaml. ```yaml pvpc_hourly_pricing: - name: PVPC manual ve tariff: electric_car - name: PVPC manual nocturna tariff: discrimination timeout: 3 ```
SHOW_SCHEMA = vol.Schema({ vol.Optional(CONF_CONFIG, False): cv.boolean, vol.Optional(CONF_TIMELINE, False): cv.boolean, }) SUN_SCHEMA = vol.Schema({ vol.Required(CONF_SUN): cv.sun_event, vol.Optional(CONF_BEFORE): cv.positive_time_period, vol.Optional(CONF_AFTER): cv.positive_time_period, }) time_event = vol.Any(cv.time, SUN_SCHEMA) month_event = vol.All(cv.ensure_list, [vol.In(MONTHS)]) day_number = vol.All(vol.Coerce(int), vol.Range(min=0, max=31)) day_event = vol.Any(CONF_ODD, CONF_EVEN, cv.ensure_list(day_number)) SCHEDULE_SCHEMA = vol.Schema({ vol.Required(CONF_TIME): time_event, vol.Required(CONF_DURATION): cv.positive_time_period, vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_WEEKDAY): cv.weekdays, vol.Optional(CONF_MONTH): month_event, vol.Optional(CONF_DAY): day_event, }) ZONE_SCHEMA = vol.Schema({ vol.Optional(CONF_SCHEDULES): vol.All(cv.ensure_list, [SCHEDULE_SCHEMA]), vol.Optional(CONF_ZONE_ID): cv.string,
CONF_INDEX = "index" CONF_RUN_SECONDS = "run_seconds" CONF_CONTINUE_RUNNING_STATIONS = "continue_running_stations" DOMAIN = "opensprinkler" DEFAULT_NAME = "OpenSprinkler" DEFAULT_SCAN_INTERVAL = 5 SCHEMA_SERVICE_RUN_SECONDS = { vol.Required(CONF_INDEX): cv.positive_int, vol.Required(CONF_RUN_SECONDS): cv.positive_int, } SCHEMA_SERVICE_RUN = { vol.Optional(CONF_RUN_SECONDS): vol.Or( cv.ensure_list(cv.positive_int), cv.ensure_list(SCHEMA_SERVICE_RUN_SECONDS), cv.positive_int, vol.Schema({}, extra=vol.ALLOW_EXTRA), ), vol.Optional(CONF_CONTINUE_RUNNING_STATIONS): cv.boolean, } SCHEMA_SERVICE_STOP = {} SERVICE_RUN = "run" SERVICE_STOP = "stop"
CONF_EVOLUTION_ARROWS_MIN = 'evolution_arrows_minutes' CONF_REMOTE_API = 'remote_api' CONF_WEATHER = 'weather' DEFAULT_NAME = "Psychrometric chart" DEFAULT_SCAN_INTERVAL_SEC = 60 DEFAULT_DEAD_BAND = 0.5 # ĀŗC DEFAULT_DELTA_EVOLUTION = 5400 # 1.5h DEFAULT_FREQ_SAMPLING_SEC = 300 # 300 (5min) BINARY_SENSOR_NAME = 'close_house' SENSOR_NAME = 'house_delta_temperature' POINT_SCHEMA = vol.Schema(cv.entity_ids) POINTS_SCHEMA = vol.Schema(vol.Any(POINT_SCHEMA, cv.ensure_list(POINT_SCHEMA))) ROOM_SCHEMA = vol.Schema({cv.string: POINTS_SCHEMA}) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { vol.Required(CONF_INTERIOR): ROOM_SCHEMA, vol.Optional(CONF_EXTERIOR): POINTS_SCHEMA, vol.Optional(CONF_WEATHER): POINTS_SCHEMA, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
}, "time": datetime.timedelta(seconds=3) }, "light_on": { "name": "{} Light On", "icon": { True: "lightbulb-on", False: "lightbulb" }, "time": datetime.timedelta(minutes=5) } } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_SWITCHES, default=[]): vol.All(cv.ensure_list([vol.In(SWITCHES)])) }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the DoorBird switch platform.""" switches = [] for doorstation in hass.data[DOORBIRD_DOMAIN]: device = doorstation.device for switch in SWITCHES: _LOGGER.debug("Adding DoorBird switch %s", SWITCHES[switch]["name"].format(doorstation.name))
import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from .const import ATTR_TARIFF, DEFAULT_NAME, DEFAULT_TARIFF, DOMAIN, PLATFORM, TARIFFS UI_CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_NAME, default=DEFAULT_NAME): str, vol.Required(ATTR_TARIFF, default=DEFAULT_TARIFF): vol.In(TARIFFS), }) CONFIG_SCHEMA = vol.Schema({DOMAIN: cv.ensure_list(UI_CONFIG_SCHEMA)}, extra=vol.ALLOW_EXTRA) async def async_setup(hass: HomeAssistant, config: dict): """ Set up the electricity price sensor from configuration.yaml. ```yaml pvpc_hourly_pricing: - name: PVPC manual ve tariff: electric_car - name: PVPC manual nocturna tariff: discrimination timeout: 3 ```
from homeassistant import config_entries from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from .const import ATTR_TARIFF, DEFAULT_NAME, DEFAULT_TARIFF, DOMAIN, PLATFORMS, TARIFFS UI_CONFIG_SCHEMA = vol.Schema( { vol.Required(CONF_NAME, default=DEFAULT_NAME): str, vol.Required(ATTR_TARIFF, default=DEFAULT_TARIFF): vol.In(TARIFFS), } ) CONFIG_SCHEMA = vol.Schema( vol.All(cv.deprecated(DOMAIN), {DOMAIN: cv.ensure_list(UI_CONFIG_SCHEMA)}), extra=vol.ALLOW_EXTRA, ) async def async_setup(hass: HomeAssistant, config: dict): """ Set up the electricity price sensor from configuration.yaml. ```yaml pvpc_hourly_pricing: - name: PVPC manual ve tariff: electric_car - name: PVPC manual nocturna tariff: discrimination timeout: 3
def _update_sub_entities(self, properties, services=None, domain=None): from .binary_sensor import MiotBinarySensorSubEntity from .switch import MiotSwitchSubEntity from .light import MiotLightSubEntity if isinstance(services, MiotService): sls = [services] elif services: sls = self._miot_service.spec.get_services( *cv.ensure_list(services)) else: sls = [self._miot_service] add_sensors = self._add_entities.get('sensor') add_binary_sensors = self._add_entities.get('binary_sensor') add_switches = self._add_entities.get('switch') add_lights = self._add_entities.get('light') for s in sls: if not properties: fnm = s.unique_name tms = self._check_same_sub_entity(fnm, domain) new = True if fnm in self._subs: new = False self._subs[fnm].update() elif tms > 0: if tms <= 1: _LOGGER.info( 'Device %s sub entity %s: %s already exists.', self.name, domain, fnm) elif add_lights and domain == 'light' and s.get_property('on'): self._subs[fnm] = MiotLightSubEntity(self, s) add_lights([self._subs[fnm]]) if new and fnm in self._subs: self._check_same_sub_entity(fnm, domain, add=1) _LOGGER.debug('Added sub entity %s: %s for %s.', domain, fnm, self.name) continue pls = s.get_properties(*cv.ensure_list(properties)) for p in pls: if p.full_name not in self._state_attrs: continue fnm = p.unique_name tms = self._check_same_sub_entity(fnm, domain) new = True if fnm in self._subs: new = False self._subs[fnm].update() elif tms > 0: if tms <= 1: _LOGGER.info( 'Device %s sub entity %s: %s already exists.', self.name, domain, fnm) elif add_switches and p.format == 'bool' and p.writeable: self._subs[fnm] = MiotSwitchSubEntity(self, p) add_switches([self._subs[fnm]]) elif add_binary_sensors and p.format == 'bool': self._subs[fnm] = MiotBinarySensorSubEntity(self, p) add_binary_sensors([self._subs[fnm]]) elif add_sensors and domain == 'sensor': self._subs[fnm] = MiotSensorSubEntity(self, p) add_sensors([self._subs[fnm]]) if new and fnm in self._subs: self._check_same_sub_entity(fnm, domain, add=1) _LOGGER.debug('Added sub entity %s: %s for %s.', domain, fnm, self.name)
def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict, _log_pkg_error: Callable = _log_pkg_error) -> Dict: """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue component = get_component(hass, comp_name) if component is None: _log_pkg_error(pack_name, comp_name, config, "does not exist") continue if hasattr(component, 'PLATFORM_SCHEMA'): if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if hasattr(component, 'CONFIG_SCHEMA'): merge_type, _ = _identify_config_schema(component) if merge_type == 'list': if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config or config[comp_name] is None: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.") continue if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Dict expected in package.") continue error = _recursive_merge(conf=config[comp_name], package=comp_conf) if error: _log_pkg_error(pack_name, comp_name, config, "has duplicate key '{}'".format(error)) return config
}, "time": datetime.timedelta(seconds=3) }, "light_on": { "name": "Light On", "icon": { True: "lightbulb-on", False: "lightbulb" }, "time": datetime.timedelta(minutes=5) } } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_SWITCHES, default=[]): vol.All(cv.ensure_list([vol.In(SWITCHES)])) }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the DoorBird switch platform.""" device = hass.data.get(DOORBIRD_DOMAIN) switches = [] for switch in SWITCHES: _LOGGER.debug("Adding DoorBird switch %s", SWITCHES[switch]["name"]) switches.append(DoorBirdSwitch(device, switch)) add_devices(switches) _LOGGER.info("Added DoorBird switches")
ATTR_ACCOUNT = CONF_ACCOUNT ATTR_BANK = 'bank' ATTR_ACCOUNT_TYPE = 'account_type' SCHEMA_ACCOUNTS = vol.Schema({ vol.Required(CONF_ACCOUNT): cv.string, vol.Optional(CONF_NAME, default=None): vol.Any(None, cv.string), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_BIN): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PIN): cv.string, vol.Required(CONF_URL): cv.string, vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_ACCOUNTS, default=[]): cv.ensure_list(SCHEMA_ACCOUNTS), vol.Optional(CONF_HOLDINGS, default=[]): cv.ensure_list(SCHEMA_ACCOUNTS), }) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the sensors. Login to the bank and get a list of existing accounts. Create a sensor for each account. """ credentials = BankCredentials(config[CONF_BIN], config[CONF_USERNAME], config[CONF_PIN], config[CONF_URL]) fints_name = config.get(CONF_NAME, config[CONF_BIN]) account_config = {acc[CONF_ACCOUNT]: acc[CONF_NAME]
def merge_packages_config(config, packages, _log_pkg_error=_log_pkg_error): """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue component = get_component(comp_name) if component is None: _log_pkg_error(pack_name, comp_name, config, "does not exist") continue if hasattr(component, 'PLATFORM_SCHEMA'): if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if hasattr(component, 'CONFIG_SCHEMA'): merge_type, _ = _identify_config_schema(component) if merge_type == 'list': if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if merge_type == 'dict': if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.") continue for key, val in comp_conf.items(): if key in config[comp_name]: _log_pkg_error(pack_name, comp_name, config, "duplicate key '{}'".format(key)) continue config[comp_name][key] = val continue # The last merge type are sections that may occur only once if comp_name in config: _log_pkg_error( pack_name, comp_name, config, "may occur only once" " and it already exist in your main configuration") continue config[comp_name] = comp_conf return config
cv.positive_int, vol.Optional(ATTR_MAX_POSITION): cv.positive_int, vol.Optional(ATTR_ROTATION): vol.In(ROTATIONS), vol.Optional(ATTR_SCALE): vol.In(SCALES), vol.Optional(ATTR_TICKS): cv.positive_int, }) DIAL_STATE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend({ vol.Required(ATTR_VALUE): vol.Coerce(int), vol.Optional(ATTR_LABELS): cv.ensure_list(cv.string), }) WINK_COMPONENTS = [ "binary_sensor", "sensor", "light", "switch", "lock", "cover", "climate", "fan", "alarm_control_panel", "scene", "water_heater", ]
async def async_start( # noqa: C901 hass: HomeAssistant, discovery_topic, config_entry=None) -> None: """Start MQTT Discovery.""" mqtt_integrations = {} async def async_discovery_message_received(msg): """Process the received message.""" hass.data[LAST_DISCOVERY] = time.time() payload = msg.payload topic = msg.topic topic_trimmed = topic.replace(f"{discovery_topic}/", "", 1) if not (match := TOPIC_MATCHER.match(topic_trimmed)): if topic_trimmed.endswith("config"): _LOGGER.warning( "Received message on illegal discovery topic '%s'. The topic contains " "not allowed characters. For more information see " "https://www.home-assistant.io/docs/mqtt/discovery/#discovery-topic", topic, ) return component, node_id, object_id = match.groups() if component not in SUPPORTED_COMPONENTS: _LOGGER.warning("Integration %s is not supported", component) return if payload: try: payload = json_loads(payload) except ValueError: _LOGGER.warning("Unable to parse JSON %s: '%s'", object_id, payload) return payload = MQTTConfig(payload) for key in list(payload): abbreviated_key = key key = ABBREVIATIONS.get(key, key) payload[key] = payload.pop(abbreviated_key) if CONF_DEVICE in payload: device = payload[CONF_DEVICE] for key in list(device): abbreviated_key = key key = DEVICE_ABBREVIATIONS.get(key, key) device[key] = device.pop(abbreviated_key) if TOPIC_BASE in payload: base = payload.pop(TOPIC_BASE) for key, value in payload.items(): if isinstance(value, str) and value: if value[0] == TOPIC_BASE and key.endswith("topic"): payload[key] = f"{base}{value[1:]}" if value[-1] == TOPIC_BASE and key.endswith("topic"): payload[key] = f"{value[:-1]}{base}" if payload.get(CONF_AVAILABILITY): for availability_conf in cv.ensure_list( payload[CONF_AVAILABILITY]): if not isinstance(availability_conf, dict): continue if topic := availability_conf.get(CONF_TOPIC): if topic[0] == TOPIC_BASE: availability_conf[ CONF_TOPIC] = f"{base}{topic[1:]}" if topic[-1] == TOPIC_BASE: availability_conf[ CONF_TOPIC] = f"{topic[:-1]}{base}"
vol.Any(None, cv.string), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_BIN): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PIN): cv.string, vol.Required(CONF_URL): cv.string, vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_ACCOUNTS, default=[]): cv.ensure_list(SCHEMA_ACCOUNTS), vol.Optional(CONF_HOLDINGS, default=[]): cv.ensure_list(SCHEMA_ACCOUNTS), }) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the sensors. Login to the bank and get a list of existing accounts. Create a sensor for each account. """ credentials = BankCredentials(config[CONF_BIN], config[CONF_USERNAME], config[CONF_PIN], config[CONF_URL]) fints_name = config.get(CONF_NAME, config[CONF_BIN])
def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict, _log_pkg_error: Callable = _log_pkg_error) -> Dict: """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue component = get_component(hass, comp_name) if component is None: _log_pkg_error(pack_name, comp_name, config, "does not exist") continue if hasattr(component, 'PLATFORM_SCHEMA'): if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if hasattr(component, 'CONFIG_SCHEMA'): merge_type, _ = _identify_config_schema(component) if merge_type == 'list': if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config or config[comp_name] is None: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.") continue if not isinstance(comp_conf, dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in package.") continue error = _recursive_merge(conf=config[comp_name], package=comp_conf) if error: _log_pkg_error(pack_name, comp_name, config, "has duplicate key '{}'".format(error)) return config
async def merge_packages_config(hass: HomeAssistant, config: Dict, packages: Dict, _log_pkg_error: Callable = _log_pkg_error) \ -> Dict: """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): for comp_name, comp_conf in pack_conf.items(): if comp_name == CONF_CORE: continue # If component name is given with a trailing description, remove it # when looking for component domain = comp_name.split(' ')[0] try: integration = await async_get_integration(hass, domain) except IntegrationNotFound: _log_pkg_error(pack_name, comp_name, config, "does not exist") continue try: component = integration.get_component() except ImportError: _log_pkg_error(pack_name, comp_name, config, "unable to import") continue if hasattr(component, 'PLATFORM_SCHEMA'): if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if hasattr(component, 'CONFIG_SCHEMA'): merge_type, _ = _identify_config_schema(component) if merge_type == 'list': if not comp_conf: continue # Ensure we dont add Falsy items to list config[comp_name] = cv.ensure_list(config.get(comp_name)) config[comp_name].extend(cv.ensure_list(comp_conf)) continue if comp_conf is None: comp_conf = OrderedDict() if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Expected a dict.") continue if comp_name not in config or config[comp_name] is None: config[comp_name] = OrderedDict() if not isinstance(config[comp_name], dict): _log_pkg_error( pack_name, comp_name, config, "cannot be merged. Dict expected in main config.") continue if not isinstance(comp_conf, dict): _log_pkg_error(pack_name, comp_name, config, "cannot be merged. Dict expected in package.") continue error = _recursive_merge(conf=config[comp_name], package=comp_conf) if error: _log_pkg_error(pack_name, comp_name, config, "has duplicate key '{}'".format(error)) return config
from homeassistant import config_entries from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from .const import ATTR_TARIFF, DEFAULT_NAME, DEFAULT_TARIFF, DOMAIN, PLATFORMS, TARIFFS UI_CONFIG_SCHEMA = vol.Schema( { vol.Required(CONF_NAME, default=DEFAULT_NAME): str, vol.Required(ATTR_TARIFF, default=DEFAULT_TARIFF): vol.In(TARIFFS), } ) CONFIG_SCHEMA = vol.Schema( {DOMAIN: cv.ensure_list(UI_CONFIG_SCHEMA)}, extra=vol.ALLOW_EXTRA ) async def async_setup(hass: HomeAssistant, config: dict): """ Set up the electricity price sensor from configuration.yaml. ```yaml pvpc_hourly_pricing: - name: PVPC manual ve tariff: electric_car - name: PVPC manual nocturna tariff: discrimination timeout: 3 ```
def datapoints_greater_than_degree(value: dict) -> dict: """Validate data point list is greater than polynomial degrees.""" if not len(value[CONF_DATAPOINTS]) > value[CONF_DEGREE]: raise vol.Invalid( f"{CONF_DATAPOINTS} must have at least {value[CONF_DEGREE]+1} {CONF_DATAPOINTS}" ) return value COMPENSATION_SCHEMA = vol.Schema( { vol.Required(CONF_TRACKED_ENTITY_ID): cv.entity_id, vol.Optional(CONF_DATAPOINTS): vol.All( cv.ensure_list(cv.matches_regex(MATCH_DATAPOINT)), ), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_ATTRIBUTE): cv.string, vol.Optional(CONF_PRECISION, default=DEFAULT_PRECISION): cv.positive_int, vol.Optional(CONF_DEGREE, default=DEFAULT_DEGREE): vol.All( vol.Coerce(int), vol.Range(min=1, max=7), ), vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, } ) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema(
''' WeatherChinaćDeveloper by Charley ''' import logging import voluptuous as vol from homeassistant.const import TEMP_CELSIUS from homeassistant.helpers.entity import Entity from homeassistant.components.sensor import PLATFORM_SCHEMA import homeassistant.helpers.config_validation as cv import requests import json PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( {vol.Required('CityCode', default=[]): vol.All(cv.ensure_list(cv.string))}) _Logger = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the sensor platform.""" # global _CityCodes cityCodes = config.get('CityCode') dev = [] for code in cityCodes: # _Logger.info('[WeatherChina] init CityCode======>'+ code) dev.append(WeatherChina(code)) add_devices(dev)
ATTR_DATA = 'data' CONF_STATE = 'state' OFF_STATES = [STATE_IDLE, STATE_OFF] REQUIREMENTS = [] _LOGGER = logging.getLogger(__name__) ATTRS_SCHEMA = vol.Schema({cv.slug: cv.string}) CMD_SCHEMA = vol.Schema({cv.slug: cv.SERVICE_SCHEMA}) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_CHILDREN, default=[]): cv.entity_ids, vol.Optional(CONF_COMMANDS, default={}): CMD_SCHEMA, vol.Optional(CONF_ATTRS, default={}): vol.Or(cv.ensure_list(ATTRS_SCHEMA), ATTRS_SCHEMA), vol.Optional(CONF_STATE_TEMPLATE): cv.template }, extra=vol.REMOVE_EXTRA) @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the universal media players.""" player = UniversalMediaPlayer( hass, config.get(CONF_NAME), config.get(CONF_CHILDREN), config.get(CONF_COMMANDS), config.get(CONF_ATTRS), config.get(CONF_STATE_TEMPLATE) )
'step': prop.range_step(), 'description': prop.list_description(value) if prop.value_list else None, }) or [] if isinstance(pms, dict) and 'method' in pms: setter = pms.get('method', setter) pms = pms.get('params', []) elif fmt and hasattr(mph, fmt): pms = [getattr(mph, fmt)(value)] elif d := cfg.get('dict', {}): for dk, dv in d.items(): if dv == value: pms = [dk] break pms = cv.ensure_list(pms) if not setter: _LOGGER.warning('%s: Set miio prop via miot failed: %s', self.model, [key, setter, cfg]) return None _LOGGER.info('%s: Set miio prop via miot: %s', self.model, [key, setter, pms]) ret = device.send(setter, pms) or [''] iok = ret == ['ok'] if self.config.get('ignore_result'): iok = ret or isinstance(ret, list) cbk = cfg.get('set_callback') if iok and cbk: cbk(prop=cfg.get('prop'), config=cfg, setter=setter,