From 6c6d21a7ab144c0fbd196f019e15aabee958314f Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 13 Jun 2018 21:27:58 +0200 Subject: [PATCH] Allow simpler automation syntax --- esphomeyaml/automation.py | 23 +++++++++++++++--- .../components/binary_sensor/__init__.py | 8 +++---- esphomeyaml/components/cover/template.py | 24 +++++++------------ esphomeyaml/components/mqtt.py | 2 +- esphomeyaml/components/remote_receiver.py | 14 +++++++++-- esphomeyaml/components/sensor/__init__.py | 7 +++--- .../components/switch/remote_transmitter.py | 18 ++++++++++---- esphomeyaml/components/switch/template.py | 16 +++++-------- esphomeyaml/config.json | 5 ---- esphomeyaml/config.py | 4 ++-- 10 files changed, 70 insertions(+), 51 deletions(-) diff --git a/esphomeyaml/automation.py b/esphomeyaml/automation.py index d1b00d571..af20359e5 100644 --- a/esphomeyaml/automation.py +++ b/esphomeyaml/automation.py @@ -132,6 +132,22 @@ OrCondition = esphomelib_ns.OrCondition RangeCondition = esphomelib_ns.RangeCondition LambdaCondition = esphomelib_ns.LambdaCondition + +def validate_automation(extra_schema=None): + schema = AUTOMATION_SCHEMA.extend(extra_schema or {}) + + def validator(value): + if isinstance(value, list): + return schema({CONF_THEN: value}) + elif isinstance(value, dict): + if CONF_THEN in value: + return schema(value) + return schema({CONF_THEN: value}) + return schema(value) + + return validator + + AUTOMATION_SCHEMA = vol.Schema({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(None), cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(None), @@ -391,18 +407,19 @@ def build_actions(config, arg_type): def build_automation_(trigger, arg_type, config): - rhs = App.make_automation(trigger) + rhs = App.make_automation(TemplateArguments(arg_type), trigger) type = Automation.template(arg_type) obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type) if CONF_IF in config: conditions = None for conditions in build_conditions(config[CONF_IF], arg_type): - yield + yield None add(obj.add_conditions(conditions)) actions = None for actions in build_actions(config[CONF_THEN], arg_type): - yield + yield None add(obj.add_actions(actions)) + yield obj def build_automation(trigger, arg_type, config): diff --git a/esphomeyaml/components/binary_sensor/__init__.py b/esphomeyaml/components/binary_sensor/__init__.py index 902983bea..89f64a554 100644 --- a/esphomeyaml/components/binary_sensor/__init__.py +++ b/esphomeyaml/components/binary_sensor/__init__.py @@ -47,19 +47,19 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower, cv.one_of(*DEVICE_CLASSES)), vol.Optional(CONF_FILTERS): FILTERS_SCHEMA, - vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PressTrigger), })]), - vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ReleaseTrigger), })]), - vol.Optional(CONF_ON_CLICK): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_CLICK): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ClickTrigger), vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, })]), vol.Optional(CONF_ON_DOUBLE_CLICK): - vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(DoubleClickTrigger), vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, diff --git a/esphomeyaml/components/cover/template.py b/esphomeyaml/components/cover/template.py index 1f6c0643f..df1d1e248 100644 --- a/esphomeyaml/components/cover/template.py +++ b/esphomeyaml/components/cover/template.py @@ -13,9 +13,9 @@ PLATFORM_SCHEMA = cv.nameable(cover.COVER_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateCover), vol.Optional(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_OPTIMISTIC): cv.boolean, - vol.Optional(CONF_OPEN_ACTION): automation.ACTIONS_SCHEMA, - vol.Optional(CONF_CLOSE_ACTION): automation.ACTIONS_SCHEMA, - vol.Optional(CONF_STOP_ACTION): automation.ACTIONS_SCHEMA, + vol.Optional(CONF_OPEN_ACTION): automation.validate_automation(), + vol.Optional(CONF_CLOSE_ACTION): automation.validate_automation(), + vol.Optional(CONF_STOP_ACTION): automation.validate_automation(), }), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) @@ -30,20 +30,14 @@ def to_code(config): yield add(make.Ptemplate_.set_state_lambda(template_)) if CONF_OPEN_ACTION in config: - actions = None - for actions in automation.build_actions(config[CONF_OPEN_ACTION], NoArg): - yield - add(make.Ptemplate_.add_open_actions(actions)) + automation.build_automation(make.Ptemplate_.get_open_trigger(), NoArg, + config[CONF_OPEN_ACTION]) if CONF_CLOSE_ACTION in config: - actions = None - for actions in automation.build_actions(config[CONF_CLOSE_ACTION], NoArg): - yield - add(make.Ptemplate_.add_close_actions(actions)) + automation.build_automation(make.Ptemplate_.get_close_trigger(), NoArg, + config[CONF_CLOSE_ACTION]) if CONF_STOP_ACTION in config: - actions = None - for actions in automation.build_actions(config[CONF_STOP_ACTION], NoArg): - yield - add(make.Ptemplate_.add_stop_actions(actions)) + automation.build_automation(make.Ptemplate_.get_stop_trigger(), NoArg, + config[CONF_STOP_ACTION]) if CONF_OPTIMISTIC in config: add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC])) diff --git a/esphomeyaml/components/mqtt.py b/esphomeyaml/components/mqtt.py index a68787245..1d174a67c 100644 --- a/esphomeyaml/components/mqtt.py +++ b/esphomeyaml/components/mqtt.py @@ -72,7 +72,7 @@ CONFIG_SCHEMA = vol.Schema({ cv.ensure_list, [validate_fingerprint]), vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds, vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds, - vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger), vol.Required(CONF_TOPIC): cv.publish_topic, vol.Optional(CONF_QOS, default=0): cv.mqtt_qos, diff --git a/esphomeyaml/components/remote_receiver.py b/esphomeyaml/components/remote_receiver.py index 574d8d02d..1c0c93077 100644 --- a/esphomeyaml/components/remote_receiver.py +++ b/esphomeyaml/components/remote_receiver.py @@ -18,11 +18,21 @@ DUMPERS = { 'sony': remote_ns.SonyDumper, } + +def validate_dumpers_all(value): + if not isinstance(value, (str, unicode)): + raise vol.Invalid("Not valid dumpers") + if value.upper() == "ALL": + return list(DUMPERS) + raise vol.Invalid("Not valid dumpers") + + CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent), vol.Required(CONF_PIN): pins.gpio_input_pin_schema, - vol.Optional(CONF_DUMP, default=[]): vol.All(cv.ensure_list, - [vol.All(vol.Lower, cv.one_of(*DUMPERS))]), + vol.Optional(CONF_DUMP, default=[]): + vol.Any(validate_dumpers_all, + vol.All(cv.ensure_list, [vol.All(vol.Lower, cv.one_of(*DUMPERS))])), vol.Optional(CONF_TOLERANCE): vol.All(cv.percentage_int, vol.Range(min=0)), vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes, vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds, diff --git a/esphomeyaml/components/sensor/__init__.py b/esphomeyaml/components/sensor/__init__.py index de7cf0662..67e2e4f5d 100644 --- a/esphomeyaml/components/sensor/__init__.py +++ b/esphomeyaml/components/sensor/__init__.py @@ -72,20 +72,19 @@ ValueRangeTrigger = sensor_ns.ValueRangeTrigger SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent), cv.GenerateID(): cv.declare_variable_id(Sensor), - vol.Required(CONF_NAME): cv.string, vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict, vol.Optional(CONF_ICON): cv.icon, vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int), vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds), vol.Optional(CONF_FILTERS): FILTERS_SCHEMA, - vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(SensorValueTrigger), })]), - vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(RawSensorValueTrigger), })]), vol.Optional(CONF_ON_VALUE_RANGE): vol.All(cv.ensure_list, [vol.All( - automation.AUTOMATION_SCHEMA.extend({ + automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ValueRangeTrigger), vol.Optional(CONF_ABOVE): vol.Coerce(float), vol.Optional(CONF_BELOW): vol.Coerce(float), diff --git a/esphomeyaml/components/switch/remote_transmitter.py b/esphomeyaml/components/switch/remote_transmitter.py index 78e523f12..f7c25617d 100644 --- a/esphomeyaml/components/switch/remote_transmitter.py +++ b/esphomeyaml/components/switch/remote_transmitter.py @@ -22,6 +22,8 @@ PanasonicTransmitter = remote_ns.PanasonicTransmitter RawTransmitter = remote_ns.RawTransmitter SonyTransmitter = remote_ns.SonyTransmitter +validate_raw_data = [vol.Any(vol.Coerce(int), cv.time_period_microseconds)] + PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_LG): vol.Schema({ vol.Required(CONF_DATA): cv.hex_uint32_t, @@ -39,10 +41,10 @@ PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ vol.Required(CONF_ADDRESS): cv.hex_uint16_t, vol.Required(CONF_COMMAND): cv.hex_uint32_t, }), - vol.Optional(CONF_RAW): vol.Schema({ - vol.Required(CONF_DATA): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)], + vol.Optional(CONF_RAW): vol.Any(validate_raw_data, vol.Schema({ + vol.Required(CONF_DATA): validate_raw_data, vol.Optional(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)), - }), + })), vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({ vol.Required(CONF_TIMES): cv.positive_not_null_int, vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds, @@ -69,8 +71,14 @@ def transmitter_base(config): return SonyTransmitter.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS]) elif CONF_RAW in config: conf = config[CONF_RAW] - data = ArrayInitializer(*conf[CONF_DATA]) - return RawTransmitter.new(data, conf[CONF_CARRIER_FREQUENCY]) + if isinstance(conf, dict): + data = conf[CONF_DATA] + carrier_frequency = conf.get(CONF_CARRIER_FREQUENCY) + else: + data = conf + carrier_frequency = None + return RawTransmitter.new(config[CONF_NAME], ArrayInitializer(*data, multiline=False), + carrier_frequency) else: raise ValueError("Unknown transmitter type {}".format(config)) diff --git a/esphomeyaml/components/switch/template.py b/esphomeyaml/components/switch/template.py index 811b3b934..515159df8 100644 --- a/esphomeyaml/components/switch/template.py +++ b/esphomeyaml/components/switch/template.py @@ -14,8 +14,8 @@ PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSwitch), vol.Optional(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_OPTIMISTIC): cv.boolean, - vol.Optional(CONF_TURN_OFF_ACTION): automation.ACTIONS_SCHEMA, - vol.Optional(CONF_TURN_ON_ACTION): automation.ACTIONS_SCHEMA, + vol.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(), + vol.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(), }), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) @@ -30,15 +30,11 @@ def to_code(config): yield add(make.Ptemplate_.set_state_lambda(template_)) if CONF_TURN_OFF_ACTION in config: - actions = None - for actions in automation.build_actions(config[CONF_TURN_OFF_ACTION], NoArg): - yield - add(make.Ptemplate_.add_turn_off_actions(actions)) + automation.build_automation(make.Ptemplate_.get_turn_off_trigger(), NoArg, + config[CONF_TURN_OFF_ACTION]) if CONF_TURN_ON_ACTION in config: - actions = None - for actions in automation.build_actions(config[CONF_TURN_ON_ACTION], NoArg): - yield - add(make.Ptemplate_.add_turn_on_actions(actions)) + automation.build_automation(make.Ptemplate_.get_turn_on_trigger(), NoArg, + config[CONF_TURN_ON_ACTION]) if CONF_OPTIMISTIC in config: add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC])) diff --git a/esphomeyaml/config.json b/esphomeyaml/config.json index 04163e561..92bcbbe83 100644 --- a/esphomeyaml/config.json +++ b/esphomeyaml/config.json @@ -11,11 +11,6 @@ "6052/tcp": 6052, "6053/tcp": 6053 }, - "arch": [ - "amd64", - "armhf", - "i386" - ], "auto_uart": true, "map": [ "config:rw" diff --git a/esphomeyaml/config.py b/esphomeyaml/config.py index e109e0904..8b08a44a8 100644 --- a/esphomeyaml/config.py +++ b/esphomeyaml/config.py @@ -32,11 +32,11 @@ CORE_SCHEMA = vol.Schema({ vol.Optional(CONF_SIMPLIFY, default=True): cv.boolean, vol.Optional(CONF_USE_BUILD_FLAGS, default=True): cv.boolean, vol.Optional(CONF_BOARD_FLASH_MODE): vol.All(vol.Lower, cv.one_of(*BUILD_FLASH_MODES)), - vol.Optional(CONF_ON_BOOT): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_BOOT): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(StartupTrigger), vol.Optional(CONF_PRIORITY): vol.Coerce(float), })]), - vol.Optional(CONF_ON_SHUTDOWN): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({ + vol.Optional(CONF_ON_SHUTDOWN): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ShutdownTrigger), })]), })