mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Updates
This commit is contained in:
parent
74c70509c2
commit
2abbe1bca3
17 changed files with 653 additions and 219 deletions
|
@ -4,7 +4,7 @@ python:
|
|||
- "2.7"
|
||||
install:
|
||||
- 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:
|
||||
- flake8 esphomeyaml
|
||||
- pylint esphomeyaml
|
||||
|
|
|
@ -7,11 +7,11 @@ import random
|
|||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util
|
||||
from esphomeyaml.config import core_to_code, get_component, iter_components, read_config
|
||||
from esphomeyaml import const, core, core_config, mqtt, wizard, writer, yaml_util
|
||||
from esphomeyaml.config import get_component, iter_components, read_config
|
||||
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, \
|
||||
ESP_PLATFORM_ESP8266
|
||||
CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \
|
||||
CONF_WIFI, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
|
||||
add_job, color, flush_tasks, indent, quote, statement
|
||||
|
@ -123,7 +123,7 @@ def run_miniterm(config, port, escape=False):
|
|||
def write_cpp(config):
|
||||
_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:
|
||||
if domain == CONF_ESPHOMEYAML or domain not in config:
|
||||
continue
|
||||
|
@ -139,7 +139,7 @@ def write_cpp(config):
|
|||
add(RawStatement(''))
|
||||
all_code = []
|
||||
for exp in _EXPRESSIONS:
|
||||
if core.SIMPLIFY:
|
||||
if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]:
|
||||
if isinstance(exp, Expression) and not exp.required:
|
||||
continue
|
||||
if isinstance(exp, AssignmentExpression) and not exp.obj.required:
|
||||
|
@ -302,7 +302,7 @@ def command_compile(args, config):
|
|||
return exit_code
|
||||
if args.only_generate:
|
||||
_LOGGER.info(u"Successfully generated source code.")
|
||||
return 0;
|
||||
return 0
|
||||
exit_code = compile_program(args, config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
@ -388,10 +388,11 @@ def parse_args(argv):
|
|||
subparsers.required = True
|
||||
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',
|
||||
help="Only generate source code, do not compile.",
|
||||
action='store_true')
|
||||
help="Only generate source code, do not compile.",
|
||||
action='store_true')
|
||||
|
||||
parser_upload = subparsers.add_parser('upload', help='Validate the configuration '
|
||||
'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, \
|
||||
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_DELAYED_OFF, CONF_LAMBDA
|
||||
CONF_DELAYED_OFF, CONF_LAMBDA, CONF_HEARTBEAT
|
||||
from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \
|
||||
setup_mqtt_component, bool_, process_lambda, ArrayInitializer
|
||||
|
||||
|
@ -30,6 +30,7 @@ InvertFilter = binary_sensor_ns.InvertFilter
|
|||
LambdaFilter = binary_sensor_ns.LambdaFilter
|
||||
DelayedOnFilter = binary_sensor_ns.DelayedOnFilter
|
||||
DelayedOffFilter = binary_sensor_ns.DelayedOffFilter
|
||||
HeartbeatFilter = binary_sensor_ns.HeartbeatFilter
|
||||
MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent
|
||||
|
||||
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_DELAYED_ON): 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_,
|
||||
}, 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]))
|
||||
elif CONF_DELAYED_ON in config:
|
||||
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:
|
||||
lambda_ = None
|
||||
for lambda_ in process_lambda(config[CONF_LAMBDA], [(bool_, 'x')]):
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# coding=utf-8
|
||||
import os.path
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
|
@ -8,7 +6,8 @@ from esphomeyaml import core
|
|||
from esphomeyaml.components import display
|
||||
from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE
|
||||
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']
|
||||
|
||||
|
@ -57,17 +56,13 @@ def validate_pillow_installed(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
|
||||
raise vol.Invalid(u"Please unzip the font archive '{}' first and then use the .ttf files "
|
||||
u"inside.".format(value))
|
||||
if not value.endswith('.ttf'):
|
||||
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")
|
||||
return value
|
||||
return cv.file_(value)
|
||||
|
||||
|
||||
DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
|
||||
|
@ -88,7 +83,7 @@ def to_code(config):
|
|||
from PIL import ImageFont
|
||||
|
||||
for conf in config:
|
||||
path = os.path.join(os.path.dirname(core.CONFIG_PATH), conf[CONF_FILE])
|
||||
path = relative_path(conf[CONF_FILE])
|
||||
try:
|
||||
font = ImageFont.truetype(path, conf[CONF_SIZE])
|
||||
except Exception as e:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# coding=utf-8
|
||||
import logging
|
||||
import os.path
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -9,7 +8,8 @@ from esphomeyaml import core
|
|||
from esphomeyaml.components import display, font
|
||||
from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE
|
||||
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__)
|
||||
|
||||
|
@ -17,20 +17,11 @@ DEPENDENCIES = ['display']
|
|||
|
||||
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'
|
||||
|
||||
IMAGE_SCHEMA = vol.Schema({
|
||||
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,
|
||||
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None),
|
||||
})
|
||||
|
@ -42,7 +33,7 @@ def to_code(config):
|
|||
from PIL import Image
|
||||
|
||||
for conf in config:
|
||||
path = os.path.join(os.path.dirname(core.CONFIG_PATH), conf[CONF_FILE])
|
||||
path = relative_path(conf[CONF_FILE])
|
||||
try:
|
||||
image = Image.open(path)
|
||||
except Exception as e:
|
||||
|
|
|
@ -5,9 +5,10 @@ import math
|
|||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_TIMEZONE
|
||||
from esphomeyaml.helpers import add, add_job, esphomelib_ns
|
||||
|
||||
from esphomeyaml import automation
|
||||
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__)
|
||||
|
||||
|
@ -16,6 +17,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
time_ns = esphomelib_ns.namespace('time')
|
||||
CronTrigger = time_ns.CronTrigger
|
||||
|
||||
|
||||
def _tz_timedelta(td):
|
||||
|
@ -117,14 +119,155 @@ def detect_tz():
|
|||
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({
|
||||
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):
|
||||
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):
|
||||
add_job(setup_time_core_, time_var, config)
|
||||
|
|
|
@ -8,7 +8,7 @@ from esphomeyaml.helpers import App, Pvariable
|
|||
SNTPComponent = time_.time_ns.SNTPComponent
|
||||
|
||||
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_LAMBDA): cv.lambda_,
|
||||
})
|
||||
|
|
|
@ -7,62 +7,20 @@ from collections import OrderedDict
|
|||
import voluptuous as vol
|
||||
from voluptuous.humanize import humanize_error
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import core, yaml_util, automation
|
||||
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 import core, yaml_util, core_config
|
||||
from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, CONF_WIFI, ESP_PLATFORMS
|
||||
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__)
|
||||
|
||||
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 = [
|
||||
CONF_ESPHOMEYAML, CONF_WIFI
|
||||
]
|
||||
|
||||
_COMPONENT_CACHE = {}
|
||||
_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):
|
||||
if domain in _COMPONENT_CACHE:
|
||||
return _COMPONENT_CACHE[domain]
|
||||
|
@ -171,9 +129,9 @@ def validate_config(config):
|
|||
result.add_error(_format_config_error(ex, domain, config), domain, config)
|
||||
|
||||
try:
|
||||
result[CONF_ESPHOMEYAML] = CORE_SCHEMA(config[CONF_ESPHOMEYAML])
|
||||
result[CONF_ESPHOMEYAML] = core_config.CONFIG_SCHEMA(config[CONF_ESPHOMEYAML])
|
||||
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():
|
||||
domain = str(domain)
|
||||
|
@ -288,23 +246,7 @@ def load_config(path):
|
|||
except OSError:
|
||||
raise ESPHomeYAMLError(u"Could not read configuration file at {}".format(path))
|
||||
core.RAW_CONFIG = config
|
||||
|
||||
if CONF_ESPHOMEYAML not in config:
|
||||
raise ESPHomeYAMLError(u"No esphomeyaml section in config")
|
||||
core_conf = config[CONF_ESPHOMEYAML]
|
||||
if CONF_PLATFORM not in core_conf:
|
||||
raise ESPHomeYAMLError("esphomeyaml.platform not specified.")
|
||||
esp_platform = unicode(core_conf[CONF_PLATFORM])
|
||||
esp_platform = esp_platform.upper()
|
||||
if '8266' in esp_platform:
|
||||
esp_platform = ESP_PLATFORM_ESP8266
|
||||
if '32' in esp_platform:
|
||||
esp_platform = ESP_PLATFORM_ESP32
|
||||
core.ESP_PLATFORM = esp_platform
|
||||
if CONF_BOARD not in core_conf:
|
||||
raise ESPHomeYAMLError("esphomeyaml.board not specified.")
|
||||
core.BOARD = unicode(core_conf[CONF_BOARD])
|
||||
core.SIMPLIFY = cv.boolean(core_conf.get(CONF_SIMPLIFY, True))
|
||||
core_config.preload_core_config(config)
|
||||
|
||||
try:
|
||||
result = validate_config(config)
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import uuid as uuid_
|
||||
|
||||
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, \
|
||||
CONF_NAME, CONF_PAYLOAD_AVAILABLE, \
|
||||
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
|
||||
|
||||
|
||||
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_dict = vol.All(
|
||||
|
@ -598,6 +612,28 @@ def dimensions(value):
|
|||
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()
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ MINOR_VERSION = 7
|
|||
PATCH_VERSION = '0'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
ESPHOMELIB_VERSION = '1.7.0'
|
||||
|
||||
ESP_PLATFORM_ESP32 = 'ESP32'
|
||||
ESP_PLATFORM_ESP8266 = 'ESP8266'
|
||||
|
@ -16,9 +17,14 @@ CONF_ESPHOMEYAML = 'esphomeyaml'
|
|||
CONF_NAME = 'name'
|
||||
CONF_PLATFORM = 'platform'
|
||||
CONF_BOARD = 'board'
|
||||
CONF_SIMPLIFY = 'simplify'
|
||||
CONF_USE_BUILD_FLAGS = 'use_build_flags'
|
||||
CONF_LIBRARY_URI = 'library_uri'
|
||||
CONF_ESPHOMELIB_VERSION = 'esphomelib_version'
|
||||
CONF_USE_CUSTOM_CODE = 'use_custom_code'
|
||||
CONF_ARDUINO_VERSION = 'arduino_version'
|
||||
CONF_LOCAL = 'local'
|
||||
CONF_REPOSITORY = 'repository'
|
||||
CONF_COMMIT = 'commit'
|
||||
CONF_TAG = 'tag'
|
||||
CONF_BRANCH = 'branch'
|
||||
CONF_LOGGER = 'logger'
|
||||
CONF_WIFI = 'wifi'
|
||||
CONF_SSID = 'ssid'
|
||||
|
@ -323,27 +329,17 @@ CONF_COLD_WHITE = 'cold_white'
|
|||
CONF_WARM_WHITE = 'warm_white'
|
||||
CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature'
|
||||
CONF_WARM_WHITE_COLOR_TEMPERATURE = 'warm_white_color_temperature'
|
||||
|
||||
ESP32_BOARDS = [
|
||||
'featheresp32', 'node32s', 'espea32', 'firebeetle32', 'esp32doit-devkit-v1',
|
||||
'pocket_32', 'espectro32', 'esp32vn-iot-uno', 'esp320', 'esp-wrover-kit',
|
||||
'esp32dev', 'heltec_wifi_kit32', 'heltec_wifi_lora_32', 'hornbill32dev',
|
||||
'hornbill32minima', 'intorobot', 'm5stack-core-esp32', 'mhetesp32devkit',
|
||||
'mhetesp32minikit', 'nano32', 'microduino-core-esp32', 'nodemcu-32s',
|
||||
'quantum', 'esp32-evb', 'esp32-gateway', 'onehorse32dev', 'esp32thing',
|
||||
'espino32', 'lolin32', 'wemosbat', 'widora-air', 'nina_w10',
|
||||
]
|
||||
|
||||
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
|
||||
}
|
||||
CONF_ON_LOOP = 'on_loop'
|
||||
CONF_ON_TIME = 'on_time'
|
||||
CONF_SECONDS = 'seconds'
|
||||
CONF_MINUTES = 'minutes'
|
||||
CONF_HOURS = 'hours'
|
||||
CONF_DAYS_OF_MONTH = 'days_of_month'
|
||||
CONF_MONTHS = 'months'
|
||||
CONF_DAYS_OF_WEEK = 'days_of_week'
|
||||
CONF_CRON = 'cron'
|
||||
|
||||
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
|
||||
SIMPLIFY = True
|
||||
ESP_PLATFORM = ''
|
||||
BOARD = ''
|
||||
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 logging
|
||||
import os
|
||||
import re
|
||||
from collections import OrderedDict, deque
|
||||
|
||||
|
@ -85,8 +86,6 @@ class AssignmentExpression(Expression):
|
|||
|
||||
def __str__(self):
|
||||
type_ = self.type
|
||||
if core.SIMPLIFY:
|
||||
type_ = u'auto'
|
||||
return u"{} {}{} = {}".format(type_, self.modifier, self.name, self.rhs)
|
||||
|
||||
def has_side_effects(self):
|
||||
|
@ -662,3 +661,7 @@ def color(the_color, message='', reset=None):
|
|||
if not message:
|
||||
return parse_colors(the_color)
|
||||
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__)
|
||||
|
||||
ESP8266_PINS = {
|
||||
'A0': 17, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14,
|
||||
}
|
||||
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
|
||||
ESP8266_BASE_PINS = {
|
||||
'A0': 17, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14, 'SDA': 4, 'SCL': 5, 'RX': 3, 'TX': 1
|
||||
}
|
||||
|
||||
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,
|
||||
'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,
|
||||
'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,
|
||||
}
|
||||
ESP32_NODEMCU_32S_PINS = dict(ESP32_PINS, **{
|
||||
'LED': 2,
|
||||
})
|
||||
ESP32_LOLIN32_PINS = dict(ESP32_PINS, **{
|
||||
'LED': 5
|
||||
})
|
||||
ESP32_BOARD_TO_PINS = {
|
||||
'nodemcu-32s': ESP32_NODEMCU_32S_PINS,
|
||||
'lolin32': ESP32_LOLIN32_PINS,
|
||||
|
||||
ESP32_BOARD_PINS = {
|
||||
'alksesp32': {'D0': 40, 'D1': 41, 'D2': 15, 'D3': 2, 'D4': 0, 'D5': 4, 'D6': 16, 'D7': 17,
|
||||
'D8': 5, 'D9': 18, 'D10': 19, 'D11': 21, 'D12': 22, 'D13': 23, 'A0': 32, 'A1': 33,
|
||||
'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,
|
||||
'SW2': 2, 'SW3': 0, 'POT1': 32, 'POT2': 33, 'PIEZO1': 19, 'PIEZO2': 18,
|
||||
'PHOTO': 25, 'DHT_PIN': 26, 'S1': 4, 'S2': 16, 'S3': 18, 'S4': 19, 'S5': 21,
|
||||
'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):
|
||||
if isinstance(value, dict) or value is None:
|
||||
raise vol.Invalid(u"This variable only supports pin numbers, not full pin schemas "
|
||||
|
@ -75,27 +178,7 @@ def _translate_pin(value):
|
|||
pass
|
||||
if value.startswith('GPIO'):
|
||||
return vol.Coerce(int)(value[len('GPIO'):].strip())
|
||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
|
||||
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.")
|
||||
return _lookup_pin(core.ESP_PLATFORM, core.BOARD, value)
|
||||
|
||||
|
||||
def validate_gpio_pin(value):
|
||||
|
|
|
@ -8,12 +8,13 @@ import voluptuous as vol
|
|||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import mqtt
|
||||
from esphomeyaml.const import ESP_BOARDS_FOR_PLATFORM, ESP_PLATFORMS, ESP_PLATFORM_ESP32, \
|
||||
ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.const import ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.helpers import color
|
||||
|
||||
|
||||
# pylint: disable=anomalous-backslash-in-string
|
||||
from esphomeyaml.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS
|
||||
|
||||
CORE_BIG = """ _____ ____ _____ ______
|
||||
/ ____/ __ \| __ \| ____|
|
||||
| | | | | | |__) | |__
|
||||
|
@ -187,11 +188,12 @@ def wizard(path):
|
|||
# Don't sleep because user needs to copy link
|
||||
if platform == ESP_PLATFORM_ESP32:
|
||||
print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s')))
|
||||
boards = list(ESP32_BOARD_PINS.keys())
|
||||
else:
|
||||
print("For example \"{}\".".format(color("bold_white", 'nodemcuv2')))
|
||||
boards = list(ESP8266_BOARD_PINS.keys())
|
||||
while True:
|
||||
board = raw_input(color("bold_white", "(board): "))
|
||||
boards = ESP_BOARDS_FOR_PLATFORM[platform]
|
||||
try:
|
||||
board = vol.All(vol.Lower, vol.Any(*boards))(board)
|
||||
break
|
||||
|
|
|
@ -2,14 +2,17 @@ from __future__ import print_function
|
|||
|
||||
import codecs
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
|
||||
from esphomeyaml import core
|
||||
from esphomeyaml.config import iter_components
|
||||
from esphomeyaml.const import CONF_BOARD, CONF_BOARD_FLASH_MODE, CONF_ESPHOMEYAML, \
|
||||
CONF_LIBRARY_URI, \
|
||||
CONF_NAME, CONF_PLATFORM, CONF_USE_BUILD_FLAGS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.const import CONF_ARDUINO_VERSION, CONF_BOARD, CONF_BOARD_FLASH_MODE, \
|
||||
CONF_ESPHOMELIB_VERSION, CONF_ESPHOMEYAML, CONF_LOCAL, CONF_NAME, CONF_USE_CUSTOM_CODE, \
|
||||
ESP_PLATFORM_ESP32, ARDUINO_VERSION_ESP32_DEV
|
||||
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_END = u'// =========== AUTO GENERATED CODE END ============'
|
||||
|
@ -59,11 +62,6 @@ build_flags =
|
|||
${{common.build_flags}}
|
||||
"""
|
||||
|
||||
PLATFORM_TO_PLATFORMIO = {
|
||||
ESP_PLATFORM_ESP32: 'espressif32',
|
||||
ESP_PLATFORM_ESP8266: 'espressif8266'
|
||||
}
|
||||
|
||||
|
||||
def get_build_flags(config, key):
|
||||
build_flags = set()
|
||||
|
@ -81,19 +79,16 @@ def get_build_flags(config, key):
|
|||
return build_flags
|
||||
|
||||
|
||||
def get_ini_content(config):
|
||||
def get_ini_content(config, path):
|
||||
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 = {
|
||||
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'build_flags': u'',
|
||||
}
|
||||
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.add(u"-DESPHOMEYAML_USE")
|
||||
|
@ -106,13 +101,48 @@ def get_ini_content(config):
|
|||
options[u'build_flags'] = u'\n '.join(build_flags)
|
||||
|
||||
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')
|
||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
|
||||
lib_deps |= {
|
||||
'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
|
||||
lib_deps = sorted(x for x in lib_deps if x)
|
||||
if lib_deps:
|
||||
|
@ -178,7 +208,7 @@ def write_platformio_ini(content, path):
|
|||
|
||||
def write_platformio_project(config, path):
|
||||
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:
|
||||
content += 'board_build.partitions = partitions.csv\n'
|
||||
partitions_csv = os.path.join(path, 'partitions.csv')
|
||||
|
|
|
@ -2,10 +2,12 @@ esphomeyaml:
|
|||
name: test1
|
||||
platform: ESP32
|
||||
board: nodemcu-32s
|
||||
# Use latest esphomelib git version. TODO: Change this
|
||||
library_uri: 'https://github.com/OttoWinter/esphomelib.git'
|
||||
simplify: false
|
||||
use_build_flags: yes
|
||||
# Use latest upstream esphomelib git version.
|
||||
esphomelib_version: dev
|
||||
# Use this for testing while developing:
|
||||
# esphomelib_version:
|
||||
# local: ~/path/to/esphomelib
|
||||
use_custom_code: false
|
||||
on_boot:
|
||||
priority: 150.0
|
||||
then:
|
||||
|
@ -15,6 +17,10 @@ esphomeyaml:
|
|||
then:
|
||||
- lambda: >-
|
||||
ESP_LOGD("main", "ON SHUTDOWN!");
|
||||
on_loop:
|
||||
then:
|
||||
- lambda: >-
|
||||
ESP_LOGV("main", "ON LOOP!");
|
||||
build_path: build
|
||||
|
||||
wifi:
|
||||
|
@ -55,7 +61,7 @@ mqtt:
|
|||
qos: 0
|
||||
then:
|
||||
- lambda: >-
|
||||
ESP_LOGD("main", "Got message %s", x);
|
||||
ESP_LOGD("main", "Got message %s", x.c_str());
|
||||
- topic: livingroom/ota_mode
|
||||
then:
|
||||
- deep_sleep.prevent:
|
||||
|
@ -905,6 +911,10 @@ time:
|
|||
- 0.pool.ntp.org
|
||||
- 1.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:
|
||||
- platform: template
|
||||
|
|
Loading…
Reference in a new issue