1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-15 15:18:16 +00:00

Merge branch 'ethernet' into custom-sensor

# Conflicts:
#	esphomeyaml/config.py
This commit is contained in:
Otto Winter 2018-12-03 22:17:08 +01:00
commit aaed9a878d
No known key found for this signature in database
GPG Key ID: DB66C0BE6013F97E
4 changed files with 145 additions and 57 deletions

View File

@ -22,7 +22,7 @@ from esphomeyaml.util import run_external_command, safe_print
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PRE_INITIALIZE = ['esphomeyaml', 'logger', 'wifi', 'ota', 'mqtt', 'web_server', 'i2c'] PRE_INITIALIZE = ['esphomeyaml', 'logger', 'wifi', 'ethernet', 'ota', 'mqtt', 'web_server', 'i2c']
def get_serial_ports(): def get_serial_ports():

View File

@ -0,0 +1,70 @@
import voluptuous as vol
from esphomeyaml import pins
from esphomeyaml.components import wifi
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_DOMAIN, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_TYPE, \
ESP_PLATFORM_ESP32
from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.cpp_helpers import gpio_output_pin_expression
from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns
CONFLICTS_WITH = ['wifi']
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
CONF_PHY_ADDR = 'phy_addr'
CONF_MDC_PIN = 'mdc_pin'
CONF_MDIO_PIN = 'mdio_pin'
CONF_CLK_MODE = 'clk_mode'
CONF_POWER_PIN = 'power_pin'
EthernetType = esphomelib_ns.enum('EthernetType')
ETHERNET_TYPES = {
'LAN8720': EthernetType.ETHERNET_TYPE_LAN8720,
'TLK110': EthernetType.ETHERNET_TYPE_TLK110,
}
eth_clock_mode_t = global_ns.enum('eth_clock_mode_t')
CLK_MODES = {
'GPIO0_IN': eth_clock_mode_t.ETH_CLOCK_GPIO0_IN,
'GPIO0_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO0_OUT,
'GPIO16_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO16_OUT,
'GPIO17_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO17_OUT,
}
EthernetComponent = esphomelib_ns.class_('EthernetComponent', Component)
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(EthernetComponent),
vol.Required(CONF_TYPE): cv.one_of(*ETHERNET_TYPES, upper=True),
vol.Required(CONF_MDC_PIN): pins.output_pin,
vol.Required(CONF_MDIO_PIN): pins.input_output_pin,
vol.Optional(CONF_CLK_MODE, default='GPIO0_IN'): cv.one_of(*CLK_MODES, upper=True),
vol.Optional(CONF_PHY_ADDR, default=0): vol.All(cv.int_, vol.Range(min=0, max=31)),
vol.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_MANUAL_IP): wifi.STA_MANUAL_IP_SCHEMA,
vol.Optional(CONF_HOSTNAME): cv.hostname,
vol.Optional(CONF_DOMAIN, default='.local'): cv.domain_name,
})
def to_code(config):
rhs = App.init_ethernet()
eth = Pvariable(config[CONF_ID], rhs)
add(eth.set_phy_addr(config[CONF_PHY_ADDR]))
add(eth.set_mdc_pin(config[CONF_MDC_PIN]))
add(eth.set_mdio_pin(config[CONF_MDIO_PIN]))
add(eth.set_type(ETHERNET_TYPES[config[CONF_TYPE]]))
add(eth.set_clk_mode(CLK_MODES[config[CONF_CLK_MODE]]))
if CONF_POWER_PIN in config:
for pin in gpio_output_pin_expression(config[CONF_POWER_PIN]):
yield
add(eth.set_power_pin(pin))
if CONF_HOSTNAME in config:
add(eth.set_hostname(config[CONF_HOSTNAME]))
if CONF_MANUAL_IP in config:
add(eth.set_manual_ip(wifi.manual_ip(config[CONF_MANUAL_IP])))

View File

@ -17,11 +17,7 @@ from esphomeyaml.util import safe_print
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
REQUIRED_COMPONENTS = [
CONF_ESPHOMEYAML, CONF_WIFI
]
_COMPONENT_CACHE = {} _COMPONENT_CACHE = {}
_ALL_COMPONENTS = []
def get_component(domain): def get_component(domain):
@ -140,29 +136,55 @@ def do_id_pass(result):
def validate_config(config): def validate_config(config):
global _ALL_COMPONENTS
for req in REQUIRED_COMPONENTS:
if req not in config:
raise EsphomeyamlError("Component {} is required for esphomeyaml.".format(req))
_ALL_COMPONENTS = list(config.keys())
result = Config() result = Config()
def _comp_error(ex, domain, config, path): def _comp_error(ex, domain, config, path):
result.add_error(_format_config_error(ex, domain, config), domain, config, path) result.add_error(_format_config_error(ex, domain, config), domain, config, path)
skip_domains = set()
# Step 1: Load everything # Step 1: Load everything
for domain, conf in config.iteritems(): for domain, conf in config.iteritems():
domain = str(domain) domain = str(domain)
if domain == CONF_ESPHOMEYAML or domain.startswith(u'.'): if domain == CONF_ESPHOMEYAML or domain.startswith(u'.'):
skip_domains.add(domain)
continue continue
if conf is None: if conf is None:
conf = {} conf = {}
component = get_component(domain) component = get_component(domain)
if component is None: if component is None:
result.add_error(u"Component not found: {}".format(domain), domain, conf, None) result.add_error(u"Component not found: {}".format(domain), domain, conf, None)
skip_domains.add(domain)
continue
success = True
dependencies = getattr(component, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in config:
result.add_error(u"Component {} requires component {}".format(domain, dependency),
domain, conf)
success = False
if not success:
skip_domains.add(domain)
continue
success = True
conflicts_with = getattr(component, 'CONFLICTS_WITH', [])
for conflict in conflicts_with:
if conflict not in config:
result.add_error(u"Component {} cannot be used together with component {}"
u"".format(domain, conflict),
domain, conf)
success = False
if not success:
skip_domains.add(domain)
continue
esp_platforms = getattr(component, 'ESP_PLATFORMS', ESP_PLATFORMS)
if CORE.esp_platform not in esp_platforms:
result.add_error(u"Component {} doesn't support {}.".format(domain, CORE.esp_platform),
domain, conf)
skip_domains.add(domain)
continue continue
if not hasattr(component, 'PLATFORM_SCHEMA'): if not hasattr(component, 'PLATFORM_SCHEMA'):
@ -180,6 +202,39 @@ def validate_config(config):
platform = get_platform(domain, p_name) platform = get_platform(domain, p_name)
if platform is None: if platform is None:
result.add_error(u"Platform not found: '{}'".format(p_domain), p_domain, p_config) result.add_error(u"Platform not found: '{}'".format(p_domain), p_domain, p_config)
skip_domains.add(p_domain)
continue
success = True
dependencies = getattr(platform, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in config:
result.add_error(
u"Platform {} requires component {}".format(p_domain, dependency),
p_domain, p_config)
success = False
if not success:
skip_domains.add(p_domain)
continue
success = True
conflicts_with = getattr(platform, 'CONFLICTS_WITH', [])
for conflict in conflicts_with:
if conflict not in config:
result.add_error(u"Platform {} cannot be used together with component {}"
u"".format(p_domain, conflict),
domain, conf)
success = False
if not success:
skip_domains.add(p_domain)
continue
esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS)
if CORE.esp_platform not in esp_platforms:
result.add_error(
u"Platform {} doesn't support {}.".format(p_domain, CORE.esp_platform),
p_domain, p_config)
skip_domains.add(p_domain)
continue continue
# Step 2: Validate configuration # Step 2: Validate configuration
@ -189,30 +244,12 @@ def validate_config(config):
_comp_error(ex, CONF_ESPHOMEYAML, config[CONF_ESPHOMEYAML]) _comp_error(ex, CONF_ESPHOMEYAML, config[CONF_ESPHOMEYAML])
for domain, conf in config.iteritems(): for domain, conf in config.iteritems():
if domain == CONF_ESPHOMEYAML or domain.startswith('.'):
continue
if conf is None: if conf is None:
conf = {} conf = {}
domain = str(domain) domain = str(domain)
if domain in skip_domains:
continue
component = get_component(domain) component = get_component(domain)
if component is None:
continue
esp_platforms = getattr(component, 'ESP_PLATFORMS', ESP_PLATFORMS)
if CORE.esp_platform not in esp_platforms:
result.add_error(u"Component {} doesn't support {}.".format(domain, CORE.esp_platform),
domain, conf)
continue
success = True
dependencies = getattr(component, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in _ALL_COMPONENTS:
result.add_error(u"Component {} requires component {}".format(domain, dependency),
domain, conf)
success = False
if not success:
continue
if hasattr(component, 'CONFIG_SCHEMA'): if hasattr(component, 'CONFIG_SCHEMA'):
try: try:
@ -233,27 +270,9 @@ def validate_config(config):
if p_name is None: if p_name is None:
continue continue
p_domain = u'{}.{}'.format(domain, p_name) p_domain = u'{}.{}'.format(domain, p_name)
if p_domain in skip_domains:
continue
platform = get_platform(domain, p_name) platform = get_platform(domain, p_name)
if platform is None:
continue
success = True
dependencies = getattr(platform, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in _ALL_COMPONENTS:
result.add_error(
u"Platform {} requires component {}".format(p_domain, dependency),
p_domain, p_config)
success = False
if not success:
continue
esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS)
if CORE.esp_platform not in esp_platforms:
result.add_error(
u"Platform {} doesn't support {}.".format(p_domain, CORE.esp_platform),
p_domain, p_config)
continue
if hasattr(platform, u'PLATFORM_SCHEMA'): if hasattr(platform, u'PLATFORM_SCHEMA'):
try: try:
@ -268,9 +287,6 @@ def validate_config(config):
return result return result
REQUIRED = ['esphomeyaml', 'wifi']
def _nested_getitem(data, path): def _nested_getitem(data, path):
for item_index in path: for item_index in path:
try: try:
@ -298,7 +314,6 @@ def _format_config_error(ex, domain, config, recursion=False):
_format_config_error(sub_error, domain, config, recursion=True) _format_config_error(sub_error, domain, config, recursion=True)
for sub_error in ex.errors for sub_error in ex.errors
))) )))
if u'extra keys not allowed' in ex.error_message: if u'extra keys not allowed' in ex.error_message:
message += u'[{}] is an invalid option for [{}].' \ message += u'[{}] is an invalid option for [{}].' \
.format(ex.path[-1], domain) .format(ex.path[-1], domain)

View File

@ -243,6 +243,9 @@ def analog_pin(value):
raise NotImplementedError raise NotImplementedError
input_output_pin = vol.All(input_pin, output_pin)
PIN_MODES_ESP8266 = [ PIN_MODES_ESP8266 = [
'INPUT', 'OUTPUT', 'INPUT_PULLUP', 'OUTPUT_OPEN_DRAIN', 'SPECIAL', 'FUNCTION_1', 'INPUT', 'OUTPUT', 'INPUT_PULLUP', 'OUTPUT_OPEN_DRAIN', 'SPECIAL', 'FUNCTION_1',
'FUNCTION_2', 'FUNCTION_3', 'FUNCTION_4', 'FUNCTION_2', 'FUNCTION_3', 'FUNCTION_4',