diff --git a/Dockerfile b/Dockerfile index 147a473926..04dcc81eee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,8 @@ VOLUME /config WORKDIR /usr/src/app COPY requirements.txt /usr/src/app/ -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r requirements.txt && \ + pip install --no-cache-dir tornado esptool COPY docker/platformio.ini /usr/src/app/ RUN platformio settings set enable_telemetry No && \ diff --git a/esphomeyaml/automation.py b/esphomeyaml/automation.py index cdd4670bb5..9dd9da14a6 100644 --- a/esphomeyaml/automation.py +++ b/esphomeyaml/automation.py @@ -33,7 +33,7 @@ ACTION_KEYS = [CONF_DELAY, CONF_MQTT_PUBLISH, CONF_LIGHT_TOGGLE, CONF_LIGHT_TURN ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ cv.GenerateID('action', CONF_ACTION_ID): cv.register_variable_id, - vol.Optional(CONF_DELAY): cv.positive_time_period_milliseconds, + vol.Optional(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds), vol.Optional(CONF_MQTT_PUBLISH): vol.Schema({ vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), vol.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload), @@ -50,8 +50,10 @@ ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ }), vol.Optional(CONF_LIGHT_TURN_ON): vol.Schema({ vol.Required(CONF_ID): cv.variable_id, - vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), - vol.Optional(CONF_FLASH_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), + vol.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'): + cv.templatable(cv.positive_time_period_milliseconds), + vol.Exclusive(CONF_FLASH_LENGTH, 'transformer'): + cv.templatable(cv.positive_time_period_milliseconds), vol.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage), vol.Optional(CONF_RED): cv.templatable(cv.percentage), vol.Optional(CONF_GREEN): cv.templatable(cv.percentage), diff --git a/esphomeyaml/components/binary_sensor/__init__.py b/esphomeyaml/components/binary_sensor/__init__.py index e96de8bec7..ec905d68f8 100644 --- a/esphomeyaml/components/binary_sensor/__init__.py +++ b/esphomeyaml/components/binary_sensor/__init__.py @@ -62,7 +62,7 @@ def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config): automation.build_automation(trigger, NoArg, conf) for conf in config.get(CONF_ON_CLICK, []): - rhs = binary_sensor_var.make_release_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH]) + rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH]) trigger = Pvariable(ClickTrigger, conf[CONF_TRIGGER_ID], rhs) automation.build_automation(trigger, NoArg, conf) diff --git a/esphomeyaml/components/cover/template.py b/esphomeyaml/components/cover/template.py index ffb4f2406c..afcaee117f 100644 --- a/esphomeyaml/components/cover/template.py +++ b/esphomeyaml/components/cover/template.py @@ -20,10 +20,12 @@ MakeTemplateCover = Application.MakeTemplateCover def to_code(config): - template_ = process_lambda(config.get(CONF_LAMBDA), []) - rhs = App.make_template_cover(config[CONF_NAME], template_) + rhs = App.make_template_cover(config[CONF_NAME]) make = variable(MakeTemplateCover, config[CONF_MAKE_ID], rhs) + if CONF_LAMBDA in config: + template_ = process_lambda(config[CONF_LAMBDA], []) + add(make.Ptemplate.set_state_lambda(template_)) if CONF_OPEN_ACTION in config: actions = automation.build_actions(config[CONF_OPEN_ACTION], NoArg) add(make.Ptemplate_.add_open_actions(actions)) diff --git a/esphomeyaml/components/output/ledc.py b/esphomeyaml/components/output/ledc.py index fbcb73799a..dbe4344114 100644 --- a/esphomeyaml/components/output/ledc.py +++ b/esphomeyaml/components/output/ledc.py @@ -20,7 +20,7 @@ def validate_frequency_bit_depth(obj): PLATFORM_SCHEMA = vol.All(output.PLATFORM_SCHEMA.extend({ - vol.Required(CONF_PIN): vol.All(pins.output_pin, vol.Range(min=0, max=33)), + vol.Required(CONF_PIN): pins.output_pin, vol.Optional(CONF_FREQUENCY): cv.frequency, vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)), vol.Optional(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15)) diff --git a/esphomeyaml/components/switch/template.py b/esphomeyaml/components/switch/template.py index 47d0c10fb7..8f073da848 100644 --- a/esphomeyaml/components/switch/template.py +++ b/esphomeyaml/components/switch/template.py @@ -19,10 +19,12 @@ MakeTemplateSwitch = Application.MakeTemplateSwitch def to_code(config): - template_ = process_lambda(config.get(CONF_LAMBDA), []) - rhs = App.make_template_switch(config[CONF_NAME], template_) + rhs = App.make_template_switch(config[CONF_NAME]) make = variable(MakeTemplateSwitch, config[CONF_MAKE_ID], rhs) + if CONF_LAMBDA in config: + template_ = process_lambda(config[CONF_LAMBDA], []) + add(make.Ptemplate.set_state_lambda(template_)) if CONF_TURN_OFF_ACTION in config: actions = automation.build_actions(config[CONF_TURN_OFF_ACTION], NoArg) add(make.Ptemplate_.add_turn_off_actions(actions)) diff --git a/esphomeyaml/config.py b/esphomeyaml/config.py index e843f95d2d..644bf8dd3a 100644 --- a/esphomeyaml/config.py +++ b/esphomeyaml/config.py @@ -222,14 +222,18 @@ def load_config(path): if CONF_ESPHOMEYAML not in config: raise ESPHomeYAMLError(u"No esphomeyaml section in config") core_conf = config[CONF_ESPHOMEYAML] - esp_platform = unicode(core_conf.get(CONF_PLATFORM, u"")) + 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 - core.BOARD = unicode(core_conf.get(CONF_BOARD, u"")) + 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: diff --git a/esphomeyaml/config_validation.py b/esphomeyaml/config_validation.py index 4b86d353bb..95298a69fb 100644 --- a/esphomeyaml/config_validation.py +++ b/esphomeyaml/config_validation.py @@ -134,11 +134,20 @@ def int_(value): hex_int = vol.Coerce(hex_int_) -match_cpp_var_ = vol.Match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', msg=u"Must be a valid C++ variable name") def variable_id(value): - value = match_cpp_var_(value) + value = string(value) + if not value: + raise vol.Invalid("ID must not be empty") + if value[0].isdigit(): + raise vol.Invalid("First character in ID cannot be a digit.") + if '-' in value: + raise vol.Invalid("Dashes are not supported in IDs, please use underscores instead.") + for char in value: + if char != '_' and not char.isalnum(): + raise vol.Invalid(u"IDs must only consist of upper/lowercase characters and numbers." + u"The character '{}' cannot be used".format(char)) if value in RESERVED_IDS: raise vol.Invalid(u"ID {} is reserved internally and cannot be used".format(value)) return value diff --git a/esphomeyaml/dashboard/dashboard.py b/esphomeyaml/dashboard/dashboard.py index 9ce244a181..ac22c1545e 100644 --- a/esphomeyaml/dashboard/dashboard.py +++ b/esphomeyaml/dashboard/dashboard.py @@ -140,7 +140,8 @@ class DownloadBinaryRequestHandler(tornado.web.RequestHandler): class MainRequestHandler(tornado.web.RequestHandler): def get(self): - files = sorted([f for f in os.listdir(CONFIG_DIR) if f.endswith('.yaml')]) + files = sorted([f for f in os.listdir(CONFIG_DIR) if f.endswith('.yaml') and + not f.startswith('.')]) full_path_files = [os.path.join(CONFIG_DIR, f) for f in files] self.render("templates/index.html", files=files, full_path_files=full_path_files, version=const.__version__) diff --git a/esphomeyaml/dashboard/templates/index.html b/esphomeyaml/dashboard/templates/index.html index a6516510cd..903b5cb0f4 100644 --- a/esphomeyaml/dashboard/templates/index.html +++ b/esphomeyaml/dashboard/templates/index.html @@ -68,7 +68,8 @@ overflow: auto; line-height: 1.45; border-radius: 3px; - word-wrap: normal; + white-space: pre-wrap; + overflow-wrap: break-word; color: #DDD; } @@ -125,10 +126,6 @@ height: 80% !important; } - .log { - - } - .page-footer { padding-top: 0; } diff --git a/esphomeyaml/helpers.py b/esphomeyaml/helpers.py index 8f8fb814f2..84e99d5d8b 100644 --- a/esphomeyaml/helpers.py +++ b/esphomeyaml/helpers.py @@ -408,7 +408,9 @@ def get_variable(id, type=None): return None result = get_result() if result is None: - raise ESPHomeYAMLError(u"Couldn't find ID '{}' with type {}".format(id, type)) + 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