mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-22 11:43:51 +01:00 
			
		
		
		
	Updates
This commit is contained in:
		| @@ -4,7 +4,7 @@ python: | |||||||
|   - "2.7" |   - "2.7" | ||||||
| install: | install: | ||||||
|   - pip install -r requirements.txt |   - pip install -r requirements.txt | ||||||
|   - pip install tornado esptool flake8==3.5.0 pylint==1.8.4 |   - pip install tornado esptool flake8==3.5.0 pylint==1.8.4 tzlocal pillow | ||||||
| script: | script: | ||||||
|  - flake8 esphomeyaml |  - flake8 esphomeyaml | ||||||
|  - pylint esphomeyaml |  - pylint esphomeyaml | ||||||
|   | |||||||
| @@ -7,11 +7,11 @@ import random | |||||||
| import sys | import sys | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
|  |  | ||||||
| from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util | from esphomeyaml import const, core, core_config, mqtt, wizard, writer, yaml_util | ||||||
| from esphomeyaml.config import core_to_code, get_component, iter_components, read_config | from esphomeyaml.config import get_component, iter_components, read_config | ||||||
| from esphomeyaml.const import CONF_BAUD_RATE, CONF_BUILD_PATH, CONF_DOMAIN, CONF_ESPHOMEYAML, \ | from esphomeyaml.const import CONF_BAUD_RATE, CONF_BUILD_PATH, CONF_DOMAIN, CONF_ESPHOMEYAML, \ | ||||||
|     CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, \ |     CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \ | ||||||
|     ESP_PLATFORM_ESP8266 |     CONF_WIFI, ESP_PLATFORM_ESP8266 | ||||||
| from esphomeyaml.core import ESPHomeYAMLError | from esphomeyaml.core import ESPHomeYAMLError | ||||||
| from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \ | from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \ | ||||||
|     add_job, color, flush_tasks, indent, quote, statement |     add_job, color, flush_tasks, indent, quote, statement | ||||||
| @@ -123,7 +123,7 @@ def run_miniterm(config, port, escape=False): | |||||||
| def write_cpp(config): | def write_cpp(config): | ||||||
|     _LOGGER.info("Generating C++ source...") |     _LOGGER.info("Generating C++ source...") | ||||||
|  |  | ||||||
|     add_job(core_to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml') |     add_job(core_config.to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml') | ||||||
|     for domain in PRE_INITIALIZE: |     for domain in PRE_INITIALIZE: | ||||||
|         if domain == CONF_ESPHOMEYAML or domain not in config: |         if domain == CONF_ESPHOMEYAML or domain not in config: | ||||||
|             continue |             continue | ||||||
| @@ -139,7 +139,7 @@ def write_cpp(config): | |||||||
|     add(RawStatement('')) |     add(RawStatement('')) | ||||||
|     all_code = [] |     all_code = [] | ||||||
|     for exp in _EXPRESSIONS: |     for exp in _EXPRESSIONS: | ||||||
|         if core.SIMPLIFY: |         if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]: | ||||||
|             if isinstance(exp, Expression) and not exp.required: |             if isinstance(exp, Expression) and not exp.required: | ||||||
|                 continue |                 continue | ||||||
|             if isinstance(exp, AssignmentExpression) and not exp.obj.required: |             if isinstance(exp, AssignmentExpression) and not exp.obj.required: | ||||||
| @@ -302,7 +302,7 @@ def command_compile(args, config): | |||||||
|         return exit_code |         return exit_code | ||||||
|     if args.only_generate: |     if args.only_generate: | ||||||
|         _LOGGER.info(u"Successfully generated source code.") |         _LOGGER.info(u"Successfully generated source code.") | ||||||
|         return 0; |         return 0 | ||||||
|     exit_code = compile_program(args, config) |     exit_code = compile_program(args, config) | ||||||
|     if exit_code != 0: |     if exit_code != 0: | ||||||
|         return exit_code |         return exit_code | ||||||
| @@ -388,10 +388,11 @@ def parse_args(argv): | |||||||
|     subparsers.required = True |     subparsers.required = True | ||||||
|     subparsers.add_parser('config', help='Validate the configuration and spit it out.') |     subparsers.add_parser('config', help='Validate the configuration and spit it out.') | ||||||
|  |  | ||||||
|     parser_compile = subparsers.add_parser('compile', help='Read the configuration and compile a program.') |     parser_compile = subparsers.add_parser('compile', | ||||||
|  |                                            help='Read the configuration and compile a program.') | ||||||
|     parser_compile.add_argument('--only-generate', |     parser_compile.add_argument('--only-generate', | ||||||
|                                help="Only generate source code, do not compile.", |                                 help="Only generate source code, do not compile.", | ||||||
|                                action='store_true') |                                 action='store_true') | ||||||
|  |  | ||||||
|     parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' |     parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' | ||||||
|                                                          'and upload the latest binary.') |                                                          'and upload the latest binary.') | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ from esphomeyaml import automation | |||||||
| from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INTERNAL, CONF_INVERTED, \ | from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INTERNAL, CONF_INVERTED, \ | ||||||
|     CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, \ |     CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, \ | ||||||
|     CONF_ON_PRESS, CONF_ON_RELEASE, CONF_TRIGGER_ID, CONF_FILTERS, CONF_INVERT, CONF_DELAYED_ON, \ |     CONF_ON_PRESS, CONF_ON_RELEASE, CONF_TRIGGER_ID, CONF_FILTERS, CONF_INVERT, CONF_DELAYED_ON, \ | ||||||
|     CONF_DELAYED_OFF, CONF_LAMBDA |     CONF_DELAYED_OFF, CONF_LAMBDA, CONF_HEARTBEAT | ||||||
| from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \ | from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \ | ||||||
|     setup_mqtt_component, bool_, process_lambda, ArrayInitializer |     setup_mqtt_component, bool_, process_lambda, ArrayInitializer | ||||||
|  |  | ||||||
| @@ -30,6 +30,7 @@ InvertFilter = binary_sensor_ns.InvertFilter | |||||||
| LambdaFilter = binary_sensor_ns.LambdaFilter | LambdaFilter = binary_sensor_ns.LambdaFilter | ||||||
| DelayedOnFilter = binary_sensor_ns.DelayedOnFilter | DelayedOnFilter = binary_sensor_ns.DelayedOnFilter | ||||||
| DelayedOffFilter = binary_sensor_ns.DelayedOffFilter | DelayedOffFilter = binary_sensor_ns.DelayedOffFilter | ||||||
|  | HeartbeatFilter = binary_sensor_ns.HeartbeatFilter | ||||||
| MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent | MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent | ||||||
|  |  | ||||||
| FILTER_KEYS = [CONF_INVERT, CONF_DELAYED_ON, CONF_DELAYED_OFF, CONF_LAMBDA] | FILTER_KEYS = [CONF_INVERT, CONF_DELAYED_ON, CONF_DELAYED_OFF, CONF_LAMBDA] | ||||||
| @@ -38,6 +39,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ | |||||||
|     vol.Optional(CONF_INVERT): None, |     vol.Optional(CONF_INVERT): None, | ||||||
|     vol.Optional(CONF_DELAYED_ON): cv.positive_time_period_milliseconds, |     vol.Optional(CONF_DELAYED_ON): cv.positive_time_period_milliseconds, | ||||||
|     vol.Optional(CONF_DELAYED_OFF): cv.positive_time_period_milliseconds, |     vol.Optional(CONF_DELAYED_OFF): cv.positive_time_period_milliseconds, | ||||||
|  |     vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds, | ||||||
|     vol.Optional(CONF_LAMBDA): cv.lambda_, |     vol.Optional(CONF_LAMBDA): cv.lambda_, | ||||||
| }, cv.has_exactly_one_key(*FILTER_KEYS))]) | }, cv.has_exactly_one_key(*FILTER_KEYS))]) | ||||||
|  |  | ||||||
| @@ -82,6 +84,8 @@ def setup_filter(config): | |||||||
|         yield App.register_component(DelayedOffFilter.new(config[CONF_DELAYED_OFF])) |         yield App.register_component(DelayedOffFilter.new(config[CONF_DELAYED_OFF])) | ||||||
|     elif CONF_DELAYED_ON in config: |     elif CONF_DELAYED_ON in config: | ||||||
|         yield App.register_component(DelayedOnFilter.new(config[CONF_DELAYED_ON])) |         yield App.register_component(DelayedOnFilter.new(config[CONF_DELAYED_ON])) | ||||||
|  |     elif CONF_HEARTBEAT in config: | ||||||
|  |         yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT])) | ||||||
|     elif CONF_LAMBDA in config: |     elif CONF_LAMBDA in config: | ||||||
|         lambda_ = None |         lambda_ = None | ||||||
|         for lambda_ in process_lambda(config[CONF_LAMBDA], [(bool_, 'x')]): |         for lambda_ in process_lambda(config[CONF_LAMBDA], [(bool_, 'x')]): | ||||||
|   | |||||||
| @@ -1,6 +1,4 @@ | |||||||
| # coding=utf-8 | # coding=utf-8 | ||||||
| import os.path |  | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| import esphomeyaml.config_validation as cv | import esphomeyaml.config_validation as cv | ||||||
| @@ -8,7 +6,8 @@ from esphomeyaml import core | |||||||
| from esphomeyaml.components import display | from esphomeyaml.components import display | ||||||
| from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE | from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE | ||||||
| from esphomeyaml.core import HexInt | from esphomeyaml.core import HexInt | ||||||
| from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add | from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \ | ||||||
|  |     relative_path | ||||||
|  |  | ||||||
| DEPENDENCIES = ['display'] | DEPENDENCIES = ['display'] | ||||||
|  |  | ||||||
| @@ -57,17 +56,13 @@ def validate_pillow_installed(value): | |||||||
|  |  | ||||||
|  |  | ||||||
| def validate_truetype_file(value): | def validate_truetype_file(value): | ||||||
|     value = cv.string(value) |  | ||||||
|     path = os.path.join(os.path.dirname(core.CONFIG_PATH), value) |  | ||||||
|     if not os.path.isfile(path): |  | ||||||
|         raise vol.Invalid(u"Could not find file '{}'. Please make sure it exists.".format(path)) |  | ||||||
|     if value.endswith('.zip'):  # for Google Fonts downloads |     if value.endswith('.zip'):  # for Google Fonts downloads | ||||||
|         raise vol.Invalid(u"Please unzip the font archive '{}' first and then use the .ttf files " |         raise vol.Invalid(u"Please unzip the font archive '{}' first and then use the .ttf files " | ||||||
|                           u"inside.".format(value)) |                           u"inside.".format(value)) | ||||||
|     if not value.endswith('.ttf'): |     if not value.endswith('.ttf'): | ||||||
|         raise vol.Invalid(u"Only truetype (.ttf) files are supported. Please make sure you're " |         raise vol.Invalid(u"Only truetype (.ttf) files are supported. Please make sure you're " | ||||||
|                           u"using the correct format or rename the extension to .ttf") |                           u"using the correct format or rename the extension to .ttf") | ||||||
|     return value |     return cv.file_(value) | ||||||
|  |  | ||||||
|  |  | ||||||
| DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' | DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' | ||||||
| @@ -88,7 +83,7 @@ def to_code(config): | |||||||
|     from PIL import ImageFont |     from PIL import ImageFont | ||||||
|  |  | ||||||
|     for conf in config: |     for conf in config: | ||||||
|         path = os.path.join(os.path.dirname(core.CONFIG_PATH), conf[CONF_FILE]) |         path = relative_path(conf[CONF_FILE]) | ||||||
|         try: |         try: | ||||||
|             font = ImageFont.truetype(path, conf[CONF_SIZE]) |             font = ImageFont.truetype(path, conf[CONF_SIZE]) | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| # coding=utf-8 | # coding=utf-8 | ||||||
| import logging | import logging | ||||||
| import os.path |  | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| @@ -9,7 +8,8 @@ from esphomeyaml import core | |||||||
| from esphomeyaml.components import display, font | from esphomeyaml.components import display, font | ||||||
| from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE | from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE | ||||||
| from esphomeyaml.core import HexInt | from esphomeyaml.core import HexInt | ||||||
| from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add | from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \ | ||||||
|  |     relative_path | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -17,20 +17,11 @@ DEPENDENCIES = ['display'] | |||||||
|  |  | ||||||
| Image_ = display.display_ns.Image | Image_ = display.display_ns.Image | ||||||
|  |  | ||||||
|  |  | ||||||
| def validate_image_file(value): |  | ||||||
|     value = cv.string(value) |  | ||||||
|     path = os.path.join(os.path.dirname(core.CONFIG_PATH), value) |  | ||||||
|     if not os.path.isfile(path): |  | ||||||
|         raise vol.Invalid(u"Could not find file '{}'. Please make sure it exists.".format(path)) |  | ||||||
|     return value |  | ||||||
|  |  | ||||||
|  |  | ||||||
| CONF_RAW_DATA_ID = 'raw_data_id' | CONF_RAW_DATA_ID = 'raw_data_id' | ||||||
|  |  | ||||||
| IMAGE_SCHEMA = vol.Schema({ | IMAGE_SCHEMA = vol.Schema({ | ||||||
|     vol.Required(CONF_ID): cv.declare_variable_id(Image_), |     vol.Required(CONF_ID): cv.declare_variable_id(Image_), | ||||||
|     vol.Required(CONF_FILE): validate_image_file, |     vol.Required(CONF_FILE): cv.file_, | ||||||
|     vol.Optional(CONF_RESIZE): cv.dimensions, |     vol.Optional(CONF_RESIZE): cv.dimensions, | ||||||
|     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None), |     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None), | ||||||
| }) | }) | ||||||
| @@ -42,7 +33,7 @@ def to_code(config): | |||||||
|     from PIL import Image |     from PIL import Image | ||||||
|  |  | ||||||
|     for conf in config: |     for conf in config: | ||||||
|         path = os.path.join(os.path.dirname(core.CONFIG_PATH), conf[CONF_FILE]) |         path = relative_path(conf[CONF_FILE]) | ||||||
|         try: |         try: | ||||||
|             image = Image.open(path) |             image = Image.open(path) | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|   | |||||||
| @@ -5,9 +5,10 @@ import math | |||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| import esphomeyaml.config_validation as cv | import esphomeyaml.config_validation as cv | ||||||
| from esphomeyaml.const import CONF_TIMEZONE | from esphomeyaml import automation | ||||||
| from esphomeyaml.helpers import add, add_job, esphomelib_ns | from esphomeyaml.const import CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, CONF_HOURS, \ | ||||||
|  |     CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_SECONDS, CONF_TIMEZONE, CONF_TRIGGER_ID | ||||||
|  | from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -16,6 +17,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
| time_ns = esphomelib_ns.namespace('time') | time_ns = esphomelib_ns.namespace('time') | ||||||
|  | CronTrigger = time_ns.CronTrigger | ||||||
|  |  | ||||||
|  |  | ||||||
| def _tz_timedelta(td): | def _tz_timedelta(td): | ||||||
| @@ -117,14 +119,155 @@ def detect_tz(): | |||||||
|     return tzbase + tzext |     return tzbase + tzext | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _parse_cron_int(value, special_mapping, message): | ||||||
|  |     special_mapping = special_mapping or {} | ||||||
|  |     if isinstance(value, (str, unicode)) and value in special_mapping: | ||||||
|  |         return special_mapping[value] | ||||||
|  |     try: | ||||||
|  |         return int(value) | ||||||
|  |     except ValueError: | ||||||
|  |         raise vol.Invalid(message.format(value)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _parse_cron_part(part, min_value, max_value, special_mapping): | ||||||
|  |     if part == '*' or part == '?': | ||||||
|  |         return set(x for x in range(min_value, max_value + 1)) | ||||||
|  |     if '/' in part: | ||||||
|  |         data = part.split('/') | ||||||
|  |         if len(data) > 2: | ||||||
|  |             raise vol.Invalid(u"Can't have more than two '/' in one time expression, got {}" | ||||||
|  |                               .format(part)) | ||||||
|  |         offset, repeat = data | ||||||
|  |         offset_n = 0 | ||||||
|  |         if offset: | ||||||
|  |             offset_n = _parse_cron_int(offset, special_mapping, | ||||||
|  |                                        u"Offset for '/' time expression must be an integer, got {}") | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             repeat_n = int(repeat) | ||||||
|  |         except ValueError: | ||||||
|  |             raise vol.Invalid(u"Repeat for '/' time expression must be an integer, got {}" | ||||||
|  |                               .format(repeat)) | ||||||
|  |         return set(x for x in range(offset_n, max_value + 1, repeat_n)) | ||||||
|  |     if '-' in part: | ||||||
|  |         data = part.split('-') | ||||||
|  |         if len(data) > 2: | ||||||
|  |             raise vol.Invalid(u"Can't have more than two '-' in range time expression '{}'" | ||||||
|  |                               .format(part)) | ||||||
|  |         begin, end = data | ||||||
|  |         begin_n = _parse_cron_int(begin, special_mapping, u"Number for time range must be integer, " | ||||||
|  |                                                           u"got {}") | ||||||
|  |         end_n = _parse_cron_int(end, special_mapping, u"Number for time range must be integer, " | ||||||
|  |                                                       u"got {}") | ||||||
|  |         if end_n < begin_n: | ||||||
|  |             return set(x for x in range(end_n, max_value + 1)) | \ | ||||||
|  |                    set(x for x in range(min_value, begin_n + 1)) | ||||||
|  |         return set(x for x in range(begin_n, end_n + 1)) | ||||||
|  |  | ||||||
|  |     return {_parse_cron_int(part, special_mapping, u"Number for time expression must be an " | ||||||
|  |                                                    u"integer, got {}")} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def cron_expression_validator(name, min_value, max_value, special_mapping=None): | ||||||
|  |     def validator(value): | ||||||
|  |         if isinstance(value, list): | ||||||
|  |             for v in value: | ||||||
|  |                 if not isinstance(v, int): | ||||||
|  |                     raise vol.Invalid( | ||||||
|  |                         "Expected integer for {} '{}', got {}".format(v, name, type(v))) | ||||||
|  |                 if v < min_value or v > max_value: | ||||||
|  |                     raise vol.Invalid( | ||||||
|  |                         "{} {} is out of range (min={} max={}).".format(name, v, min_value, | ||||||
|  |                                                                         max_value)) | ||||||
|  |             return list(sorted(value)) | ||||||
|  |         value = cv.string(value) | ||||||
|  |         values = set() | ||||||
|  |         for part in value.split(','): | ||||||
|  |             values |= _parse_cron_part(part, min_value, max_value, special_mapping) | ||||||
|  |         return validator(list(values)) | ||||||
|  |  | ||||||
|  |     return validator | ||||||
|  |  | ||||||
|  |  | ||||||
|  | validate_cron_seconds = cron_expression_validator('seconds', 0, 60) | ||||||
|  | validate_cron_minutes = cron_expression_validator('minutes', 0, 59) | ||||||
|  | validate_cron_hours = cron_expression_validator('hours', 0, 23) | ||||||
|  | validate_cron_days_of_month = cron_expression_validator('days of month', 1, 31) | ||||||
|  | validate_cron_months = cron_expression_validator('months', 1, 12, { | ||||||
|  |     'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6, 'JUL': 7, 'AUG': 8, | ||||||
|  |     'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12 | ||||||
|  | }) | ||||||
|  | validate_cron_days_of_week = cron_expression_validator('days of week', 1, 7, { | ||||||
|  |     'SUN': 1, 'MON': 2, 'TUE': 3, 'WED': 4, 'THU': 5, 'FRI': 6, 'SAT': 7 | ||||||
|  | }) | ||||||
|  | CRON_KEYS = [CONF_SECONDS, CONF_MINUTES, CONF_HOURS, CONF_DAYS_OF_MONTH, CONF_MONTHS, | ||||||
|  |              CONF_DAYS_OF_WEEK] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_cron_raw(value): | ||||||
|  |     value = cv.string(value) | ||||||
|  |     value = value.split(' ') | ||||||
|  |     if len(value) != 6: | ||||||
|  |         raise vol.Invalid("Cron expression must consist of exactly 6 space-separated parts, " | ||||||
|  |                           "not {}".format(len(value))) | ||||||
|  |     seconds, minutes, hours, days_of_month, months, days_of_week = value | ||||||
|  |     return { | ||||||
|  |         CONF_SECONDS: validate_cron_seconds(seconds), | ||||||
|  |         CONF_MINUTES: validate_cron_minutes(minutes), | ||||||
|  |         CONF_HOURS: validate_cron_hours(hours), | ||||||
|  |         CONF_DAYS_OF_MONTH: validate_cron_days_of_month(days_of_month), | ||||||
|  |         CONF_MONTHS: validate_cron_months(months), | ||||||
|  |         CONF_DAYS_OF_WEEK: validate_cron_days_of_week(days_of_week), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_cron_keys(value): | ||||||
|  |     if CONF_CRON in value: | ||||||
|  |         for key in value.keys(): | ||||||
|  |             if key in CRON_KEYS: | ||||||
|  |                 raise vol.Invalid("Cannot use option {} when cron: is specified.".format(key)) | ||||||
|  |         cron_ = value[CONF_CRON] | ||||||
|  |         value = {x: value[x] for x in value if x != CONF_CRON} | ||||||
|  |         value.update(cron_) | ||||||
|  |         return value | ||||||
|  |     return cv.has_at_least_one_key(*CRON_KEYS)(value) | ||||||
|  |  | ||||||
|  |  | ||||||
| TIME_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | TIME_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||||||
|     vol.Optional(CONF_TIMEZONE, default=detect_tz): cv.string, |     vol.Optional(CONF_TIMEZONE, default=detect_tz): cv.string, | ||||||
|  |     vol.Optional(CONF_ON_TIME): vol.All(cv.ensure_list, [vol.All(automation.validate_automation({ | ||||||
|  |         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(CronTrigger), | ||||||
|  |         vol.Optional(CONF_SECONDS): validate_cron_seconds, | ||||||
|  |         vol.Optional(CONF_MINUTES): validate_cron_minutes, | ||||||
|  |         vol.Optional(CONF_HOURS): validate_cron_hours, | ||||||
|  |         vol.Optional(CONF_DAYS_OF_MONTH): validate_cron_days_of_month, | ||||||
|  |         vol.Optional(CONF_MONTHS): validate_cron_months, | ||||||
|  |         vol.Optional(CONF_DAYS_OF_WEEK): validate_cron_days_of_week, | ||||||
|  |         vol.Optional(CONF_CRON): validate_cron_raw, | ||||||
|  |     }), validate_cron_keys)]), | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  |  | ||||||
| def setup_time_core_(time_var, config): | def setup_time_core_(time_var, config): | ||||||
|     add(time_var.set_timezone(config[CONF_TIMEZONE])) |     add(time_var.set_timezone(config[CONF_TIMEZONE])) | ||||||
|  |  | ||||||
|  |     for conf in config.get(CONF_ON_TIME, []): | ||||||
|  |         rhs = App.register_component(time_var.Pmake_cron_trigger()) | ||||||
|  |         trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) | ||||||
|  |         for second in conf.get(CONF_SECONDS, [x for x in range(0, 61)]): | ||||||
|  |             add(trigger.add_second(second)) | ||||||
|  |         for minute in conf.get(CONF_MINUTES, [x for x in range(0, 60)]): | ||||||
|  |             add(trigger.add_minute(minute)) | ||||||
|  |         for hour in conf.get(CONF_HOURS, [x for x in range(0, 24)]): | ||||||
|  |             add(trigger.add_hour(hour)) | ||||||
|  |         for day_of_month in conf.get(CONF_DAYS_OF_MONTH, [x for x in range(1, 32)]): | ||||||
|  |             add(trigger.add_day_of_month(day_of_month)) | ||||||
|  |         for month in conf.get(CONF_MONTHS, [x for x in range(1, 13)]): | ||||||
|  |             add(trigger.add_month(month)) | ||||||
|  |         for day_of_week in conf.get(CONF_DAYS_OF_WEEK, [x for x in range(1, 8)]): | ||||||
|  |             add(trigger.add_day_of_week(day_of_week)) | ||||||
|  |         automation.build_automation(trigger, NoArg, conf) | ||||||
|  |  | ||||||
|  |  | ||||||
| def setup_time(time_var, config): | def setup_time(time_var, config): | ||||||
|     add_job(setup_time_core_, time_var, config) |     add_job(setup_time_core_, time_var, config) | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ from esphomeyaml.helpers import App, Pvariable | |||||||
| SNTPComponent = time_.time_ns.SNTPComponent | SNTPComponent = time_.time_ns.SNTPComponent | ||||||
|  |  | ||||||
| PLATFORM_SCHEMA = time_.TIME_PLATFORM_SCHEMA.extend({ | PLATFORM_SCHEMA = time_.TIME_PLATFORM_SCHEMA.extend({ | ||||||
|     vol.Required(CONF_ID): cv.declare_variable_id(SNTPComponent), |     cv.GenerateID(): cv.declare_variable_id(SNTPComponent), | ||||||
|     vol.Optional(CONF_SERVERS): vol.All(cv.ensure_list, [cv.string], vol.Length(max=3)), |     vol.Optional(CONF_SERVERS): vol.All(cv.ensure_list, [cv.string], vol.Length(max=3)), | ||||||
|     vol.Optional(CONF_LAMBDA): cv.lambda_, |     vol.Optional(CONF_LAMBDA): cv.lambda_, | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -7,62 +7,20 @@ from collections import OrderedDict | |||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
| from voluptuous.humanize import humanize_error | from voluptuous.humanize import humanize_error | ||||||
|  |  | ||||||
| import esphomeyaml.config_validation as cv | from esphomeyaml import core, yaml_util, core_config | ||||||
| from esphomeyaml import core, yaml_util, automation | from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, CONF_WIFI, ESP_PLATFORMS | ||||||
| from esphomeyaml.const import CONF_BOARD, CONF_BOARD_FLASH_MODE, CONF_ESPHOMEYAML, \ |  | ||||||
|     CONF_LIBRARY_URI, CONF_NAME, CONF_PLATFORM, CONF_SIMPLIFY, CONF_USE_BUILD_FLAGS, CONF_WIFI, \ |  | ||||||
|     ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, CONF_ON_BOOT, CONF_TRIGGER_ID, \ |  | ||||||
|     CONF_PRIORITY, CONF_ON_SHUTDOWN, CONF_BUILD_PATH |  | ||||||
| from esphomeyaml.core import ESPHomeYAMLError | from esphomeyaml.core import ESPHomeYAMLError | ||||||
| from esphomeyaml.helpers import App, add, color, esphomelib_ns, Pvariable, NoArg, const_char_p | from esphomeyaml.helpers import color | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.7.0' |  | ||||||
|  |  | ||||||
| BUILD_FLASH_MODES = ['qio', 'qout', 'dio', 'dout'] |  | ||||||
| StartupTrigger = esphomelib_ns.StartupTrigger |  | ||||||
| ShutdownTrigger = esphomelib_ns.ShutdownTrigger |  | ||||||
|  |  | ||||||
| CORE_SCHEMA = vol.Schema({ |  | ||||||
|     vol.Required(CONF_NAME): cv.valid_name, |  | ||||||
|     vol.Required(CONF_PLATFORM): cv.string, |  | ||||||
|     vol.Required(CONF_BOARD): cv.string, |  | ||||||
|     vol.Optional(CONF_LIBRARY_URI, default=DEFAULT_LIBRARY_URI): cv.string, |  | ||||||
|     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.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.validate_automation({ |  | ||||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ShutdownTrigger), |  | ||||||
|     })]), |  | ||||||
|     vol.Optional(CONF_BUILD_PATH): cv.string, |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| REQUIRED_COMPONENTS = [ | REQUIRED_COMPONENTS = [ | ||||||
|     CONF_ESPHOMEYAML, CONF_WIFI |     CONF_ESPHOMEYAML, CONF_WIFI | ||||||
| ] | ] | ||||||
|  |  | ||||||
| _COMPONENT_CACHE = {} | _COMPONENT_CACHE = {} | ||||||
| _ALL_COMPONENTS = [] | _ALL_COMPONENTS = [] | ||||||
|  |  | ||||||
|  |  | ||||||
| def core_to_code(config): |  | ||||||
|     add(App.set_name(config[CONF_NAME])) |  | ||||||
|  |  | ||||||
|     for conf in config.get(CONF_ON_BOOT, []): |  | ||||||
|         rhs = App.register_component(StartupTrigger.new(conf.get(CONF_PRIORITY))) |  | ||||||
|         trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) |  | ||||||
|         automation.build_automation(trigger, NoArg, conf) |  | ||||||
|  |  | ||||||
|     for conf in config.get(CONF_ON_SHUTDOWN, []): |  | ||||||
|         trigger = Pvariable(conf[CONF_TRIGGER_ID], ShutdownTrigger.new()) |  | ||||||
|         automation.build_automation(trigger, const_char_p, conf) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_component(domain): | def get_component(domain): | ||||||
|     if domain in _COMPONENT_CACHE: |     if domain in _COMPONENT_CACHE: | ||||||
|         return _COMPONENT_CACHE[domain] |         return _COMPONENT_CACHE[domain] | ||||||
| @@ -171,9 +129,9 @@ def validate_config(config): | |||||||
|         result.add_error(_format_config_error(ex, domain, config), domain, config) |         result.add_error(_format_config_error(ex, domain, config), domain, config) | ||||||
|  |  | ||||||
|     try: |     try: | ||||||
|         result[CONF_ESPHOMEYAML] = CORE_SCHEMA(config[CONF_ESPHOMEYAML]) |         result[CONF_ESPHOMEYAML] = core_config.CONFIG_SCHEMA(config[CONF_ESPHOMEYAML]) | ||||||
|     except vol.Invalid as ex: |     except vol.Invalid as ex: | ||||||
|         _comp_error(ex, CONF_ESPHOMEYAML, config) |         _comp_error(ex, CONF_ESPHOMEYAML, config[CONF_ESPHOMEYAML]) | ||||||
|  |  | ||||||
|     for domain, conf in config.iteritems(): |     for domain, conf in config.iteritems(): | ||||||
|         domain = str(domain) |         domain = str(domain) | ||||||
| @@ -288,23 +246,7 @@ def load_config(path): | |||||||
|     except OSError: |     except OSError: | ||||||
|         raise ESPHomeYAMLError(u"Could not read configuration file at {}".format(path)) |         raise ESPHomeYAMLError(u"Could not read configuration file at {}".format(path)) | ||||||
|     core.RAW_CONFIG = config |     core.RAW_CONFIG = config | ||||||
|  |     core_config.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.") |  | ||||||
|     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: |     try: | ||||||
|         result = validate_config(config) |         result = validate_config(config) | ||||||
|   | |||||||
| @@ -3,12 +3,13 @@ | |||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
|  | import os | ||||||
| import re | import re | ||||||
| import uuid as uuid_ | import uuid as uuid_ | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| from esphomeyaml import core | from esphomeyaml import core, helpers | ||||||
| from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_ID, \ | from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_ID, \ | ||||||
|     CONF_NAME, CONF_PAYLOAD_AVAILABLE, \ |     CONF_NAME, CONF_PAYLOAD_AVAILABLE, \ | ||||||
|     CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \ |     CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \ | ||||||
| @@ -240,6 +241,19 @@ def has_exactly_one_key(*keys): | |||||||
|     return validate |     return validate | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def has_at_most_one_key(*keys): | ||||||
|  |     def validate(obj): | ||||||
|  |         if not isinstance(obj, dict): | ||||||
|  |             raise vol.Invalid('expected dictionary') | ||||||
|  |  | ||||||
|  |         number = sum(k in keys for k in obj) | ||||||
|  |         if number > 1: | ||||||
|  |             raise vol.Invalid("Cannot specify more than one of {}.".format(', '.join(keys))) | ||||||
|  |         return obj | ||||||
|  |  | ||||||
|  |     return validate | ||||||
|  |  | ||||||
|  |  | ||||||
| TIME_PERIOD_ERROR = "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h" | TIME_PERIOD_ERROR = "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h" | ||||||
|  |  | ||||||
| time_period_dict = vol.All( | time_period_dict = vol.All( | ||||||
| @@ -598,6 +612,28 @@ def dimensions(value): | |||||||
|     return dimensions([match.group(1), match.group(2)]) |     return dimensions([match.group(1), match.group(2)]) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def directory(value): | ||||||
|  |     value = string(value) | ||||||
|  |     path = helpers.relative_path(value) | ||||||
|  |     if not os.path.exists(path): | ||||||
|  |         raise vol.Invalid(u"Could not find directory '{}'. Please make sure it exists.".format( | ||||||
|  |             path)) | ||||||
|  |     if not os.path.isdir(path): | ||||||
|  |         raise vol.Invalid(u"Path '{}' is not a directory.".format(path)) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def file_(value): | ||||||
|  |     value = string(value) | ||||||
|  |     path = helpers.relative_path(value) | ||||||
|  |     if not os.path.exists(path): | ||||||
|  |         raise vol.Invalid(u"Could not find file '{}'. Please make sure it exists.".format( | ||||||
|  |             path)) | ||||||
|  |     if not os.path.isfile(path): | ||||||
|  |         raise vol.Invalid(u"Path '{}' is not a file.".format(path)) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
| REGISTERED_IDS = set() | REGISTERED_IDS = set() | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ MINOR_VERSION = 7 | |||||||
| PATCH_VERSION = '0' | PATCH_VERSION = '0' | ||||||
| __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) | __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) | ||||||
| __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) | __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) | ||||||
|  | ESPHOMELIB_VERSION = '1.7.0' | ||||||
|  |  | ||||||
| ESP_PLATFORM_ESP32 = 'ESP32' | ESP_PLATFORM_ESP32 = 'ESP32' | ||||||
| ESP_PLATFORM_ESP8266 = 'ESP8266' | ESP_PLATFORM_ESP8266 = 'ESP8266' | ||||||
| @@ -16,9 +17,14 @@ CONF_ESPHOMEYAML = 'esphomeyaml' | |||||||
| CONF_NAME = 'name' | CONF_NAME = 'name' | ||||||
| CONF_PLATFORM = 'platform' | CONF_PLATFORM = 'platform' | ||||||
| CONF_BOARD = 'board' | CONF_BOARD = 'board' | ||||||
| CONF_SIMPLIFY = 'simplify' | CONF_ESPHOMELIB_VERSION = 'esphomelib_version' | ||||||
| CONF_USE_BUILD_FLAGS = 'use_build_flags' | CONF_USE_CUSTOM_CODE = 'use_custom_code' | ||||||
| CONF_LIBRARY_URI = 'library_uri' | CONF_ARDUINO_VERSION = 'arduino_version' | ||||||
|  | CONF_LOCAL = 'local' | ||||||
|  | CONF_REPOSITORY = 'repository' | ||||||
|  | CONF_COMMIT = 'commit' | ||||||
|  | CONF_TAG = 'tag' | ||||||
|  | CONF_BRANCH = 'branch' | ||||||
| CONF_LOGGER = 'logger' | CONF_LOGGER = 'logger' | ||||||
| CONF_WIFI = 'wifi' | CONF_WIFI = 'wifi' | ||||||
| CONF_SSID = 'ssid' | CONF_SSID = 'ssid' | ||||||
| @@ -323,27 +329,17 @@ CONF_COLD_WHITE = 'cold_white' | |||||||
| CONF_WARM_WHITE = 'warm_white' | CONF_WARM_WHITE = 'warm_white' | ||||||
| CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature' | CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature' | ||||||
| CONF_WARM_WHITE_COLOR_TEMPERATURE = 'warm_white_color_temperature' | CONF_WARM_WHITE_COLOR_TEMPERATURE = 'warm_white_color_temperature' | ||||||
|  | CONF_ON_LOOP = 'on_loop' | ||||||
| ESP32_BOARDS = [ | CONF_ON_TIME = 'on_time' | ||||||
|     'featheresp32', 'node32s', 'espea32', 'firebeetle32', 'esp32doit-devkit-v1', | CONF_SECONDS = 'seconds' | ||||||
|     'pocket_32', 'espectro32', 'esp32vn-iot-uno', 'esp320', 'esp-wrover-kit', | CONF_MINUTES = 'minutes' | ||||||
|     'esp32dev', 'heltec_wifi_kit32', 'heltec_wifi_lora_32', 'hornbill32dev', | CONF_HOURS = 'hours' | ||||||
|     'hornbill32minima', 'intorobot', 'm5stack-core-esp32', 'mhetesp32devkit', | CONF_DAYS_OF_MONTH = 'days_of_month' | ||||||
|     'mhetesp32minikit', 'nano32', 'microduino-core-esp32', 'nodemcu-32s', | CONF_MONTHS = 'months' | ||||||
|     'quantum', 'esp32-evb', 'esp32-gateway', 'onehorse32dev', 'esp32thing', | CONF_DAYS_OF_WEEK = 'days_of_week' | ||||||
|     'espino32', 'lolin32', 'wemosbat', 'widora-air', 'nina_w10', | CONF_CRON = 'cron' | ||||||
| ] |  | ||||||
|  |  | ||||||
| ESP8266_BOARDS = [ |  | ||||||
|     'gen4iod', 'huzzah', 'oak', 'espduino', 'espectro', 'espresso_lite_v1', |  | ||||||
|     'espresso_lite_v2', 'espino', 'esp01', 'esp01_1m', 'esp07', 'esp12e', 'esp8285', |  | ||||||
|     'esp_wroom_02', 'phoenix_v1', 'phoenix_v2', 'wifinfo', 'heltex_wifi_kit_8', |  | ||||||
|     'nodemcu', 'nodemcuv2', 'modwifi', 'wio_node', 'sparkfunBlynk', 'thing', |  | ||||||
|     'thingdev', 'esp210', 'espinotee', 'd1', 'd1_mini', 'd1_mini_lite', 'd1_mini_pro', |  | ||||||
| ] |  | ||||||
| ESP_BOARDS_FOR_PLATFORM = { |  | ||||||
|     ESP_PLATFORM_ESP32: ESP32_BOARDS, |  | ||||||
|     ESP_PLATFORM_ESP8266: ESP8266_BOARDS |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' | ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' | ||||||
|  | ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' | ||||||
|  | ARDUINO_VERSION_ESP8266_DEV = 'https://github.com/platformio/platform-espressif8266.git#feature' \ | ||||||
|  |                               '/stage' | ||||||
|   | |||||||
| @@ -239,7 +239,6 @@ class ID(object): | |||||||
|  |  | ||||||
|  |  | ||||||
| CONFIG_PATH = None | CONFIG_PATH = None | ||||||
| SIMPLIFY = True |  | ||||||
| ESP_PLATFORM = '' | ESP_PLATFORM = '' | ||||||
| BOARD = '' | BOARD = '' | ||||||
| RAW_CONFIG = None | RAW_CONFIG = None | ||||||
|   | |||||||
							
								
								
									
										199
									
								
								esphomeyaml/core_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								esphomeyaml/core_config.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | |||||||
|  | import os | ||||||
|  | import re | ||||||
|  |  | ||||||
|  | import voluptuous as vol | ||||||
|  |  | ||||||
|  | import esphomeyaml.config_validation as cv | ||||||
|  | from esphomeyaml import automation, core, pins | ||||||
|  | from esphomeyaml.const import CONF_ARDUINO_VERSION, CONF_BOARD, CONF_BOARD_FLASH_MODE, \ | ||||||
|  |     CONF_BRANCH, CONF_BUILD_PATH, CONF_COMMIT, CONF_ESPHOMELIB_VERSION, CONF_ESPHOMEYAML, \ | ||||||
|  |     CONF_LOCAL, CONF_NAME, CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, CONF_PLATFORM, \ | ||||||
|  |     CONF_PRIORITY, CONF_REPOSITORY, CONF_TAG, CONF_TRIGGER_ID, CONF_USE_CUSTOM_CODE, \ | ||||||
|  |     ESPHOMELIB_VERSION, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, ARDUINO_VERSION_ESP8266_DEV, \ | ||||||
|  |     ARDUINO_VERSION_ESP32_DEV | ||||||
|  | from esphomeyaml.core import ESPHomeYAMLError | ||||||
|  | from esphomeyaml.helpers import App, NoArg, Pvariable, add, const_char_p, esphomelib_ns, \ | ||||||
|  |     relative_path | ||||||
|  |  | ||||||
|  | LIBRARY_URI_REPO = u'https://github.com/OttoWinter/esphomelib.git' | ||||||
|  |  | ||||||
|  | BUILD_FLASH_MODES = ['qio', 'qout', 'dio', 'dout'] | ||||||
|  | StartupTrigger = esphomelib_ns.StartupTrigger | ||||||
|  | ShutdownTrigger = esphomelib_ns.ShutdownTrigger | ||||||
|  | LoopTrigger = esphomelib_ns.LoopTrigger | ||||||
|  |  | ||||||
|  | VERSION_REGEX = re.compile(r'^[0-9]+\.[0-9]+\.[0-9]+(?:-beta)?(?:-alpha)?$') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_board(value): | ||||||
|  |     if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266: | ||||||
|  |         board_pins = pins.ESP8266_BOARD_PINS | ||||||
|  |     elif core.ESP_PLATFORM == ESP_PLATFORM_ESP32: | ||||||
|  |         board_pins = pins.ESP32_BOARD_PINS | ||||||
|  |     else: | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |     if value not in board_pins: | ||||||
|  |         raise vol.Invalid(u"Could not find board '{}'. Valid boards are {}".format( | ||||||
|  |             value, u', '.join(pins.ESP8266_BOARD_PINS.keys()))) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_simple_esphomelib_version(value): | ||||||
|  |     value = cv.string_strict(value) | ||||||
|  |     if value.upper() == 'LATEST': | ||||||
|  |         return LIBRARY_URI_REPO + '#v{}'.format(ESPHOMELIB_VERSION) | ||||||
|  |     elif value.upper() == 'DEV': | ||||||
|  |         return LIBRARY_URI_REPO | ||||||
|  |     elif VERSION_REGEX.match(value) is not None: | ||||||
|  |         return LIBRARY_URI_REPO + '#v{}'.format(value) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_local_esphomelib_version(value): | ||||||
|  |     value = cv.directory(value) | ||||||
|  |     path = relative_path(value) | ||||||
|  |     library_json = os.path.join(path, 'library.json') | ||||||
|  |     if not os.path.exists(library_json): | ||||||
|  |         raise vol.Invalid(u"Could not find '{}' file. '{}' does not seem to point to an " | ||||||
|  |                           u"esphomelib copy.".format(library_json, value)) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def convert_esphomelib_version_schema(value): | ||||||
|  |     if CONF_COMMIT in value: | ||||||
|  |         return value[CONF_REPOSITORY] + '#' + value[CONF_COMMIT] | ||||||
|  |     if CONF_BRANCH in value: | ||||||
|  |         return value[CONF_REPOSITORY] + '#' + value[CONF_BRANCH] | ||||||
|  |     return value[CONF_REPOSITORY] + '#' + value[CONF_TAG] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ESPHOMELIB_VERSION_SCHEMA = vol.Any( | ||||||
|  |     validate_simple_esphomelib_version, | ||||||
|  |     vol.Schema({ | ||||||
|  |         vol.Required(CONF_LOCAL): validate_local_esphomelib_version, | ||||||
|  |     }), | ||||||
|  |     vol.All( | ||||||
|  |         vol.Schema({ | ||||||
|  |             vol.Optional(CONF_REPOSITORY, default=LIBRARY_URI_REPO): cv.string, | ||||||
|  |             vol.Optional(CONF_COMMIT, 'tag'): cv.string, | ||||||
|  |             vol.Optional(CONF_BRANCH, 'tag'): cv.string, | ||||||
|  |             vol.Optional(CONF_TAG, 'tag'): cv.string, | ||||||
|  |         }), | ||||||
|  |         cv.has_at_most_one_key(CONF_COMMIT, CONF_BRANCH, CONF_TAG), | ||||||
|  |         convert_esphomelib_version_schema | ||||||
|  |     ), | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_platform(value): | ||||||
|  |     value = cv.string(value) | ||||||
|  |     if value.upper() in ('ESP8266', 'ESPRESSIF8266'): | ||||||
|  |         return ESP_PLATFORM_ESP8266 | ||||||
|  |     if value.upper() in ('ESP32', 'ESPRESSIF32'): | ||||||
|  |         return ESP_PLATFORM_ESP32 | ||||||
|  |     raise vol.Invalid(u"Invalid platform '{}'. Only options are ESP8266 and ESP32. Please note " | ||||||
|  |                       u"the old way to use the latest arduino framework version has been split up " | ||||||
|  |                       u"into the arduino_version configuration option.".format(value)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | PLATFORMIO_ESP8266_LUT = { | ||||||
|  |     '2.4.2': 'espressif8266@1.8.0', | ||||||
|  |     '2.4.1': 'espressif8266@1.7.3', | ||||||
|  |     '2.4.0': 'espressif8266@1.6.0', | ||||||
|  |     '2.3.0': 'espressif8266@1.5.0', | ||||||
|  |     'RECOMMENDED': 'espressif8266@>=1.8.0', | ||||||
|  |     'LATEST': 'espressif8266', | ||||||
|  |     'DEV': ARDUINO_VERSION_ESP8266_DEV, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | PLATFORMIO_ESP32_LUT = { | ||||||
|  |     '1.0.0': 'espressif32@1.3.0', | ||||||
|  |     'RECOMMENDED': 'espressif32@>=1.3.0', | ||||||
|  |     'LATEST': 'espressif32', | ||||||
|  |     'DEV': ARDUINO_VERSION_ESP32_DEV, | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_arduino_version(value): | ||||||
|  |     value = cv.string_strict(value) | ||||||
|  |     value_ = value.upper() | ||||||
|  |     if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266: | ||||||
|  |         if VERSION_REGEX.match(value) is not None and value_ not in PLATFORMIO_ESP8266_LUT: | ||||||
|  |             raise vol.Invalid("Unfortunately the arduino framework version '{}' is unsupported " | ||||||
|  |                               "at this time. You can override this by manually using " | ||||||
|  |                               "espressif8266@<platformio version>") | ||||||
|  |         if value_ in PLATFORMIO_ESP8266_LUT: | ||||||
|  |             return PLATFORMIO_ESP8266_LUT[value_] | ||||||
|  |         return value | ||||||
|  |     elif core.ESP_PLATFORM == ESP_PLATFORM_ESP32: | ||||||
|  |         if VERSION_REGEX.match(value) is not None and value_ not in PLATFORMIO_ESP32_LUT: | ||||||
|  |             raise vol.Invalid("Unfortunately the arduino framework version '{}' is unsupported " | ||||||
|  |                               "at this time. You can override this by manually using " | ||||||
|  |                               "espressif32@<platformio version>") | ||||||
|  |         if value_ in PLATFORMIO_ESP32_LUT: | ||||||
|  |             return PLATFORMIO_ESP32_LUT[value_] | ||||||
|  |         return value | ||||||
|  |     else: | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = vol.Schema({ | ||||||
|  |     vol.Required(CONF_NAME): cv.valid_name, | ||||||
|  |     vol.Required(CONF_PLATFORM): vol.All(vol.Upper, cv.one_of('ESP8266', 'ESPRESSIF8266', | ||||||
|  |                                                               'ESP32', 'ESPRESSIF32')), | ||||||
|  |     vol.Required(CONF_BOARD): validate_board, | ||||||
|  |     vol.Optional(CONF_ESPHOMELIB_VERSION, default='latest'): ESPHOMELIB_VERSION_SCHEMA, | ||||||
|  |     vol.Optional(CONF_ARDUINO_VERSION, default='recommended'): validate_arduino_version, | ||||||
|  |     vol.Optional(CONF_USE_CUSTOM_CODE, default=False): cv.boolean, | ||||||
|  |     vol.Optional(CONF_BUILD_PATH): cv.string, | ||||||
|  |  | ||||||
|  |     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.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.validate_automation({ | ||||||
|  |         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ShutdownTrigger), | ||||||
|  |     })]), | ||||||
|  |     vol.Optional(CONF_ON_LOOP): vol.All(cv.ensure_list, [automation.validate_automation({ | ||||||
|  |         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(LoopTrigger), | ||||||
|  |     })]), | ||||||
|  |  | ||||||
|  |     vol.Optional('library_uri'): cv.invalid("The library_uri option has been removed in 1.8.0 and " | ||||||
|  |                                             "was moved into the esphomelib_version option.") | ||||||
|  | }) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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.") | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         core.ESP_PLATFORM = validate_platform(core_conf[CONF_PLATFORM]) | ||||||
|  |         core.BOARD = validate_board(core_conf[CONF_BOARD]) | ||||||
|  |     except vol.Invalid as e: | ||||||
|  |         raise ESPHomeYAMLError(unicode(e)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def to_code(config): | ||||||
|  |     add(App.set_name(config[CONF_NAME])) | ||||||
|  |  | ||||||
|  |     for conf in config.get(CONF_ON_BOOT, []): | ||||||
|  |         rhs = App.register_component(StartupTrigger.new(conf.get(CONF_PRIORITY))) | ||||||
|  |         trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) | ||||||
|  |         automation.build_automation(trigger, NoArg, conf) | ||||||
|  |  | ||||||
|  |     for conf in config.get(CONF_ON_SHUTDOWN, []): | ||||||
|  |         trigger = Pvariable(conf[CONF_TRIGGER_ID], ShutdownTrigger.new()) | ||||||
|  |         automation.build_automation(trigger, const_char_p, conf) | ||||||
|  |  | ||||||
|  |     for conf in config.get(CONF_ON_LOOP, []): | ||||||
|  |         rhs = App.register_component(LoopTrigger.new()) | ||||||
|  |         trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) | ||||||
|  |         automation.build_automation(trigger, NoArg, conf) | ||||||
| @@ -2,6 +2,7 @@ from __future__ import print_function | |||||||
|  |  | ||||||
| import inspect | import inspect | ||||||
| import logging | import logging | ||||||
|  | import os | ||||||
| import re | import re | ||||||
| from collections import OrderedDict, deque | from collections import OrderedDict, deque | ||||||
|  |  | ||||||
| @@ -85,8 +86,6 @@ class AssignmentExpression(Expression): | |||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         type_ = self.type |         type_ = self.type | ||||||
|         if core.SIMPLIFY: |  | ||||||
|             type_ = u'auto' |  | ||||||
|         return u"{} {}{} = {}".format(type_, self.modifier, self.name, self.rhs) |         return u"{} {}{} = {}".format(type_, self.modifier, self.name, self.rhs) | ||||||
|  |  | ||||||
|     def has_side_effects(self): |     def has_side_effects(self): | ||||||
| @@ -662,3 +661,7 @@ def color(the_color, message='', reset=None): | |||||||
|     if not message: |     if not message: | ||||||
|         return parse_colors(the_color) |         return parse_colors(the_color) | ||||||
|     return parse_colors(the_color) + message + escape_codes[reset or 'reset'] |     return parse_colors(the_color) + message + escape_codes[reset or 'reset'] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def relative_path(path): | ||||||
|  |     return os.path.join(os.path.dirname(core.CONFIG_PATH), os.path.expanduser(path)) | ||||||
|   | |||||||
| @@ -10,59 +10,162 @@ from esphomeyaml.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_PCF857 | |||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| ESP8266_PINS = { | ESP8266_BASE_PINS = { | ||||||
|     'A0': 17, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14, |     'A0': 17, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14, 'SDA': 4, 'SCL': 5, 'RX': 3, 'TX': 1 | ||||||
| } |  | ||||||
| ESP8266_NODEMCU_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, 'D8': 15, 'D9': 3, |  | ||||||
|     'D10': 1, 'LED': 16, 'SDA': 4, 'SCL': 5, |  | ||||||
| }) |  | ||||||
| ESP8266_D1_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'D0': 3, 'D1': 1, 'D2': 16, 'D3': 5, 'D4': 4, 'D5': 14, 'D6': 12, 'D7': 13, 'D8': 0, 'D9': 2, |  | ||||||
|     'D10': 15, 'D11': 13, 'D12': 14, 'D13': 14, 'D14': 4, 'D15': 5, 'LED': 2, 'SDA': 4, 'SCL': 5, |  | ||||||
| }) |  | ||||||
| ESP8266_D1_MINI_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, 'D8': 15, 'RX': 3, |  | ||||||
|     'TX': 1, 'LED': 2, 'SDA': 4, 'SCL': 5, |  | ||||||
| }) |  | ||||||
| ESP8266_THING_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'LED': 5, 'SDA': 2, 'SCL': 14, |  | ||||||
| }) |  | ||||||
| ESP8266_ADAFRUIT_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'LED': 0, 'SDA': 4, 'SCL': 5, |  | ||||||
| }) |  | ||||||
| ESP8266_ESPDUINO_PINS = dict(ESP8266_PINS, **{ |  | ||||||
|     'LED': 16, 'SDA': 4, 'SCL': 5, |  | ||||||
| }) |  | ||||||
| ESP8266_BOARD_TO_PINS = { |  | ||||||
|     'huzzah': ESP8266_ADAFRUIT_PINS, |  | ||||||
|     'espduino': ESP8266_ESPDUINO_PINS, |  | ||||||
|     'nodemcu': ESP8266_NODEMCU_PINS, 'nodemcuv2': ESP8266_NODEMCU_PINS, |  | ||||||
|     'thing': ESP8266_THING_PINS, 'thingdev': ESP8266_THING_PINS, |  | ||||||
|     'd1': ESP8266_D1_PINS, |  | ||||||
|     'd1_mini': ESP8266_D1_MINI_PINS, 'd1_mini_lite': ESP8266_D1_MINI_PINS, |  | ||||||
|     'd1_mini_pro': ESP8266_D1_MINI_PINS |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ESP32_PINS = { | ESP8266_BOARD_PINS = { | ||||||
|  |     'd1': {'D0': 3, 'D1': 1, 'D2': 16, 'D3': 5, 'D4': 4, 'D5': 14, 'D6': 12, 'D7': 13, 'D8': 0, | ||||||
|  |            'D9': 2, 'D10': 15, 'D11': 13, 'D12': 14, 'D13': 14, 'D14': 4, 'D15': 5, 'LED': 2}, | ||||||
|  |     'd1_mini': {'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, | ||||||
|  |                 'D8': 15, 'LED': 2}, | ||||||
|  |     'd1_mini_lite': 'd1_mini', | ||||||
|  |     'd1_mini_pro': 'd1_mini', | ||||||
|  |     'esp01': {}, | ||||||
|  |     'esp01_1m': {}, | ||||||
|  |     'esp07': {}, | ||||||
|  |     'esp12e': {}, | ||||||
|  |     'esp210': {}, | ||||||
|  |     'esp8285': {}, | ||||||
|  |     'esp_wroom_02': {}, | ||||||
|  |     'espduino': {'LED': 16}, | ||||||
|  |     'espectro': {'LED': 15, 'BUTTON': 2}, | ||||||
|  |     'espino': {'LED': 2, 'LED_RED': 2, 'LED_GREEN': 4, 'LED_BLUE': 5, 'BUTTON': 0}, | ||||||
|  |     'espinotee': {'LED': 16}, | ||||||
|  |     'espresso_lite_v1': {'LED': 16}, | ||||||
|  |     'espresso_lite_v2': {'LED': 2}, | ||||||
|  |     'gen4iod': {}, | ||||||
|  |     'heltec_wifi_kit_8': 'd1_mini', | ||||||
|  |     'huzzah': {'LED': 0}, | ||||||
|  |     'modwifi': {}, | ||||||
|  |     'nodemcu': {'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, | ||||||
|  |                 'D8': 15, 'D9': 3, 'D10': 1, 'LED': 16}, | ||||||
|  |     'nodemcuv2': 'nodemcu', | ||||||
|  |     'oak': {'P0': 2, 'P1': 5, 'P2': 0, 'P3': 3, 'P4': 1, 'P5': 4, 'P6': 15, 'P7': 13, 'P8': 12, | ||||||
|  |             'P9': 14, 'P10': 16, 'P11': 17, 'LED': 5}, | ||||||
|  |     'phoenix_v1': {'LED': 16}, | ||||||
|  |     'phoenix_v2': {'LED': 2}, | ||||||
|  |     'sparkfunBlynk': 'thing', | ||||||
|  |     'thing': {'LED': 5, 'SDA': 2, 'SCL': 14}, | ||||||
|  |     'thingdev': 'thing', | ||||||
|  |     'wifi_slot': {'LED': 2}, | ||||||
|  |     'wifiduino': {'D0': 3, 'D1': 1, 'D2': 2, 'D3': 0, 'D4': 4, 'D5': 5, 'D6': 16, 'D7': 14, | ||||||
|  |                   'D8': 12, 'D9': 13, 'D10': 15, 'D11': 13, 'D12': 12, 'D13': 14}, | ||||||
|  |     'wifinfo': {'LED': 12, 'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, | ||||||
|  |                 'D7': 13, 'D8': 15, 'D9': 3, 'D10': 1}, | ||||||
|  |     'wio_link': {'LED': 2, 'GROVE': 15}, | ||||||
|  |     'wio_node': 'nodemcu', | ||||||
|  |     'xinabox_cw01': {'SDA': 2, 'SCL': 14, 'LED': 5, 'LED_RED': 12, 'LED_GREEN': 13} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ESP32_BASE_PINS = { | ||||||
|     'TX': 1, 'RX': 3, 'SDA': 21, 'SCL': 22, 'SS': 5, 'MOSI': 23, 'MISO': 19, 'SCK': 18, 'A0': 36, |     'TX': 1, 'RX': 3, 'SDA': 21, 'SCL': 22, 'SS': 5, 'MOSI': 23, 'MISO': 19, 'SCK': 18, 'A0': 36, | ||||||
|     'A3': 39, 'A4': 32, 'A5': 33, 'A6': 34, 'A7': 35, 'A10': 4, 'A11': 0, 'A12': 2, 'A13': 15, |     'A3': 39, 'A4': 32, 'A5': 33, 'A6': 34, 'A7': 35, 'A10': 4, 'A11': 0, 'A12': 2, 'A13': 15, | ||||||
|     'A14': 13, 'A15': 12, 'A16': 14, 'A17': 27, 'A18': 25, 'A19': 26, 'T0': 4, 'T1': 0, 'T2': 2, |     'A14': 13, 'A15': 12, 'A16': 14, 'A17': 27, 'A18': 25, 'A19': 26, 'T0': 4, 'T1': 0, 'T2': 2, | ||||||
|     'T3': 15, 'T4': 12, 'T5': 12, 'T6': 14, 'T7': 27, 'T8': 33, 'T9': 32, 'DAC1': 25, 'DAC2': 26, |     'T3': 15, 'T4': 13, 'T5': 12, 'T6': 14, 'T7': 27, 'T8': 33, 'T9': 32, 'DAC1': 25, 'DAC2': 26, | ||||||
|     'SVP': 36, 'SVN': 39, |     'SVP': 36, 'SVN': 39, | ||||||
| } | } | ||||||
| ESP32_NODEMCU_32S_PINS = dict(ESP32_PINS, **{ |  | ||||||
|     'LED': 2, | ESP32_BOARD_PINS = { | ||||||
| }) |     'alksesp32': {'D0': 40, 'D1': 41, 'D2': 15, 'D3': 2, 'D4': 0, 'D5': 4, 'D6': 16, 'D7': 17, | ||||||
| ESP32_LOLIN32_PINS = dict(ESP32_PINS, **{ |                   'D8': 5, 'D9': 18, 'D10': 19, 'D11': 21, 'D12': 22, 'D13': 23, 'A0': 32, 'A1': 33, | ||||||
|     'LED': 5 |                   'A2': 25, 'A3': 26, 'A4': 27, 'A5': 14, 'A6': 12, 'A7': 15, 'L_R': 22, 'L_G': 17, | ||||||
| }) |                   'L_Y': 23, 'L_B': 5, 'L_RGB_R': 4, 'L_RGB_G': 21, 'L_RGB_B': 16, 'SW1': 15, | ||||||
| ESP32_BOARD_TO_PINS = { |                   'SW2': 2, 'SW3': 0, 'POT1': 32, 'POT2': 33, 'PIEZO1': 19, 'PIEZO2': 18, | ||||||
|     'nodemcu-32s': ESP32_NODEMCU_32S_PINS, |                   'PHOTO': 25, 'DHT_PIN': 26, 'S1': 4, 'S2': 16, 'S3': 18, 'S4': 19, 'S5': 21, | ||||||
|     'lolin32': ESP32_LOLIN32_PINS, |                   'SDA': 27, 'SCL': 14, 'SS': 19, 'MOSI': 21, 'MISO': 22, 'SCK': 23}, | ||||||
|  |     'esp-wrover-kit': {}, | ||||||
|  |     'esp32-evb': {'BUTTON': 34, 'SDA': 13, 'SCL': 16, 'SS': 17, 'MOSI': 2, 'MISO': 15, 'SCK': 14}, | ||||||
|  |     'esp32-gateway': {'LED': 33, 'BUTTON': 34, 'SCL': 16, 'SDA': 17}, | ||||||
|  |     'esp320': {'LED': 5, 'SDA': 2, 'SCL': 14, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14}, | ||||||
|  |     'esp32dev': {}, | ||||||
|  |     'esp32doit-devkit-v1': {'LED': 2}, | ||||||
|  |     'esp32thing': {'LED': 5, 'BUTTON': 0, 'SS': 2}, | ||||||
|  |     'esp32vn-iot-uno': {}, | ||||||
|  |     'espea32': {'LED': 5, 'BUTTON': 0}, | ||||||
|  |     'espectro32': {'LED': 15, 'SD_SS': 33}, | ||||||
|  |     'espino32': {'LED': 16, 'BUTTON': 0}, | ||||||
|  |     'featheresp32': {'LED': 13, 'TX': 17, 'RX': 16, 'SDA': 23, 'SS': 2, 'MOSI': 18, 'SCK': 5, | ||||||
|  |                      'A0': 26, 'A1': 25, 'A2': 34, 'A4': 36, 'A5': 4, 'A6': 14, 'A7': 32, 'A8': 15, | ||||||
|  |                      'A9': 33, 'A10': 27, 'A11': 12, 'A12': 13, 'A13': 35}, | ||||||
|  |     'firebeetle32': {'LED': 2}, | ||||||
|  |     'heltec_wifi_kit_32': {'LED': 25, 'BUTTON': 0, 'A1': 37, 'A2': 38}, | ||||||
|  |     'heltec_wifi_lora_32': {'LED': 25, 'BUTTON': 0, 'SDA': 4, 'SCL': 15, 'SS': 18, 'MOSI': 27, | ||||||
|  |                             'SCK': 5, 'A1': 37, 'A2': 38, 'T8': 32, 'T9': 33, 'DAC1': 26, | ||||||
|  |                             'DAC2': 25, 'OLED_SCL': 15, 'OLED_SDA': 4, 'OLED_RST': 16, | ||||||
|  |                             'LORA_SCK': 5, 'LORA_MOSI': 27, 'LORA_MISO': 19, 'LORA_CS': 18, | ||||||
|  |                             'LORA_RST': 14, 'LORA_IRQ': 26}, | ||||||
|  |     'hornbill32dev': {'LED': 13, 'BUTTON': 0}, | ||||||
|  |     'hornbill32minima': {'SS': 2}, | ||||||
|  |     'intorobot': {'LED': 4, 'LED_RED': 27, 'LED_GREEN': 21, 'LED_BLUE': 22, | ||||||
|  |                   'BUTTON': 0, 'SDA': 23, 'SCL': 19, 'MOSI': 16, 'MISO': 17, 'A1': 39, 'A2': 35, | ||||||
|  |                   'A3': 25, 'A4': 26, 'A5': 14, 'A6': 12, 'A7': 15, 'A8': 13, 'A9': 2, 'D0': 19, | ||||||
|  |                   'D1': 23, 'D2': 18, 'D3': 17, 'D4': 16, 'D5': 5, 'D6': 4, 'T0': 19, 'T1': 23, | ||||||
|  |                   'T2': 18, 'T3': 17, 'T4': 16, 'T5': 5, 'T6': 4}, | ||||||
|  |     'lolin32': {'LED': 5}, | ||||||
|  |     'lolin_d32': {'LED': 5, 'VBAT': 35}, | ||||||
|  |     'lolin_d32_pro': {'LED': 5, 'VBAT': 35, 'TF_CS': 4, 'TS_CS': 12, 'TFT_CS': 14, 'TFT_LED': 32, | ||||||
|  |                       'TFT_RST': 33, 'TFT_DC': 27}, | ||||||
|  |     'm5stack-core-esp32': {'TXD2': 17, 'RXD2': 16, 'G23': 23, 'G19': 19, 'G18': 18, 'G3': 3, | ||||||
|  |                            'G16': 16, 'G21': 21, 'G2': 2, 'G12': 12, 'G15': 15, 'G35': 35, | ||||||
|  |                            'G36': 36, 'G25': 25, 'G26': 26, 'G1': 1, 'G17': 17, 'G22': 22, 'G5': 5, | ||||||
|  |                            'G13': 13, 'G0': 0, 'G34': 34, 'ADC1': 35, 'ADC2': 36}, | ||||||
|  |     'm5stack-fire': {'G23': 23, 'G19': 19, 'G18': 18, 'G3': 3, 'G16': 16, 'G21': 21, 'G2': 2, | ||||||
|  |                      'G12': 12, 'G15': 15, 'G35': 35, 'G36': 36, 'G25': 25, 'G26': 26, 'G1': 1, | ||||||
|  |                      'G17': 17, 'G22': 22, 'G5': 5, 'G13': 13, 'G0': 0, 'G34': 34, 'ADC1': 35, | ||||||
|  |                      'ADC2': 36}, | ||||||
|  |     'mhetesp32devkit': {'LED': 2}, | ||||||
|  |     'mhetesp32minikit': {'LED': 2}, | ||||||
|  |     'microduino-core-esp32': {'SDA': 22, 'SCL': 21, 'SDA1': 12, 'SCL1': 13, 'A0': 12, 'A1': 13, | ||||||
|  |                               'A2': 15, 'A3': 4, 'A6': 38, 'A7': 37, 'A8': 32, 'A9': 33, 'A10': 25, | ||||||
|  |                               'A11': 26, 'A12': 27, 'A13': 14, 'D0': 3, 'D1': 1, 'D2': 16, 'D3': 17, | ||||||
|  |                               'D4': 32, 'D5': 33, 'D6': 25, 'D7': 26, 'D8': 27, 'D9': 14, 'D10': 5, | ||||||
|  |                               'D11': 23, 'D12': 19, 'D13': 18, 'D14': 12, 'D15': 13, 'D16': 15, | ||||||
|  |                               'D17': 4, 'D18': 22, 'D19': 21, 'D20': 38, 'D21': 37}, | ||||||
|  |     'nano32': {'LED': 16, 'BUTTON': 0}, | ||||||
|  |     'nina_w10': {'LED_GREEN': 33, 'LED_RED': 23, 'LED_BLUE': 21, 'SW1': 33, 'SW2': 27, 'SDA': 12, | ||||||
|  |                  'SCL': 13, 'D0': 3, 'D1': 1, 'D2': 26, 'D3': 25, 'D4': 35, 'D5': 27, 'D6': 22, | ||||||
|  |                  'D7': 0, 'D8': 15, 'D9': 14, 'D10': 5, 'D11': 19, 'D12': 23, 'D13': 18, 'D14': 13, | ||||||
|  |                  'D15': 12, 'D16': 32, 'D17': 33, 'D18': 21, 'D19': 34, 'D20': 36, 'D21': 39}, | ||||||
|  |     'node32s': {}, | ||||||
|  |     'nodemcu-32s': {'LED': 2, 'BUTTON': 0}, | ||||||
|  |     'odroid_esp32': {'LED': 2, 'SDA': 15, 'SCL': 4, 'SS': 22, 'ADC1': 35, 'ADC2': 36}, | ||||||
|  |     'onehorse32dev': {'LED': 5, 'BUTTON': 0, 'A1': 37, 'A2': 38}, | ||||||
|  |     'pico32': {}, | ||||||
|  |     'pocket_32': {'LED': 16}, | ||||||
|  |     'quantum': {}, | ||||||
|  |     'ttgo-lora32-v1': {'LED': 2, 'BUTTON': 0, 'SS': 18, 'MOSI': 27, 'SCK': 5, 'A1': 37, 'A2': 38, | ||||||
|  |                        'T8': 32, 'T9': 33, 'DAC1': 26, 'DAC2': 25, 'OLED_SDA': 4, 'OLED_SCL': 15, | ||||||
|  |                        'OLED_RST': 16, 'LORA_SCK': 5, 'LORA_MISO': 19, 'LORA_MOSI': 27, | ||||||
|  |                        'LORA_CS': 18, 'LORA_RST': 14, 'LORA_IRQ': 26}, | ||||||
|  |     'wemosbat': 'pocket_32', | ||||||
|  |     'widora-air': {'LED': 25, 'BUTTON': 0, 'SDA': 23, 'SCL': 19, 'MOSI': 16, 'MISO': 17, 'A1': 39, | ||||||
|  |                    'A2': 35, 'A3': 25, 'A4': 26, 'A5': 14, 'A6': 12, 'A7': 15, 'A8': 13, 'A9': 2, | ||||||
|  |                    'D0': 19, 'D1': 23, 'D2': 18, 'D3': 17, 'D4': 16, 'D5': 5, 'D6': 4, 'T0': 19, | ||||||
|  |                    'T1': 23, 'T2': 18, 'T3': 17, 'T4': 16, 'T5': 5, 'T6': 4}, | ||||||
|  |     'xinabox_cw02': {'LED': 27}, | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _lookup_pin(platform, board, value): | ||||||
|  |     if platform == ESP_PLATFORM_ESP8266: | ||||||
|  |         board_pins = ESP8266_BOARD_PINS.get(board, {}) | ||||||
|  |         base_pins = ESP8266_BASE_PINS | ||||||
|  |     elif platform == ESP_PLATFORM_ESP32: | ||||||
|  |         board_pins = ESP32_BOARD_PINS.get(board, {}) | ||||||
|  |         base_pins = ESP32_BASE_PINS | ||||||
|  |     else: | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |     if isinstance(board_pins, str): | ||||||
|  |         return _lookup_pin(platform, board_pins, value) | ||||||
|  |     if value in board_pins: | ||||||
|  |         return board_pins[value] | ||||||
|  |     if value in base_pins: | ||||||
|  |         return base_pins[value] | ||||||
|  |     raise vol.Invalid(u"Can't find internal pin number for {}.".format(value)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def _translate_pin(value): | def _translate_pin(value): | ||||||
|     if isinstance(value, dict) or value is None: |     if isinstance(value, dict) or value is None: | ||||||
|         raise vol.Invalid(u"This variable only supports pin numbers, not full pin schemas " |         raise vol.Invalid(u"This variable only supports pin numbers, not full pin schemas " | ||||||
| @@ -75,27 +178,7 @@ def _translate_pin(value): | |||||||
|         pass |         pass | ||||||
|     if value.startswith('GPIO'): |     if value.startswith('GPIO'): | ||||||
|         return vol.Coerce(int)(value[len('GPIO'):].strip()) |         return vol.Coerce(int)(value[len('GPIO'):].strip()) | ||||||
|     if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: |     return _lookup_pin(core.ESP_PLATFORM, core.BOARD, value) | ||||||
|         if value in ESP32_PINS: |  | ||||||
|             return ESP32_PINS[value] |  | ||||||
|         if core.BOARD not in ESP32_BOARD_TO_PINS: |  | ||||||
|             raise vol.Invalid(u"ESP32: Unknown board {} with unknown " |  | ||||||
|                               u"pin {}.".format(core.BOARD, value)) |  | ||||||
|         if value not in ESP32_BOARD_TO_PINS[core.BOARD]: |  | ||||||
|             raise vol.Invalid(u"ESP32: Board {} doesn't have " |  | ||||||
|                               u"pin {}".format(core.BOARD, value)) |  | ||||||
|         return ESP32_BOARD_TO_PINS[core.BOARD][value] |  | ||||||
|     elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266: |  | ||||||
|         if value in ESP8266_PINS: |  | ||||||
|             return ESP8266_PINS[value] |  | ||||||
|         if core.BOARD not in ESP8266_BOARD_TO_PINS: |  | ||||||
|             raise vol.Invalid(u"ESP8266: Unknown board {} with unknown " |  | ||||||
|                               u"pin {}.".format(core.BOARD, value)) |  | ||||||
|         if value not in ESP8266_BOARD_TO_PINS[core.BOARD]: |  | ||||||
|             raise vol.Invalid(u"ESP8266: Board {} doesn't have " |  | ||||||
|                               u"pin {}".format(core.BOARD, value)) |  | ||||||
|         return ESP8266_BOARD_TO_PINS[core.BOARD][value] |  | ||||||
|     raise vol.Invalid(u"Invalid ESP platform.") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def validate_gpio_pin(value): | def validate_gpio_pin(value): | ||||||
|   | |||||||
| @@ -8,12 +8,13 @@ import voluptuous as vol | |||||||
|  |  | ||||||
| import esphomeyaml.config_validation as cv | import esphomeyaml.config_validation as cv | ||||||
| from esphomeyaml.components import mqtt | from esphomeyaml.components import mqtt | ||||||
| from esphomeyaml.const import ESP_BOARDS_FOR_PLATFORM, ESP_PLATFORMS, ESP_PLATFORM_ESP32, \ | from esphomeyaml.const import ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 | ||||||
|     ESP_PLATFORM_ESP8266 |  | ||||||
| from esphomeyaml.helpers import color | from esphomeyaml.helpers import color | ||||||
|  |  | ||||||
|  |  | ||||||
| # pylint: disable=anomalous-backslash-in-string | # pylint: disable=anomalous-backslash-in-string | ||||||
|  | from esphomeyaml.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS | ||||||
|  |  | ||||||
| CORE_BIG = """    _____ ____  _____  ______ | CORE_BIG = """    _____ ____  _____  ______ | ||||||
|    / ____/ __ \|  __ \|  ____| |    / ____/ __ \|  __ \|  ____| | ||||||
|   | |   | |  | | |__) | |__ |   | |   | |  | | |__) | |__ | ||||||
| @@ -187,11 +188,12 @@ def wizard(path): | |||||||
|     # Don't sleep because user needs to copy link |     # Don't sleep because user needs to copy link | ||||||
|     if platform == ESP_PLATFORM_ESP32: |     if platform == ESP_PLATFORM_ESP32: | ||||||
|         print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s'))) |         print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s'))) | ||||||
|  |         boards = list(ESP32_BOARD_PINS.keys()) | ||||||
|     else: |     else: | ||||||
|         print("For example \"{}\".".format(color("bold_white", 'nodemcuv2'))) |         print("For example \"{}\".".format(color("bold_white", 'nodemcuv2'))) | ||||||
|  |         boards = list(ESP8266_BOARD_PINS.keys()) | ||||||
|     while True: |     while True: | ||||||
|         board = raw_input(color("bold_white", "(board): ")) |         board = raw_input(color("bold_white", "(board): ")) | ||||||
|         boards = ESP_BOARDS_FOR_PLATFORM[platform] |  | ||||||
|         try: |         try: | ||||||
|             board = vol.All(vol.Lower, vol.Any(*boards))(board) |             board = vol.All(vol.Lower, vol.Any(*boards))(board) | ||||||
|             break |             break | ||||||
|   | |||||||
| @@ -2,14 +2,17 @@ from __future__ import print_function | |||||||
|  |  | ||||||
| import codecs | import codecs | ||||||
| import errno | import errno | ||||||
|  | import json | ||||||
| import os | import os | ||||||
|  |  | ||||||
| from esphomeyaml import core | from esphomeyaml import core | ||||||
| from esphomeyaml.config import iter_components | from esphomeyaml.config import iter_components | ||||||
| from esphomeyaml.const import CONF_BOARD, CONF_BOARD_FLASH_MODE, CONF_ESPHOMEYAML, \ | from esphomeyaml.const import CONF_ARDUINO_VERSION, CONF_BOARD, CONF_BOARD_FLASH_MODE, \ | ||||||
|     CONF_LIBRARY_URI, \ |     CONF_ESPHOMELIB_VERSION, CONF_ESPHOMEYAML, CONF_LOCAL, CONF_NAME, CONF_USE_CUSTOM_CODE, \ | ||||||
|     CONF_NAME, CONF_PLATFORM, CONF_USE_BUILD_FLAGS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 |     ESP_PLATFORM_ESP32, ARDUINO_VERSION_ESP32_DEV | ||||||
| from esphomeyaml.core import ESPHomeYAMLError | from esphomeyaml.core import ESPHomeYAMLError | ||||||
|  | from esphomeyaml.core_config import VERSION_REGEX | ||||||
|  | from esphomeyaml.helpers import relative_path | ||||||
|  |  | ||||||
| CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ===========' | CPP_AUTO_GENERATE_BEGIN = u'// ========== AUTO GENERATED CODE BEGIN ===========' | ||||||
| CPP_AUTO_GENERATE_END = u'// =========== AUTO GENERATED CODE END ============' | CPP_AUTO_GENERATE_END = u'// =========== AUTO GENERATED CODE END ============' | ||||||
| @@ -59,11 +62,6 @@ build_flags = | |||||||
|     ${{common.build_flags}} |     ${{common.build_flags}} | ||||||
| """ | """ | ||||||
|  |  | ||||||
| PLATFORM_TO_PLATFORMIO = { |  | ||||||
|     ESP_PLATFORM_ESP32: 'espressif32', |  | ||||||
|     ESP_PLATFORM_ESP8266: 'espressif8266' |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_build_flags(config, key): | def get_build_flags(config, key): | ||||||
|     build_flags = set() |     build_flags = set() | ||||||
| @@ -81,19 +79,16 @@ def get_build_flags(config, key): | |||||||
|     return build_flags |     return build_flags | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_ini_content(config): | def get_ini_content(config, path): | ||||||
|     version_specific_settings = determine_platformio_version_settings() |     version_specific_settings = determine_platformio_version_settings() | ||||||
|     platform = config[CONF_ESPHOMEYAML][CONF_PLATFORM] |  | ||||||
|     if platform in PLATFORM_TO_PLATFORMIO: |  | ||||||
|         platform = PLATFORM_TO_PLATFORMIO[platform] |  | ||||||
|     options = { |     options = { | ||||||
|         u'env': config[CONF_ESPHOMEYAML][CONF_NAME], |         u'env': config[CONF_ESPHOMEYAML][CONF_NAME], | ||||||
|         u'platform': platform, |         u'platform': config[CONF_ESPHOMEYAML][CONF_ARDUINO_VERSION], | ||||||
|         u'board': config[CONF_ESPHOMEYAML][CONF_BOARD], |         u'board': config[CONF_ESPHOMEYAML][CONF_BOARD], | ||||||
|         u'build_flags': u'', |         u'build_flags': u'', | ||||||
|     } |     } | ||||||
|     build_flags = set() |     build_flags = set() | ||||||
|     if config[CONF_ESPHOMEYAML][CONF_USE_BUILD_FLAGS]: |     if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]: | ||||||
|         build_flags |= get_build_flags(config, 'build_flags') |         build_flags |= get_build_flags(config, 'build_flags') | ||||||
|         build_flags |= get_build_flags(config, 'BUILD_FLAGS') |         build_flags |= get_build_flags(config, 'BUILD_FLAGS') | ||||||
|         build_flags.add(u"-DESPHOMEYAML_USE") |         build_flags.add(u"-DESPHOMEYAML_USE") | ||||||
| @@ -106,13 +101,48 @@ def get_ini_content(config): | |||||||
|         options[u'build_flags'] = u'\n    '.join(build_flags) |         options[u'build_flags'] = u'\n    '.join(build_flags) | ||||||
|  |  | ||||||
|     lib_deps = set() |     lib_deps = set() | ||||||
|     lib_deps.add(config[CONF_ESPHOMEYAML][CONF_LIBRARY_URI]) |  | ||||||
|  |     lib_version = config[CONF_ESPHOMEYAML][CONF_ESPHOMELIB_VERSION] | ||||||
|  |     lib_path = os.path.join(path, 'lib') | ||||||
|  |     dst_path = os.path.join(lib_path, 'esphomelib') | ||||||
|  |     if isinstance(lib_version, (str, unicode)): | ||||||
|  |         lib_deps.add(lib_version) | ||||||
|  |         if os.path.islink(dst_path): | ||||||
|  |             os.unlink(dst_path) | ||||||
|  |     else: | ||||||
|  |         src_path = relative_path(lib_version[CONF_LOCAL]) | ||||||
|  |         do_write = True | ||||||
|  |         if os.path.islink(dst_path): | ||||||
|  |             old_path = os.path.join(os.readlink(dst_path), lib_path) | ||||||
|  |             if old_path != lib_path: | ||||||
|  |                 os.unlink(dst_path) | ||||||
|  |             else: | ||||||
|  |                 do_write = False | ||||||
|  |         if do_write: | ||||||
|  |             mkdir_p(lib_path) | ||||||
|  |             os.symlink(src_path, dst_path) | ||||||
|  |  | ||||||
|  |         # Manually add lib_deps because platformio seems to ignore them inside libs/ | ||||||
|  |         library_json_path = os.path.join(src_path, 'library.json') | ||||||
|  |         with codecs.open(library_json_path, 'r', encoding='utf-8') as f_handle: | ||||||
|  |             library_json_text = f_handle.read() | ||||||
|  |  | ||||||
|  |         library_json = json.loads(library_json_text) | ||||||
|  |         for dep in library_json.get('dependencies', []): | ||||||
|  |             if 'version' in dep and VERSION_REGEX.match(dep['version']) is not None: | ||||||
|  |                 lib_deps.add(dep['name'] + '@' + dep['version']) | ||||||
|  |             else: | ||||||
|  |                 lib_deps.add(dep['version']) | ||||||
|  |  | ||||||
|     lib_deps |= get_build_flags(config, 'LIB_DEPS') |     lib_deps |= get_build_flags(config, 'LIB_DEPS') | ||||||
|     lib_deps |= get_build_flags(config, 'lib_deps') |     lib_deps |= get_build_flags(config, 'lib_deps') | ||||||
|     if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: |     if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: | ||||||
|         lib_deps |= { |         lib_deps |= { | ||||||
|             'Preferences',  # Preferences helper |             'Preferences',  # Preferences helper | ||||||
|         } |         } | ||||||
|  |         # Manual fix for AsyncTCP | ||||||
|  |         if config[CONF_ESPHOMEYAML].get(CONF_ARDUINO_VERSION) == ARDUINO_VERSION_ESP32_DEV: | ||||||
|  |             lib_deps.add('https://github.com/me-no-dev/AsyncTCP.git#idf-update') | ||||||
|     # avoid changing build flags order |     # avoid changing build flags order | ||||||
|     lib_deps = sorted(x for x in lib_deps if x) |     lib_deps = sorted(x for x in lib_deps if x) | ||||||
|     if lib_deps: |     if lib_deps: | ||||||
| @@ -178,7 +208,7 @@ def write_platformio_ini(content, path): | |||||||
|  |  | ||||||
| def write_platformio_project(config, path): | def write_platformio_project(config, path): | ||||||
|     platformio_ini = os.path.join(path, 'platformio.ini') |     platformio_ini = os.path.join(path, 'platformio.ini') | ||||||
|     content = get_ini_content(config) |     content = get_ini_content(config, path) | ||||||
|     if 'esp32_ble_beacon' in config or 'esp32_ble_tracker' in config: |     if 'esp32_ble_beacon' in config or 'esp32_ble_tracker' in config: | ||||||
|         content += 'board_build.partitions = partitions.csv\n' |         content += 'board_build.partitions = partitions.csv\n' | ||||||
|         partitions_csv = os.path.join(path, 'partitions.csv') |         partitions_csv = os.path.join(path, 'partitions.csv') | ||||||
|   | |||||||
| @@ -2,10 +2,12 @@ esphomeyaml: | |||||||
|   name: test1 |   name: test1 | ||||||
|   platform: ESP32 |   platform: ESP32 | ||||||
|   board: nodemcu-32s |   board: nodemcu-32s | ||||||
|   # Use latest esphomelib git version. TODO: Change this |   # Use latest upstream esphomelib git version. | ||||||
|   library_uri: 'https://github.com/OttoWinter/esphomelib.git' |   esphomelib_version: dev | ||||||
|   simplify: false |   # Use this for testing while developing: | ||||||
|   use_build_flags: yes |   # esphomelib_version: | ||||||
|  |   #   local: ~/path/to/esphomelib | ||||||
|  |   use_custom_code: false | ||||||
|   on_boot: |   on_boot: | ||||||
|     priority: 150.0 |     priority: 150.0 | ||||||
|     then: |     then: | ||||||
| @@ -15,6 +17,10 @@ esphomeyaml: | |||||||
|     then: |     then: | ||||||
|       - lambda: >- |       - lambda: >- | ||||||
|           ESP_LOGD("main", "ON SHUTDOWN!"); |           ESP_LOGD("main", "ON SHUTDOWN!"); | ||||||
|  |   on_loop: | ||||||
|  |     then: | ||||||
|  |       - lambda: >- | ||||||
|  |           ESP_LOGV("main", "ON LOOP!"); | ||||||
|   build_path: build |   build_path: build | ||||||
|  |  | ||||||
| wifi: | wifi: | ||||||
| @@ -55,7 +61,7 @@ mqtt: | |||||||
|       qos: 0 |       qos: 0 | ||||||
|       then: |       then: | ||||||
|         - lambda: >- |         - lambda: >- | ||||||
|             ESP_LOGD("main", "Got message %s", x); |             ESP_LOGD("main", "Got message %s", x.c_str()); | ||||||
|     - topic: livingroom/ota_mode |     - topic: livingroom/ota_mode | ||||||
|       then: |       then: | ||||||
|       - deep_sleep.prevent: |       - deep_sleep.prevent: | ||||||
| @@ -905,6 +911,10 @@ time: | |||||||
|   - 0.pool.ntp.org |   - 0.pool.ntp.org | ||||||
|   - 1.pool.ntp.org |   - 1.pool.ntp.org | ||||||
|   - 2.pool.ntp.org |   - 2.pool.ntp.org | ||||||
|  |   on_time: | ||||||
|  |     cron: '/30 0-30,30/5 * ? JAN-DEC MON,SAT-SUN,TUE-FRI' | ||||||
|  |     then: | ||||||
|  |       - lambda: 'ESP_LOGD("main", "time");' | ||||||
|  |  | ||||||
| cover: | cover: | ||||||
|   - platform: template |   - platform: template | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user