def get_variable(id, type=None): def get_result(): if id is not None: if id in _VARIABLES: return _VARIABLES[id][0] elif type is not None: return next( (x[0] for x in _VARIABLES.itervalues() if x[1] == type), None) return None while _QUEUE: result = get_result() if result is not None: return result func, config = _QUEUE.popleft() func(config) if id is None and type is None: return None result = get_result() if result is None: if type is None: raise ESPHomeYAMLError(u"Couldn't find ID '{}'".format(id)) raise ESPHomeYAMLError(u"Couldn't find ID '{}' with type '{}'".format( id, type)) return result
def load_config(path): try: config = yaml_util.load_yaml(path) except OSError: raise ESPHomeYAMLError( u"Could not read configuration file at {}".format(path)) core.RAW_CONFIG = config if CONF_ESPHOMEYAML not in config: raise ESPHomeYAMLError(u"No esphomeyaml section in config") core_conf = config[CONF_ESPHOMEYAML] if CONF_PLATFORM not in core_conf: raise ESPHomeYAMLError("esphomeyaml.platform not specified.") esp_platform = unicode(core_conf[CONF_PLATFORM]) esp_platform = esp_platform.upper() if '8266' in esp_platform: esp_platform = ESP_PLATFORM_ESP8266 if '32' in esp_platform: esp_platform = ESP_PLATFORM_ESP32 core.ESP_PLATFORM = esp_platform if CONF_BOARD not in core_conf: raise ESPHomeYAMLError("esphomeyaml.board not specified.") core.BOARD = unicode(core_conf[CONF_BOARD]) core.SIMPLIFY = cv.boolean(core_conf.get(CONF_SIMPLIFY, True)) try: result = validate_config(config) except Exception: print(u"Unexpected exception while reading configuration:") raise return result
def load_yaml(fname): """Load a YAML file.""" try: with codecs.open(fname, encoding='utf-8') as conf_file: return yaml.load(conf_file, Loader=SafeLineLoader) or OrderedDict() except yaml.YAMLError as exc: _LOGGER.error(exc) raise ESPHomeYAMLError(exc) except UnicodeDecodeError as exc: _LOGGER.error(u"Unable to read file %s: %s", fname, exc) raise ESPHomeYAMLError(exc)
def _secret_yaml(loader, node): """Load secrets and embed it into the configuration YAML.""" secret_path = os.path.join(os.path.dirname(loader.name), SECRET_YAML) secrets = load_yaml(secret_path) if node.value not in secrets: raise ESPHomeYAMLError(u"Secret {} not defined".format(node.value)) return secrets[node.value]
def _ordered_dict(loader, node): """Load YAML mappings into an ordered dictionary to preserve key order.""" loader.flatten_mapping(node) nodes = loader.construct_pairs(node) seen = {} for (key, _), (child_node, _) in zip(nodes, node.value): line = child_node.start_mark.line try: hash(key) except TypeError: fname = getattr(loader.stream, 'name', '') raise yaml.MarkedYAMLError( context="invalid key: \"{}\"".format(key), context_mark=yaml.Mark(fname, 0, line, -1, None, None)) if key in seen: fname = getattr(loader.stream, 'name', '') raise ESPHomeYAMLError( u'YAML file {} contains duplicate key "{}". ' u'Check lines {} and {}.'.format(fname, key, seen[key], line)) seen[key] = line return _add_reference(OrderedDict(nodes), loader, node)
def build_condition(config, arg_type): template_arg = TemplateArguments(arg_type) if CONF_AND in config: yield AndCondition.new( template_arg, build_conditions(config[CONF_AND], template_arg)) elif CONF_OR in config: yield OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg)) elif CONF_LAMBDA in config: lambda_ = None for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]): yield yield LambdaCondition.new(template_arg, lambda_) elif CONF_RANGE in config: conf = config[CONF_RANGE] rhs = RangeCondition.new(template_arg) type = RangeCondition.template(template_arg) condition = Pvariable(config[CONF_CONDITION_ID], rhs, type=type) if CONF_ABOVE in conf: template_ = None for template_ in templatable(conf[CONF_ABOVE], arg_type, float_): yield condition.set_min(template_) if CONF_BELOW in conf: template_ = None for template_ in templatable(conf[CONF_BELOW], arg_type, float_): yield condition.set_max(template_) yield condition else: raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
def exp_send_data(config): if CONF_NEC in config: conf = config[CONF_NEC] base = SendData.from_nec(safe_hex(conf[CONF_ADDRESS]), safe_hex(conf[CONF_COMMAND])) elif CONF_LG in config: conf = config[CONF_LG] base = SendData.from_lg(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS)) elif CONF_SONY in config: conf = config[CONF_SONY] base = SendData.from_sony(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS)) elif CONF_PANASONIC in config: conf = config[CONF_PANASONIC] base = SendData.from_panasonic(safe_hex(conf[CONF_ADDRESS]), safe_hex(conf[CONF_COMMAND])) elif CONF_RAW in config: conf = config[CONF_RAW] data = ArrayInitializer(*conf[CONF_DATA]) base = SendData.from_raw(data, conf[CONF_CARRIER_FREQUENCY]) else: raise ESPHomeYAMLError(u"Unsupported IR mode {}".format(config)) if CONF_REPEAT in config: if isinstance(config[CONF_REPEAT], int): times = config[CONF_REPEAT] wait_us = None else: times = config[CONF_REPEAT][CONF_TIMES] wait_us = config[CONF_REPEAT][CONF_WAIT_TIME] base = base.repeat(times, wait_us) return base
def __init__(self, config): if 'mqtt' not in config: raise ESPHomeYAMLError( "Cannot generate Home Assistant MQTT config if MQTT is not " "used!") mqtt = config[CONF_MQTT] self.topic_prefix = mqtt.get(CONF_TOPIC_PREFIX, config[CONF_ESPHOMEYAML][CONF_NAME]) birth_message = mqtt.get(CONF_BIRTH_MESSAGE) if CONF_BIRTH_MESSAGE not in mqtt: birth_message = { CONF_TOPIC: self.topic_prefix + '/status', CONF_PAYLOAD: 'online', } will_message = mqtt.get(CONF_WILL_MESSAGE) if CONF_WILL_MESSAGE not in mqtt: will_message = { CONF_TOPIC: self.topic_prefix + '/status', CONF_PAYLOAD: 'offline' } if not birth_message or not will_message: self.availability = None elif birth_message[CONF_TOPIC] != will_message[CONF_TOPIC]: self.availability = None else: self.availability = { CONF_TOPIC: birth_message[CONF_TOPIC], CONF_PAYLOAD_AVAILABLE: birth_message[CONF_PAYLOAD], CONF_PAYLOAD_NOT_AVAILABLE: will_message[CONF_PAYLOAD], }
def generic_gpio_pin_expression_(conf, mock_obj, default_mode): if conf is None: return number = conf[CONF_NUMBER] inverted = conf.get(CONF_INVERTED) if CONF_PCF8574 in conf: hub = None for hub in get_variable(conf[CONF_PCF8574]): yield None if default_mode == u'INPUT': mode = conf.get(CONF_MODE, u'INPUT') yield hub.make_input_pin(number, RawExpression('PCF8574_' + mode), inverted) return elif default_mode == u'OUTPUT': yield hub.make_output_pin(number, inverted) return else: raise ESPHomeYAMLError( u"Unknown default mode {}".format(default_mode)) if len(conf) == 1: yield IntLiteral(number) return mode = RawExpression(conf.get(CONF_MODE, default_mode)) yield mock_obj(number, mode, inverted)
def find_begin_end(text, begin_s, end_s): begin_index = text.find(begin_s) if begin_index == -1: raise ESPHomeYAMLError(u"Could not find auto generated code begin in file, either" u"delete the main sketch file or insert the comment again.") if text.find(begin_s, begin_index + 1) != -1: raise ESPHomeYAMLError(u"Found multiple auto generate code begins, don't know" u"which to chose, please remove one of them.") end_index = text.find(end_s) if end_index == -1: raise ESPHomeYAMLError(u"Could not find auto generated code end in file, either" u"delete the main sketch file or insert the comment again.") if text.find(end_s, end_index + 1) != -1: raise ESPHomeYAMLError(u"Found multiple auto generate code endings, don't know" u"which to chose, please remove one of them.") return text[:begin_index], text[(end_index + len(end_s)):]
def preload_core_config(config): if CONF_ESPHOMEYAML not in config: raise ESPHomeYAMLError(u"No esphomeyaml section in config") core_conf = config[CONF_ESPHOMEYAML] if CONF_PLATFORM not in core_conf: raise ESPHomeYAMLError("esphomeyaml.platform not specified.") if CONF_BOARD not in core_conf: raise ESPHomeYAMLError("esphomeyaml.board not specified.") if CONF_NAME not in core_conf: raise ESPHomeYAMLError("esphomeyaml.name not specified.") try: core.ESP_PLATFORM = validate_platform(core_conf[CONF_PLATFORM]) core.BOARD = validate_board(core_conf[CONF_BOARD]) core.NAME = cv.valid_name(core_conf[CONF_NAME]) except vol.Invalid as e: raise ESPHomeYAMLError(unicode(e))
def get_port(config): if CONF_PORT in config[CONF_OTA]: return config[CONF_OTA][CONF_PORT] if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: return 3232 elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266: return 8266 raise ESPHomeYAMLError(u"Invalid ESP Platform for ESP OTA port.")
def validate_local_no_higher_than_global(value): global_level = value.get(CONF_LEVEL, 'DEBUG') for tag, level in value.get(CONF_LOGS, {}).iteritems(): if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index( global_level): raise ESPHomeYAMLError( u"The local log level {} for {} must be less severe than the " u"global log level {}.".format(level, tag, global_level)) return value
def _env_var_yaml(_, node): """Load environment variables and embed it into the configuration YAML.""" args = node.value.split() # Check for a default value if len(args) > 1: return os.getenv(args[0], u' '.join(args[1:])) elif args[0] in os.environ: return os.environ[args[0]] raise ESPHomeYAMLError(u"Environment variable {} not defined.".format(node.value))
def flush_tasks(): i = 0 while _TASKS: i += 1 if i > 1000000: raise ESPHomeYAMLError("Circular dependency detected!") task, domain = _TASKS.popleft() _LOGGER.debug("Executing task for domain=%s", domain) try: task.next() _TASKS.append((task, domain)) except StopIteration: _LOGGER.debug(" -> %s finished", domain)
def to_code(config): rhs = App.init_log(config.get(CONF_BAUD_RATE)) log = Pvariable(u'LogComponent', config[CONF_ID], rhs) if CONF_TX_BUFFER_SIZE in config: add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE])) if CONF_LEVEL in config: add(log.set_global_log_level(exp_log_level(config[CONF_LEVEL]))) for tag, level in config.get(CONF_LOGS, {}).iteritems(): global_level = config.get(CONF_LEVEL, 'DEBUG') if LOG_LEVELS.index(level) > LOG_LEVELS.index(global_level): raise ESPHomeYAMLError( u"The local log level {} for {} must be less severe than the " u"global log level {}.".format(level, tag, global_level)) add(log.set_log_level(tag, exp_log_level(level)))
def load_config(path): try: config = yaml_util.load_yaml(path) except OSError: raise ESPHomeYAMLError(u"Could not read configuration file at {}".format(path)) core.RAW_CONFIG = config core_config.preload_core_config(config) try: result = validate_config(config) except ESPHomeYAMLError: raise except Exception: _LOGGER.error(u"Unexpected exception while reading configuration:") raise return result
def write_platformio_ini(content, path): if os.path.isfile(path): try: with codecs.open(path, 'r', encoding='utf-8') as f_handle: text = f_handle.read() except OSError: raise ESPHomeYAMLError(u"Could not read ini file at {}".format(path)) prev_file = text content_format = find_begin_end(text, INI_AUTO_GENERATE_BEGIN, INI_AUTO_GENERATE_END) else: prev_file = None content_format = INI_BASE_FORMAT full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + '\n' + \ content + INI_AUTO_GENERATE_END + content_format[1] if prev_file == full_file: return with codecs.open(path, mode='w+', encoding='utf-8') as f_handle: f_handle.write(full_file)
def custom_construct_pairs(loader, node): pairs = [] for kv in node.value: if isinstance(kv, yaml.ScalarNode): obj = loader.construct_object(kv) if not isinstance(obj, dict): raise ESPHomeYAMLError( "Expected mapping for anchored include tag, got {}".format( type(obj))) for key, value in obj.iteritems(): pairs.append((key, value)) else: key_node, value_node = kv key = loader.construct_object(key_node) value = loader.construct_object(value_node) pairs.append((key, value)) return pairs
def start_web_server(args): global CONFIG_DIR global PASSWORD if tornado is None: raise ESPHomeYAMLError( "Attempted to load dashboard, but tornado is not installed! " "Please run \"pip2 install tornado esptool\" in your terminal.") CONFIG_DIR = args.configuration if not os.path.exists(CONFIG_DIR): os.makedirs(CONFIG_DIR) # HassIO options storage PASSWORD = args.password if os.path.isfile('/data/options.json'): with open('/data/options.json') as f: js = json.load(f) PASSWORD = js.get('password') or PASSWORD if PASSWORD: PASSWORD = hmac.new(str(PASSWORD)).digest() # Use the digest of the password as our cookie secret. This makes sure the cookie # isn't too short. It, of course, enables local hash brute forcing (because the cookie # secret can be brute forced without making requests). But the hashing algorithm used # by tornado is apparently strong enough to make brute forcing even a short string pretty # hard. _LOGGER.info( "Starting dashboard web server on port %s and configuration dir %s...", args.port, CONFIG_DIR) app = make_app(args.verbose) app.listen(args.port) if args.open_ui: import webbrowser webbrowser.open('localhost:{}'.format(args.port)) try: tornado.ioloop.IOLoop.current().start() except KeyboardInterrupt: _LOGGER.info("Shutting down...")
def write_cpp(code_s, path): if os.path.isfile(path): try: with codecs.open(path, 'r', encoding='utf-8') as f_handle: text = f_handle.read() except OSError: raise ESPHomeYAMLError(u"Could not read C++ file at {}".format(path)) prev_file = text code_format = find_begin_end(text, CPP_AUTO_GENERATE_BEGIN, CPP_AUTO_GENERATE_END) else: prev_file = None mkdir_p(os.path.dirname(path)) code_format = CPP_BASE_FORMAT full_file = code_format[0] + CPP_AUTO_GENERATE_BEGIN + '\n' + \ code_s + CPP_AUTO_GENERATE_END + code_format[1] if prev_file == full_file: return with codecs.open(path, 'w+', encoding='utf-8') as f_handle: f_handle.write(full_file)
def exp_gpio_pin_(obj, conf, default_mode): if isinstance(conf, int): return conf if 'pcf8574' in conf: hub = get_variable(conf['pcf8574']) if default_mode == u'INPUT': return hub.make_input_pin( conf[CONF_NUMBER], RawExpression('PCF8574_' + conf[CONF_MODE]), conf[CONF_INVERTED]) elif default_mode == u'OUTPUT': return hub.make_output_pin(conf[CONF_NUMBER], conf[CONF_INVERTED]) else: raise ESPHomeYAMLError( u"Unknown default mode {}".format(default_mode)) if conf.get(CONF_INVERTED) is None: return obj(conf[CONF_NUMBER], conf.get(CONF_MODE)) return obj(conf[CONF_NUMBER], RawExpression(conf.get(CONF_MODE, default_mode)), conf[CONF_INVERTED])
def build_condition(config, arg_type): template_arg = TemplateArguments(arg_type) if CONF_AND in config: return AndCondition.new( template_arg, build_conditions(config[CONF_AND], template_arg)) if CONF_OR in config: return OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg)) if CONF_LAMBDA in config: return LambdaCondition.new( template_arg, process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')])) if CONF_RANGE in config: conf = config[CONF_RANGE] rhs = RangeCondition.new(template_arg) condition = Pvariable(RangeCondition.template(template_arg), config[CONF_CONDITION_ID], rhs) if CONF_ABOVE in conf: condition.set_min(templatable(conf[CONF_ABOVE], arg_type, float_)) if CONF_BELOW in conf: condition.set_max(templatable(conf[CONF_BELOW], arg_type, float_)) return condition raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
def validate_config(config): global _ALL_COMPONENTS for req in REQUIRED_COMPONENTS: if req not in config: raise ESPHomeYAMLError( "Component {} is required for esphomeyaml.".format(req)) _ALL_COMPONENTS = list(config.keys()) result = Config() def _comp_error(ex, domain, config): result.add_error(_format_config_error(ex, domain, config), domain, config) try: result[CONF_ESPHOMEYAML] = CORE_SCHEMA(config[CONF_ESPHOMEYAML]) except vol.Invalid as ex: _comp_error(ex, CONF_ESPHOMEYAML, config) for domain, conf in config.iteritems(): if domain == CONF_ESPHOMEYAML: continue if conf is None: conf = {} component = get_component(domain) if component is None: result.add_error(u"Component not found: {}".format(domain)) continue esp_platforms = getattr(component, 'ESP_PLATFORMS', ESP_PLATFORMS) if core.ESP_PLATFORM not in esp_platforms: result.add_error(u"Component {} doesn't support {}.".format( domain, core.ESP_PLATFORM)) continue success = True dependencies = getattr(component, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in _ALL_COMPONENTS: result.add_error(u"Component {} requires {}".format( domain, dependency)) success = False if not success: continue if hasattr(component, 'CONFIG_SCHEMA'): try: validated = component.CONFIG_SCHEMA(conf) result[domain] = validated except vol.Invalid as ex: _comp_error(ex, domain, conf) continue if not hasattr(component, 'PLATFORM_SCHEMA'): continue platforms = [] for p_config in conf: if not isinstance(p_config, dict): result.add_error(u"Platform schemas must have 'platform:' key") continue p_name = p_config.get(u'platform') if p_name is None: result.add_error( u"No platform specified for {}".format(domain)) continue platform = get_platform(domain, p_name) if platform is None: result.add_error(u"Platform not found: {}.{}") continue success = True dependencies = getattr(platform, 'DEPENDENCIES', []) for dependency in dependencies: if dependency not in _ALL_COMPONENTS: result.add_error(u"Platform {}.{} requires {}".format( domain, p_name, dependency)) success = False if not success: continue esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS) if core.ESP_PLATFORM not in esp_platforms: result.add_error(u"Platform {}.{} doesn't support {}.".format( domain, p_name, core.ESP_PLATFORM)) continue if hasattr(platform, u'PLATFORM_SCHEMA'): try: p_validated = platform.PLATFORM_SCHEMA(p_config) except vol.Invalid as ex: _comp_error(ex, u'{}.{}'.format(domain, p_name), p_config) continue platforms.append(p_validated) result[domain] = platforms return result
def valid_pwm_pin(value): if value[CONF_NUMBER] > 16: raise ESPHomeYAMLError(u"ESP8266: Only pins 0-16 support PWM.") return value
def build_action(config, arg_type): from esphomeyaml.components import light, mqtt, switch template_arg = TemplateArguments(arg_type) # Keep pylint from freaking out var = None if CONF_DELAY in config: rhs = App.register_component(DelayAction.new(template_arg)) type = DelayAction.template(template_arg) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) template_ = None for template_ in templatable(config[CONF_DELAY], arg_type, uint32): yield add(action.set_delay(template_)) yield action elif CONF_LAMBDA in config: lambda_ = None for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]): yield None rhs = LambdaAction.new(template_arg, lambda_) type = LambdaAction.template(template_arg) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_MQTT_PUBLISH in config: conf = config[CONF_MQTT_PUBLISH] rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg) type = mqtt.MQTTPublishAction.template(template_arg) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) template_ = None for template_ in templatable(conf[CONF_TOPIC], arg_type, std_string): yield None add(action.set_topic(template_)) template_ = None for template_ in templatable(conf[CONF_PAYLOAD], arg_type, std_string): yield None add(action.set_payload(template_)) if CONF_QOS in conf: template_ = None for template_ in templatable(conf[CONF_QOS], arg_type, uint8): yield add(action.set_qos(template_)) if CONF_RETAIN in conf: template_ = None for template_ in templatable(conf[CONF_RETAIN], arg_type, bool_): yield None add(action.set_retain(template_)) yield action elif CONF_LIGHT_TOGGLE in config: conf = config[CONF_LIGHT_TOGGLE] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = light.ToggleAction.template(template_arg) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) if CONF_TRANSITION_LENGTH in conf: template_ = None for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) yield action elif CONF_LIGHT_TURN_OFF in config: conf = config[CONF_LIGHT_TURN_OFF] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = light.TurnOffAction.template(template_arg) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) if CONF_TRANSITION_LENGTH in conf: template_ = None for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) yield action elif CONF_LIGHT_TURN_ON in config: conf = config[CONF_LIGHT_TURN_ON] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = light.TurnOnAction.template(template_arg) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) if CONF_TRANSITION_LENGTH in conf: template_ = None for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) if CONF_FLASH_LENGTH in conf: template_ = None for template_ in templatable(conf[CONF_FLASH_LENGTH], arg_type, uint32): yield None add(action.set_flash_length(template_)) if CONF_BRIGHTNESS in conf: template_ = None for template_ in templatable(conf[CONF_BRIGHTNESS], arg_type, float_): yield None add(action.set_brightness(template_)) if CONF_RED in conf: template_ = None for template_ in templatable(conf[CONF_RED], arg_type, float_): yield None add(action.set_red(template_)) if CONF_GREEN in conf: template_ = None for template_ in templatable(conf[CONF_GREEN], arg_type, float_): yield None add(action.set_green(template_)) if CONF_BLUE in conf: template_ = None for template_ in templatable(conf[CONF_BLUE], arg_type, float_): yield None add(action.set_blue(template_)) if CONF_WHITE in conf: template_ = None for template_ in templatable(conf[CONF_WHITE], arg_type, float_): yield None add(action.set_white(template_)) if CONF_EFFECT in conf: template_ = None for template_ in templatable(conf[CONF_EFFECT], arg_type, std_string): yield None add(action.set_effect(template_)) yield action elif CONF_SWITCH_TOGGLE in config: conf = config[CONF_SWITCH_TOGGLE] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = switch.ToggleAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_SWITCH_TURN_OFF in config: conf = config[CONF_SWITCH_TURN_OFF] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = switch.TurnOffAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_SWITCH_TURN_ON in config: conf = config[CONF_SWITCH_TURN_ON] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = switch.TurnOnAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_COVER_OPEN in config: conf = config[CONF_COVER_OPEN] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_open_action(template_arg) type = cover.OpenAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_COVER_CLOSE in config: conf = config[CONF_COVER_CLOSE] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_close_action(template_arg) type = cover.CloseAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_COVER_STOP in config: conf = config[CONF_COVER_STOP] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_stop_action(template_arg) type = cover.StopAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_FAN_TOGGLE in config: conf = config[CONF_FAN_TOGGLE] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = fan.ToggleAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_FAN_TURN_OFF in config: conf = config[CONF_FAN_TURN_OFF] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = fan.TurnOffAction.template(arg_type) yield Pvariable(config[CONF_ACTION_ID], rhs, type=type) elif CONF_FAN_TURN_ON in config: conf = config[CONF_FAN_TURN_ON] for var in get_variable(conf[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = fan.TurnOnAction.template(arg_type) action = Pvariable(config[CONF_ACTION_ID], rhs, type=type) if CONF_OSCILLATING in config: template_ = None for template_ in templatable(conf[CONF_OSCILLATING], arg_type, bool_): yield None add(action.set_oscillating(template_)) if CONF_SPEED in config: template_ = None for template_ in templatable(conf[CONF_SPEED], arg_type, fan.FanSpeed): yield None add(action.set_speed(template_)) yield action else: raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
def build_action(full_config, arg_type): from esphomeyaml.components import light, mqtt, switch template_arg = TemplateArguments(arg_type) # Keep pylint from freaking out var = None action_id = full_config[CONF_ACTION_ID] key, config = next( (k, v) for k, v in full_config.items() if k in ACTION_KEYS) if key == CONF_DELAY: rhs = App.register_component(DelayAction.new(template_arg)) type = DelayAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) for template_ in templatable(config, arg_type, uint32): yield add(action.set_delay(template_)) yield action elif key == CONF_LAMBDA: for lambda_ in process_lambda(config, [(arg_type, 'x')]): yield None rhs = LambdaAction.new(template_arg, lambda_) type = LambdaAction.template(template_arg) yield Pvariable(action_id, rhs, type=type) elif key == CONF_MQTT_PUBLISH: rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg) type = mqtt.MQTTPublishAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) for template_ in templatable(config[CONF_TOPIC], arg_type, std_string): yield None add(action.set_topic(template_)) for template_ in templatable(config[CONF_PAYLOAD], arg_type, std_string): yield None add(action.set_payload(template_)) if CONF_QOS in config: for template_ in templatable(config[CONF_QOS], arg_type, uint8): yield add(action.set_qos(template_)) if CONF_RETAIN in config: for template_ in templatable(config[CONF_RETAIN], arg_type, bool_): yield None add(action.set_retain(template_)) yield action elif key == CONF_LIGHT_TOGGLE: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = light.ToggleAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) if CONF_TRANSITION_LENGTH in config: for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) yield action elif key == CONF_LIGHT_TURN_OFF: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = light.TurnOffAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) if CONF_TRANSITION_LENGTH in config: for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) yield action elif key == CONF_LIGHT_TURN_ON: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = light.TurnOnAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) if CONF_TRANSITION_LENGTH in config: for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32): yield None add(action.set_transition_length(template_)) if CONF_FLASH_LENGTH in config: for template_ in templatable(config[CONF_FLASH_LENGTH], arg_type, uint32): yield None add(action.set_flash_length(template_)) if CONF_BRIGHTNESS in config: for template_ in templatable(config[CONF_BRIGHTNESS], arg_type, float_): yield None add(action.set_brightness(template_)) if CONF_RED in config: for template_ in templatable(config[CONF_RED], arg_type, float_): yield None add(action.set_red(template_)) if CONF_GREEN in config: for template_ in templatable(config[CONF_GREEN], arg_type, float_): yield None add(action.set_green(template_)) if CONF_BLUE in config: for template_ in templatable(config[CONF_BLUE], arg_type, float_): yield None add(action.set_blue(template_)) if CONF_WHITE in config: for template_ in templatable(config[CONF_WHITE], arg_type, float_): yield None add(action.set_white(template_)) if CONF_COLOR_TEMPERATURE in config: for template_ in templatable(config[CONF_COLOR_TEMPERATURE], arg_type, float_): yield None add(action.set_color_temperature(template_)) if CONF_EFFECT in config: for template_ in templatable(config[CONF_EFFECT], arg_type, std_string): yield None add(action.set_effect(template_)) yield action elif key == CONF_SWITCH_TOGGLE: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = switch.ToggleAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_SWITCH_TURN_OFF: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = switch.TurnOffAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_SWITCH_TURN_ON: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = switch.TurnOnAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_COVER_OPEN: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_open_action(template_arg) type = cover.OpenAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_COVER_CLOSE: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_close_action(template_arg) type = cover.CloseAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_COVER_STOP: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_stop_action(template_arg) type = cover.StopAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_FAN_TOGGLE: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_toggle_action(template_arg) type = fan.ToggleAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_FAN_TURN_OFF: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = fan.TurnOffAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_FAN_TURN_ON: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = fan.TurnOnAction.template(arg_type) action = Pvariable(action_id, rhs, type=type) if CONF_OSCILLATING in config: for template_ in templatable(config[CONF_OSCILLATING], arg_type, bool_): yield None add(action.set_oscillating(template_)) if CONF_SPEED in config: for template_ in templatable(config[CONF_SPEED], arg_type, fan.FanSpeed): yield None add(action.set_speed(template_)) yield action elif key == CONF_OUTPUT_TURN_OFF: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_off_action(template_arg) type = output.TurnOffAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_OUTPUT_TURN_ON: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_turn_on_action(template_arg) type = output.TurnOnAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_OUTPUT_SET_LEVEL: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_set_level_action(template_arg) type = output.SetLevelAction.template(arg_type) action = Pvariable(action_id, rhs, type=type) for template_ in templatable(config[CONF_LEVEL], arg_type, bool_): yield None add(action.set_level(template_)) yield action elif key == CONF_IF: for conditions in build_conditions(config[CONF_CONDITION], arg_type): yield None rhs = IfAction.new(template_arg, conditions) type = IfAction.template(template_arg) action = Pvariable(action_id, rhs, type=type) if CONF_THEN in config: for actions in build_actions(config[CONF_THEN], arg_type): yield None add(action.add_then(actions)) if CONF_ELSE in config: for actions in build_actions(config[CONF_ELSE], arg_type): yield None add(action.add_else(actions)) yield action elif key == CONF_DEEP_SLEEP_ENTER: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_enter_deep_sleep_action(template_arg) type = deep_sleep.EnterDeepSleepAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) elif key == CONF_DEEP_SLEEP_PREVENT: for var in get_variable(config[CONF_ID]): yield None rhs = var.make_prevent_deep_sleep_action(template_arg) type = deep_sleep.PreventDeepSleepAction.template(arg_type) yield Pvariable(action_id, rhs, type=type) else: raise ESPHomeYAMLError(u"Unsupported action {}".format(config))