1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-12 21:05:46 +00:00

Compare commits

...

44 Commits

Author SHA1 Message Date
Otto Winter
e47bcb9abb Bump version to 1.6.2 2018-06-06 21:01:20 +02:00
Otto Winter
30b94f06b3 Add verbose mode for espota 2018-06-06 11:12:42 +02:00
Otto Winter
19dfdb77eb Fix MQTT logs 2018-06-06 11:12:29 +02:00
Otto Winter
b6e7ad3589 Fix OTA port not being set 2018-06-06 11:12:14 +02:00
Otto Winter
1267680379 Improve error messages 2018-06-06 10:27:59 +02:00
Otto Winter
b5f6b32fad Fix dallas resolution 2018-06-06 10:27:50 +02:00
Otto Winter
7068808d4f Fix optional returns from templates 2018-06-06 09:48:59 +02:00
Otto Winter
c82a44d541 Fix ESP32 touch sleep duration conversion 2018-06-06 09:30:14 +02:00
Otto Winter
e650473682 Fix ESP32 touch ID issue 2018-06-06 09:26:56 +02:00
Otto Winter
2ee0d4242d Make Automation output readable again 2018-06-06 09:18:39 +02:00
Otto Winter
b2aecf29dc Fix ESP32 BLE 2018-06-06 09:18:21 +02:00
Otto Winter
081c2f4e07 Fix SHT3xD with manual update interval 2018-06-06 09:06:14 +02:00
Otto Winter
0c77228421 Improve wrong pin error message 2018-06-06 08:55:53 +02:00
Otto Winter
8a509c6551 Fix MQTT publish 2018-06-06 08:35:31 +02:00
Otto Winter
d249820bcd Fix MQTT availability option 2018-06-06 08:35:23 +02:00
Otto Winter
f39cf52eae Fix WiFi domain option 2018-06-06 08:13:05 +02:00
Otto Winter
63fb252b46 Fix web server CSS/JS URL 2018-06-06 08:12:51 +02:00
Otto Winter
2f98adca49 Fix OrFilter 2018-06-06 08:12:39 +02:00
Otto Winter
084fc00517 Fix MQTT messages 2018-06-06 08:12:30 +02:00
Otto Winter
abeac23abd Fix i2c frequency 2018-06-06 08:12:17 +02:00
Otto Winter
7264e3a4bf Fix ultrasonic typo Fixes #62 2018-06-06 07:09:03 +02:00
Otto Winter
16eeb3af31 Attempt to solve UnicodeEncodeError in HassIO when running on RPi 2018-06-05 23:19:46 +02:00
Otto Winter
b799d2df7f Adjust serial port fetch interval 2018-06-05 23:19:28 +02:00
Otto Winter
11d55fec4f Better OSError handling for YAML parser 2018-06-05 23:18:56 +02:00
Otto Winter
923a5990c7 Fix erroneous validation. Fixes OttoWinter/esphomelib#59 2018-06-05 22:32:34 +02:00
Otto Winter
a0a615c335 Deep Sleep wakeup pin mode 2018-06-05 22:31:39 +02:00
Otto Winter
e9ced0cc3f Fix lint 2018-06-04 20:47:29 +02:00
Otto Winter
1a92381994 Update Dockerfile 2018-06-04 20:47:23 +02:00
Otto Winter
a07a7a87a2 Fix filter out nan filter 2018-06-04 20:47:15 +02:00
Otto Winter
6a823f5777 Bump version to 1.6.1 2018-06-03 23:45:57 +02:00
Otto Winter
419c5afe27 Update Dockerfiles 2018-06-03 23:45:29 +02:00
Otto Winter
17798dee1e HassIO add-on pre-built images 2018-06-03 19:22:25 +02:00
Otto Winter
ee2c53585f Add Sonoff S20 example 2018-06-03 13:00:40 +02:00
Otto Winter
2f05acfa5a Validate configuration button 2018-06-03 12:16:43 +02:00
Otto Winter
f4d393a59e Fix dashboard upload port selection 2018-06-03 11:18:53 +02:00
Otto Winter
967aa53bad add_job 2018-06-03 07:11:11 +02:00
Otto Winter
4f3f460105 ESP32 Hall Sensor 2018-06-02 23:25:13 +02:00
Otto Winter
6e85a741ae New coroutine-based task execution 2018-06-02 22:22:20 +02:00
Otto Winter
2db45898e2 Sonoff 4CH example with automation 2018-06-02 15:41:11 +02:00
Otto Winter
eb62599a98 ADC VCC support Fixes #26 2018-06-02 13:43:49 +02:00
Otto Winter
9f0737e5b9 Fix pylint... Again... 2018-06-01 23:01:31 +02:00
Otto Winter
7a393c1a3a Fix template/switch cover example. Fixes #27 2018-06-01 22:58:23 +02:00
Otto Winter
4fa7bc196a Warn about tornado. Fixes #24 2018-06-01 22:49:14 +02:00
Brandon Davidson
65d0dd47f3 Fix #27 - invalid code gen for Template Cover (#29) 2018-06-01 22:48:07 +02:00
93 changed files with 1859 additions and 948 deletions

View File

@@ -4,7 +4,7 @@ python:
- "2.7"
install:
- pip install -r requirements.txt
- pip install flake8==3.5.0 pylint==1.8.4
- pip install tornado esptool flake8==3.5.0 pylint==1.8.4
script:
- flake8 esphomeyaml
- pylint esphomeyaml

View File

@@ -0,0 +1,43 @@
# Dockerfile for HassIO add-on
ARG BUILD_FROM=ubuntu:bionic
FROM ${BUILD_FROM}
# Re-declare BUILD_FROM to fix weird docker issue
ARG BUILD_FROM
# On amd64 and alike, using ubuntu as the base is better as building
# for the ESP32 only works with glibc (and ubuntu). However, on armhf
# the build toolchain frequently procudes segfaults under ubuntu.
# -> Use ubuntu for most architectures, except alpine for armhf
#
# * python and related required because this is a python project
# * git required for platformio library dependencies downloads
# * libc6-compat and openssh required on alpine for weird reasons
# * disable platformio telemetry on install
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
apt-get update && apt-get install -y --no-install-recommends \
python python-pip python-setuptools git && \
rm -rf /var/lib/apt/lists/* /tmp/*; \
else \
apk add --no-cache python2 py2-pip git openssh libc6-compat; \
fi" && \
pip install --no-cache-dir platformio && \
platformio settings set enable_telemetry No
# Create fake project to make platformio install all depdencies.
# * Ignore build errors from platformio - empty project
# * On alpine, only install ESP8266 toolchain
COPY platformio.ini /pio/platformio.ini
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
platformio run -e espressif32 -e espressif8266 -d /pio; exit 0; \
else \
echo \"\$(head -8 /pio/platformio.ini)\" >/pio/platformio.ini; \
platformio run -e espressif8266 -d /pio; exit 0; \
fi"
# Install latest esphomeyaml from git
RUN pip install --no-cache-dir \
git+git://github.com/OttoWinter/esphomeyaml.git
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]

View File

@@ -0,0 +1,10 @@
{
"squash": false,
"build_from": {
"aarch64": "arm64v8/ubuntu:bionic",
"amd64": "ubuntu:bionic",
"armhf": "homeassistant/armhf-base:latest",
"i386": "i386/ubuntu:bionic"
},
"args": {}
}

View File

@@ -0,0 +1,29 @@
{
"name": "esphomeyaml-edge",
"version": "dev",
"slug": "esphomeyaml-edge",
"description": "Development build of the esphomeyaml HassIO add-on.",
"url": "https://esphomelib.com/esphomeyaml/index.html",
"startup": "application",
"webui": "http://[HOST]:[PORT:6052]",
"boot": "auto",
"ports": {
"6052/tcp": 6052,
"6053/tcp": 6053
},
"arch": [
"aarch64",
"amd64",
"armhf",
"i386"
],
"auto_uart": true,
"map": [
"config:rw"
],
"options": {},
"environment": {
"ESPHOMEYAML_OTA_HOST_PORT": "6053"
},
"schema": {}
}

View File

@@ -0,0 +1,12 @@
; This file allows the docker build file to install the required platformio
; platforms
[env:espressif8266]
platform = espressif8266
board = nodemcuv2
framework = arduino
[env:espressif32]
platform = espressif32
board = nodemcu-32s
framework = arduino

View File

@@ -1,20 +1,44 @@
# Dockerfile for HassIO add-on
ARG BUILD_FROM=ubuntu:bionic
FROM ${BUILD_FROM}
# Re-declare BUILD_FROM to fix weird docker issue
ARG BUILD_FROM
FROM $BUILD_FROM
ARG BUILD_VERSION
ENV LANG C.UTF-8
# Install requirements for add-on
RUN apk add --no-cache python2 py2-pip git openssh libc6-compat && \
# On amd64 and alike, using ubuntu as the base is better as building
# for the ESP32 only works with glibc (and ubuntu). However, on armhf
# the build toolchain frequently procudes segfaults under ubuntu.
# -> Use ubuntu for most architectures, except alpine for armhf
#
# * python and related required because this is a python project
# * git required for platformio library dependencies downloads
# * libc6-compat and openssh required on alpine for weird reasons
# * disable platformio telemetry on install
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
apt-get update && apt-get install -y --no-install-recommends \
python python-pip python-setuptools git && \
rm -rf /var/lib/apt/lists/* /tmp/*; \
else \
apk add --no-cache python2 py2-pip git openssh libc6-compat; \
fi" && \
pip install --no-cache-dir platformio && \
platformio platform install espressif8266 \
--with-package tool-esptool \
--with-package framework-arduinoespressif8266 \
--with-package tool-mkspiffs \
--with-package tool-espotapy
platformio settings set enable_telemetry No
# Create fake project to make platformio install all depdencies.
# * Ignore build errors from platformio - empty project
# * On alpine, only install ESP8266 toolchain
COPY platformio.ini /pio/platformio.ini
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
platformio run -e espressif32 -e espressif8266 -d /pio; \
else \
echo \"\$(head -8 /pio/platformio.ini)\" >/pio/platformio.ini; \
platformio run -e espressif8266 -d /pio; \
fi"; exit 0
# Install latest esphomeyaml from git
RUN pip install --no-cache-dir \
git+git://github.com/OttoWinter/esphomeyaml.git@v1.6.0 \
tornado esptool
esphomeyaml==${BUILD_VERSION}
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]

View File

@@ -1,11 +1,11 @@
from __future__ import print_function
import argparse
from datetime import datetime
import logging
import os
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
@@ -13,7 +13,7 @@ from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, CON
CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, ESP_PLATFORM_ESP8266
from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
add_task, color, get_variable, indent, quote, statement
add_job, color, flush_tasks, indent, quote, statement
_LOGGER = logging.getLogger(__name__)
@@ -102,40 +102,34 @@ def run_miniterm(config, port, escape=False):
with serial.Serial(port, baudrate=baud_rate) as ser:
while True:
line = ser.readline()
line = ser.readline().replace('\r', '').replace('\n', '')
time = datetime.now().time().strftime('[%H:%M:%S]')
message = time + line.decode('unicode-escape').replace('\r', '').replace('\n', '')
message = time + line
if escape:
message = message.replace('\033', '\\033').encode('ascii', 'replace')
print(message)
message = message.replace('\033', '\\033')
try:
print(message)
except UnicodeEncodeError:
print(message.encode('ascii', 'backslashreplace'))
def write_cpp(config):
_LOGGER.info("Generating C++ source...")
add_task(core_to_code, config[CONF_ESPHOMEYAML])
add_job(core_to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml')
for domain in PRE_INITIALIZE:
if domain == CONF_ESPHOMEYAML:
if domain == CONF_ESPHOMEYAML or domain not in config:
continue
if domain in config:
add_task(get_component(domain).to_code, config[domain])
# Clear queue
get_variable(None)
add(RawStatement(''))
add_job(get_component(domain).to_code, config[domain], domain=domain)
for domain, component, conf in iter_components(config):
if domain in PRE_INITIALIZE:
if domain in PRE_INITIALIZE or not hasattr(component, 'to_code'):
continue
if not hasattr(component, 'to_code'):
continue
add_task(component.to_code, conf)
add_job(component.to_code, conf, domain=domain)
# Clear queue
get_variable(None)
flush_tasks()
add(RawStatement(''))
add(RawStatement(''))
all_code = []
for exp in _EXPRESSIONS:
if core.SIMPLIFY:
@@ -157,9 +151,12 @@ def write_cpp(config):
return 0
def compile_program(config):
def compile_program(args, config):
_LOGGER.info("Compiling app...")
return run_platformio('platformio', 'run', '-d', get_base_path(config))
command = ['platformio', 'run', '-d', get_base_path(config)]
if args.verbose:
command.append('-v')
return run_platformio(*command)
def get_upload_host(config):
@@ -188,8 +185,11 @@ def upload_program(config, args, port):
if port != 'OTA':
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266 and args.use_esptoolpy:
return upload_using_esptool(config, port)
return run_platformio('platformio', 'run', '-d', get_base_path(config),
'-t', 'upload', '--upload-port', port)
command = ['platformio', 'run', '-d', get_base_path(config),
'-t', 'upload', '--upload-port', port]
if args.verbose:
command.append('-v')
return run_platformio(*command)
if 'ota' not in config:
_LOGGER.error("No serial port found and OTA not enabled. Can't upload!")
@@ -208,6 +208,8 @@ def upload_program(config, args, port):
espota_args = ['espota.py', '--debug', '--progress', '-i', host,
'-p', str(ota.get_port(config)), '-f', bin_file,
'-a', ota.get_auth(config), '-P', str(host_port)]
if args.verbose:
espota_args.append('-d')
return espota.main(espota_args)
@@ -223,8 +225,9 @@ def clean_mqtt(config, args):
return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id)
def setup_log():
logging.basicConfig(level=logging.INFO)
def setup_log(debug=False):
log_level = logging.DEBUG if debug else logging.INFO
logging.basicConfig(level=log_level)
fmt = "%(levelname)s [%(name)s] %(message)s"
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
datefmt = '%H:%M:%S'
@@ -253,7 +256,28 @@ def command_wizard(args):
return wizard.wizard(args.configuration)
def strip_default_ids(config):
value = config
if isinstance(config, list):
value = type(config)()
for x in config:
if isinstance(x, core.ID) and not x.is_manual:
continue
value.append(strip_default_ids(x))
return value
elif isinstance(config, dict):
value = type(config)()
for k, v in config.iteritems():
if isinstance(v, core.ID) and not v.is_manual:
continue
value[k] = strip_default_ids(v)
return value
return value
def command_config(args, config):
if not args.verbose:
config = strip_default_ids(config)
print(yaml_util.dump(config))
return 0
@@ -262,7 +286,7 @@ def command_compile(args, config):
exit_code = write_cpp(config)
if exit_code != 0:
return exit_code
exit_code = compile_program(config)
exit_code = compile_program(args, config)
if exit_code != 0:
return exit_code
_LOGGER.info(u"Successfully compiled program.")
@@ -287,7 +311,7 @@ def command_run(args, config):
exit_code = write_cpp(config)
if exit_code != 0:
return exit_code
exit_code = compile_program(config)
exit_code = compile_program(args, config)
if exit_code != 0:
return exit_code
_LOGGER.info(u"Successfully compiled program.")
@@ -339,6 +363,8 @@ POST_CONFIG_ACTIONS = {
def parse_args(argv):
parser = argparse.ArgumentParser(prog='esphomeyaml')
parser.add_argument('-v', '--verbose', help="Enable verbose esphomeyaml logs.",
action='store_true')
parser.add_argument('configuration', help='Your YAML configuration file.')
subparsers = parser.add_subparsers(help='Commands', dest='command')
@@ -407,8 +433,8 @@ def parse_args(argv):
def run_esphomeyaml(argv):
setup_log()
args = parse_args(argv)
setup_log(args.verbose)
if args.command in PRE_CONFIG_ACTIONS:
try:
return PRE_CONFIG_ACTIONS[args.command](args)

View File

@@ -2,15 +2,16 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import cover, fan
from esphomeyaml.const import CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, CONF_BLUE, \
CONF_BRIGHTNESS, CONF_CONDITION_ID, CONF_DELAY, CONF_EFFECT, CONF_FLASH_LENGTH, CONF_GREEN, \
CONF_ID, CONF_IF, CONF_LAMBDA, CONF_OR, CONF_OSCILLATING, CONF_PAYLOAD, \
CONF_QOS, CONF_RANGE, CONF_RED, CONF_RETAIN, CONF_SPEED, CONF_THEN, CONF_TOPIC, \
CONF_TRANSITION_LENGTH, CONF_TRIGGER_ID, CONF_WHITE, CONF_ABOVE, CONF_BELOW
from esphomeyaml.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \
CONF_BELOW, \
CONF_BLUE, CONF_BRIGHTNESS, CONF_CONDITION_ID, CONF_DELAY, CONF_EFFECT, CONF_FLASH_LENGTH, \
CONF_GREEN, CONF_ID, CONF_IF, CONF_LAMBDA, CONF_OR, CONF_OSCILLATING, CONF_PAYLOAD, CONF_QOS, \
CONF_RANGE, CONF_RED, CONF_RETAIN, CONF_SPEED, CONF_THEN, CONF_TOPIC, CONF_TRANSITION_LENGTH, \
CONF_TRIGGER_ID, CONF_WHITE
from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, TemplateArguments, add, \
bool_, esphomelib_ns, float_, get_variable, process_lambda, std_string, templatable, uint32, \
uint8
uint8, add_job
CONF_MQTT_PUBLISH = 'mqtt.publish'
CONF_LIGHT_TOGGLE = 'light.toggle'
@@ -32,7 +33,7 @@ ACTION_KEYS = [CONF_DELAY, CONF_MQTT_PUBLISH, CONF_LIGHT_TOGGLE, CONF_LIGHT_TURN
CONF_FAN_TURN_OFF, CONF_FAN_TURN_ON]
ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
cv.GenerateID('action', CONF_ACTION_ID): cv.register_variable_id,
cv.GenerateID(CONF_ACTION_ID): cv.declare_variable_id(None),
vol.Optional(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds),
vol.Optional(CONF_MQTT_PUBLISH): vol.Schema({
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
@@ -41,15 +42,15 @@ ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
vol.Optional(CONF_RETAIN): cv.templatable(cv.boolean),
}),
vol.Optional(CONF_LIGHT_TOGGLE): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
}),
vol.Optional(CONF_LIGHT_TURN_OFF): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
}),
vol.Optional(CONF_LIGHT_TURN_ON): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
vol.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'):
cv.templatable(cv.positive_time_period_milliseconds),
vol.Exclusive(CONF_FLASH_LENGTH, 'transformer'):
@@ -62,45 +63,45 @@ ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
vol.Optional(CONF_EFFECT): cv.templatable(cv.string),
}),
vol.Optional(CONF_SWITCH_TOGGLE): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_SWITCH_TURN_OFF): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_SWITCH_TURN_ON): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_OPEN): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_STOP): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_OPEN): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_COVER_STOP): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_FAN_TOGGLE): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_FAN_TURN_OFF): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
}),
vol.Optional(CONF_FAN_TURN_ON): vol.Schema({
vol.Required(CONF_ID): cv.variable_id,
vol.Required(CONF_ID): cv.use_variable_id(None),
vol.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
vol.Optional(CONF_SPEED): cv.templatable(fan.validate_fan_speed),
}),
vol.Optional(CONF_LAMBDA): cv.lambda_,
}, cv.has_at_exactly_one_key(*ACTION_KEYS))])
}, cv.has_exactly_one_key(*ACTION_KEYS))])
# pylint: disable=invalid-name
DelayAction = esphomelib_ns.DelayAction
@@ -115,7 +116,7 @@ def validate_recursive_condition(value):
CONDITION_KEYS = [CONF_AND, CONF_OR, CONF_RANGE, CONF_LAMBDA]
CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
cv.GenerateID('condition', CONF_CONDITION_ID): cv.register_variable_id,
cv.GenerateID(CONF_CONDITION_ID): cv.declare_variable_id(None),
vol.Optional(CONF_AND): validate_recursive_condition,
vol.Optional(CONF_OR): validate_recursive_condition,
vol.Optional(CONF_RANGE): vol.All(vol.Schema({
@@ -123,7 +124,7 @@ CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
vol.Optional(CONF_BELOW): vol.Coerce(float),
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)),
vol.Optional(CONF_LAMBDA): cv.lambda_,
}), cv.has_at_exactly_one_key(*CONDITION_KEYS)])
}), cv.has_exactly_one_key(*CONDITION_KEYS)])
# pylint: disable=invalid-name
AndCondition = esphomelib_ns.AndCondition
@@ -132,8 +133,8 @@ RangeCondition = esphomelib_ns.RangeCondition
LambdaCondition = esphomelib_ns.LambdaCondition
AUTOMATION_SCHEMA = vol.Schema({
cv.GenerateID('trigger', CONF_TRIGGER_ID): cv.register_variable_id,
cv.GenerateID('automation', CONF_AUTOMATION_ID): cv.register_variable_id,
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(None),
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(None),
vol.Optional(CONF_IF): CONDITIONS_SCHEMA,
vol.Required(CONF_THEN): ACTIONS_SCHEMA,
})
@@ -142,156 +143,267 @@ AUTOMATION_SCHEMA = vol.Schema({
def build_condition(config, arg_type):
template_arg = TemplateArguments(arg_type)
if CONF_AND in config:
return AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg))
if CONF_OR in config:
return OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg))
if CONF_LAMBDA in config:
return LambdaCondition.new(template_arg,
process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]))
if CONF_RANGE in config:
yield AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg))
elif CONF_OR in config:
yield OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg))
elif CONF_LAMBDA in config:
lambda_ = None
for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]):
yield
yield LambdaCondition.new(template_arg, lambda_)
elif CONF_RANGE in config:
conf = config[CONF_RANGE]
rhs = RangeCondition.new(template_arg)
condition = Pvariable(RangeCondition.template(template_arg), config[CONF_CONDITION_ID], rhs)
type = RangeCondition.template(template_arg)
condition = Pvariable(config[CONF_CONDITION_ID], rhs, type=type)
if CONF_ABOVE in conf:
condition.set_min(templatable(conf[CONF_ABOVE], arg_type, float_))
template_ = None
for template_ in templatable(conf[CONF_ABOVE], arg_type, float_):
yield
condition.set_min(template_)
if CONF_BELOW in conf:
condition.set_max(templatable(conf[CONF_BELOW], arg_type, float_))
return condition
raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
template_ = None
for template_ in templatable(conf[CONF_BELOW], arg_type, float_):
yield
condition.set_max(template_)
yield condition
else:
raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
def build_conditions(config, arg_type):
return ArrayInitializer(*[build_condition(x, arg_type) for x in config])
conditions = []
for conf in config:
condition = None
for condition in build_condition(conf, arg_type):
yield None
conditions.append(condition)
yield ArrayInitializer(*conditions)
def build_action(config, arg_type):
from esphomeyaml.components import light, mqtt, switch
template_arg = TemplateArguments(arg_type)
# Keep pylint from freaking out
var = None
if CONF_DELAY in config:
rhs = App.register_component(DelayAction.new(template_arg))
action = Pvariable(DelayAction.template(template_arg), config[CONF_ACTION_ID], rhs)
add(action.set_delay(templatable(config[CONF_DELAY], arg_type, uint32)))
return action
type = DelayAction.template(template_arg)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
template_ = None
for template_ in templatable(config[CONF_DELAY], arg_type, uint32):
yield
add(action.set_delay(template_))
yield action
elif CONF_LAMBDA in config:
rhs = LambdaAction.new(template_arg, process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]))
return Pvariable(LambdaAction.template(template_arg), config[CONF_ACTION_ID], rhs)
lambda_ = None
for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]):
yield None
rhs = LambdaAction.new(template_arg, lambda_)
type = LambdaAction.template(template_arg)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_MQTT_PUBLISH in config:
conf = config[CONF_MQTT_PUBLISH]
rhs = App.Pget_mqtt_client().Pmake_publish_action()
action = Pvariable(mqtt.MQTTPublishAction.template(template_arg), config[CONF_ACTION_ID],
rhs)
add(action.set_topic(templatable(conf[CONF_TOPIC], arg_type, std_string)))
add(action.set_payload(templatable(conf[CONF_PAYLOAD], arg_type, std_string)))
rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg)
type = mqtt.MQTTPublishAction.template(template_arg)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
template_ = None
for template_ in templatable(conf[CONF_TOPIC], arg_type, std_string):
yield None
add(action.set_topic(template_))
template_ = None
for template_ in templatable(conf[CONF_PAYLOAD], arg_type, std_string):
yield None
add(action.set_payload(template_))
if CONF_QOS in conf:
add(action.set_qos(templatable(conf[CONF_QOS], arg_type, uint8)))
template_ = None
for template_ in templatable(conf[CONF_QOS], arg_type, uint8):
yield
add(action.set_qos(template_))
if CONF_RETAIN in conf:
add(action.set_retain(templatable(conf[CONF_RETAIN], arg_type, bool_)))
return action
template_ = None
for template_ in templatable(conf[CONF_RETAIN], arg_type, bool_):
yield None
add(action.set_retain(template_))
yield action
elif CONF_LIGHT_TOGGLE in config:
conf = config[CONF_LIGHT_TOGGLE]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_toggle_action(template_arg)
action = Pvariable(light.ToggleAction.template(template_arg), config[CONF_ACTION_ID], rhs)
type = light.ToggleAction.template(template_arg)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
if CONF_TRANSITION_LENGTH in conf:
add(action.set_transition_length(
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
))
return action
template_ = None
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
yield None
add(action.set_transition_length(template_))
yield action
elif CONF_LIGHT_TURN_OFF in config:
conf = config[CONF_LIGHT_TURN_OFF]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
action = Pvariable(light.TurnOffAction.template(template_arg), config[CONF_ACTION_ID], rhs)
type = light.TurnOffAction.template(template_arg)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
if CONF_TRANSITION_LENGTH in conf:
add(action.set_transition_length(
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
))
return action
template_ = None
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
yield None
add(action.set_transition_length(template_))
yield action
elif CONF_LIGHT_TURN_ON in config:
conf = config[CONF_LIGHT_TURN_ON]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
action = Pvariable(light.TurnOnAction.template(template_arg), config[CONF_ACTION_ID], rhs)
type = light.TurnOnAction.template(template_arg)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
if CONF_TRANSITION_LENGTH in conf:
add(action.set_transition_length(
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
))
template_ = None
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
yield None
add(action.set_transition_length(template_))
if CONF_FLASH_LENGTH in conf:
add(action.set_flash_length(templatable(conf[CONF_FLASH_LENGTH], arg_type, uint32)))
template_ = None
for template_ in templatable(conf[CONF_FLASH_LENGTH], arg_type, uint32):
yield None
add(action.set_flash_length(template_))
if CONF_BRIGHTNESS in conf:
add(action.set_brightness(templatable(conf[CONF_BRIGHTNESS], arg_type, float_)))
template_ = None
for template_ in templatable(conf[CONF_BRIGHTNESS], arg_type, float_):
yield None
add(action.set_brightness(template_))
if CONF_RED in conf:
add(action.set_red(templatable(conf[CONF_RED], arg_type, float_)))
template_ = None
for template_ in templatable(conf[CONF_RED], arg_type, float_):
yield None
add(action.set_red(template_))
if CONF_GREEN in conf:
add(action.set_green(templatable(conf[CONF_GREEN], arg_type, float_)))
template_ = None
for template_ in templatable(conf[CONF_GREEN], arg_type, float_):
yield None
add(action.set_green(template_))
if CONF_BLUE in conf:
add(action.set_blue(templatable(conf[CONF_BLUE], arg_type, float_)))
template_ = None
for template_ in templatable(conf[CONF_BLUE], arg_type, float_):
yield None
add(action.set_blue(template_))
if CONF_WHITE in conf:
add(action.set_white(templatable(conf[CONF_WHITE], arg_type, float_)))
template_ = None
for template_ in templatable(conf[CONF_WHITE], arg_type, float_):
yield None
add(action.set_white(template_))
if CONF_EFFECT in conf:
add(action.set_effect(templatable(conf[CONF_EFFECT], arg_type, std_string)))
return action
template_ = None
for template_ in templatable(conf[CONF_EFFECT], arg_type, std_string):
yield None
add(action.set_effect(template_))
yield action
elif CONF_SWITCH_TOGGLE in config:
conf = config[CONF_SWITCH_TOGGLE]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_toggle_action(template_arg)
return Pvariable(switch.ToggleAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = switch.ToggleAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_SWITCH_TURN_OFF in config:
conf = config[CONF_SWITCH_TURN_OFF]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
return Pvariable(switch.TurnOffAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = switch.TurnOffAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_SWITCH_TURN_ON in config:
conf = config[CONF_SWITCH_TURN_ON]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
return Pvariable(switch.TurnOnAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = switch.TurnOnAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_COVER_OPEN in config:
conf = config[CONF_COVER_OPEN]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_open_action(template_arg)
return Pvariable(cover.OpenAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = cover.OpenAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_COVER_CLOSE in config:
conf = config[CONF_COVER_CLOSE]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_close_action(template_arg)
return Pvariable(cover.CloseAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = cover.CloseAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_COVER_STOP in config:
conf = config[CONF_COVER_STOP]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_stop_action(template_arg)
return Pvariable(cover.StopAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = cover.StopAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_FAN_TOGGLE in config:
conf = config[CONF_FAN_TOGGLE]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_toggle_action(template_arg)
return Pvariable(fan.ToggleAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = fan.ToggleAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_FAN_TURN_OFF in config:
conf = config[CONF_FAN_TURN_OFF]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
return Pvariable(fan.TurnOffAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = fan.TurnOffAction.template(arg_type)
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
elif CONF_FAN_TURN_ON in config:
conf = config[CONF_FAN_TURN_ON]
var = get_variable(conf[CONF_ID])
for var in get_variable(conf[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
action = Pvariable(fan.TurnOnAction.template(arg_type), config[CONF_ACTION_ID], rhs)
type = fan.TurnOnAction.template(arg_type)
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
if CONF_OSCILLATING in config:
add(action.set_oscillating(templatable(conf[CONF_OSCILLATING], arg_type, bool_)))
template_ = None
for template_ in templatable(conf[CONF_OSCILLATING], arg_type, bool_):
yield None
add(action.set_oscillating(template_))
if CONF_SPEED in config:
add(action.set_speed(templatable(conf[CONF_SPEED], arg_type, fan.FanSpeed)))
return action
raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
template_ = None
for template_ in templatable(conf[CONF_SPEED], arg_type, fan.FanSpeed):
yield None
add(action.set_speed(template_))
yield action
else:
raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
def build_actions(config, arg_type):
return ArrayInitializer(*[build_action(x, arg_type) for x in config])
actions = []
for conf in config:
action = None
for action in build_action(conf, arg_type):
yield None
actions.append(action)
yield ArrayInitializer(*actions, multiline=False)
def build_automation_(trigger, arg_type, config):
rhs = App.make_automation(trigger)
type = Automation.template(arg_type)
obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type)
if CONF_IF in config:
conditions = None
for conditions in build_conditions(config[CONF_IF], arg_type):
yield
add(obj.add_conditions(conditions))
actions = None
for actions in build_actions(config[CONF_THEN], arg_type):
yield
add(obj.add_actions(actions))
def build_automation(trigger, arg_type, config):
rhs = App.make_automation(trigger)
obj = Pvariable(Automation.template(arg_type), config[CONF_AUTOMATION_ID], rhs)
if CONF_IF in config:
add(obj.add_conditions(build_conditions(config[CONF_IF], arg_type)))
add(obj.add_actions(build_actions(config[CONF_THEN], arg_type)))
add_job(build_automation_, trigger, arg_type, config)

10
esphomeyaml/build.json Normal file
View File

@@ -0,0 +1,10 @@
{
"squash": false,
"build_from": {
"aarch64": "arm64v8/ubuntu:bionic",
"amd64": "ubuntu:bionic",
"armhf": "homeassistant/armhf-base:latest",
"i386": "i386/ubuntu:bionic"
},
"args": {}
}

View File

@@ -12,7 +12,7 @@ ADS1115Component = sensor.sensor_ns.ADS1115Component
RATE_REMOVE_MESSAGE = """The rate option has been removed in 1.5.0 and is no longer required."""
ADS1115_SCHEMA = vol.Schema({
cv.GenerateID('ads1115'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
vol.Required(CONF_ADDRESS): cv.i2c_address,
vol.Optional(CONF_RATE): cv.invalid(RATE_REMOVE_MESSAGE)
@@ -24,7 +24,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
def to_code(config):
for conf in config:
rhs = App.make_ads1115_component(conf[CONF_ADDRESS])
Pvariable(ADS1115Component, conf[CONF_ID], rhs)
Pvariable(conf[CONF_ID], rhs)
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'

View File

@@ -5,7 +5,8 @@ from esphomeyaml import automation
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, 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
from esphomeyaml.helpers import App, NoArg, Pvariable, add, esphomelib_ns, setup_mqtt_component
from esphomeyaml.helpers import App, NoArg, Pvariable, add, esphomelib_ns, setup_mqtt_component, \
add_job
DEVICE_CLASSES = [
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
@@ -27,18 +28,24 @@ BinarySensor = binary_sensor_ns.BinarySensor
MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
cv.GenerateID('mqtt_binary_sensor', CONF_MQTT_ID): cv.register_variable_id,
cv.GenerateID('binary_sensor'): cv.register_variable_id,
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTBinarySensorComponent),
cv.GenerateID(): cv.declare_variable_id(BinarySensor),
vol.Optional(CONF_INVERTED): cv.boolean,
vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower, cv.one_of(*DEVICE_CLASSES)),
vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PressTrigger),
})]),
vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ReleaseTrigger),
})]),
vol.Optional(CONF_ON_CLICK): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ClickTrigger),
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
})]),
vol.Optional(CONF_ON_DOUBLE_CLICK):
vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(DoubleClickTrigger),
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
})]),
@@ -53,43 +60,41 @@ def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config):
for conf in config.get(CONF_ON_PRESS, []):
rhs = binary_sensor_var.make_press_trigger()
trigger = Pvariable(PressTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
for conf in config.get(CONF_ON_RELEASE, []):
rhs = binary_sensor_var.make_release_trigger()
trigger = Pvariable(ReleaseTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
for conf in config.get(CONF_ON_CLICK, []):
rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH])
trigger = Pvariable(ClickTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
for conf in config.get(CONF_ON_DOUBLE_CLICK, []):
rhs = binary_sensor_var.make_double_click_trigger(conf[CONF_MIN_LENGTH],
conf[CONF_MAX_LENGTH])
trigger = Pvariable(DoubleClickTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
setup_mqtt_component(mqtt_var, config)
def setup_binary_sensor(binary_sensor_obj, mqtt_obj, config):
binary_sensor_var = Pvariable(BinarySensor, config[CONF_ID], binary_sensor_obj,
binary_sensor_var = Pvariable(config[CONF_ID], binary_sensor_obj,
has_side_effects=False)
mqtt_var = Pvariable(MQTTBinarySensorComponent, config[CONF_MQTT_ID], mqtt_obj,
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False)
setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config)
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
def register_binary_sensor(var, config):
binary_sensor_var = Pvariable(BinarySensor, config[CONF_ID], var,
has_side_effects=True)
binary_sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
rhs = App.register_binary_sensor(binary_sensor_var)
mqtt_var = Pvariable(MQTTBinarySensorComponent, config[CONF_MQTT_ID], rhs,
has_side_effects=True)
setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config)
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'

View File

@@ -10,6 +10,8 @@ from esphomeyaml.helpers import ArrayInitializer, get_variable
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
DEPENDENCIES = ['esp32_ble']
CONF_ESP32_BLE_ID = 'esp32_ble_id'
def validate_mac(value):
value = cv.string_strict(value)
@@ -30,11 +32,14 @@ def validate_mac(value):
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
vol.Required(CONF_MAC_ADDRESS): validate_mac,
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker)
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
def to_code(config):
hub = get_variable(None, type=ESP32BLETracker)
hub = None
for hub in get_variable(config[CONF_ESP32_BLE_ID]):
yield
addr = [HexInt(i) for i in config[CONF_MAC_ADDRESS].parts]
rhs = hub.make_device(config[CONF_NAME], ArrayInitializer(*addr, multiline=False))
binary_sensor.register_binary_sensor(rhs, config)

View File

@@ -11,6 +11,8 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
DEPENDENCIES = ['esp32_touch']
CONF_ESP32_TOUCH_ID = 'esp32_touch_id'
TOUCH_PADS = {
4: global_ns.TOUCH_PAD_NUM0,
0: global_ns.TOUCH_PAD_NUM1,
@@ -35,11 +37,14 @@ def validate_touch_pad(value):
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
vol.Required(CONF_PIN): validate_touch_pad,
vol.Required(CONF_THRESHOLD): cv.uint16_t,
cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_variable_id(ESP32TouchComponent),
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
def to_code(config):
hub = get_variable(None, type=ESP32TouchComponent)
hub = None
for hub in get_variable(config[CONF_ESP32_TOUCH_ID]):
yield
touch_pad = TOUCH_PADS[config[CONF_PIN]]
rhs = hub.make_touch_pad(config[CONF_NAME], touch_pad, config[CONF_THRESHOLD])
binary_sensor.register_binary_sensor(rhs, config)

View File

@@ -6,18 +6,20 @@ from esphomeyaml.components import binary_sensor
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('gpio_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN): pins.GPIO_INPUT_PIN_SCHEMA
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
MakeGPIOBinarySensor = Application.MakeGPIOBinarySensor
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOBinarySensor),
vol.Required(CONF_PIN): pins.gpio_input_pin_schema
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
def to_code(config):
rhs = App.make_gpio_binary_sensor(config[CONF_NAME],
gpio_input_pin_expression(config[CONF_PIN]))
gpio = variable(MakeGPIOBinarySensor, config[CONF_MAKE_ID], rhs)
pin = None
for pin in gpio_input_pin_expression(config[CONF_PIN]):
yield
rhs = App.make_gpio_binary_sensor(config[CONF_NAME], pin)
gpio = variable(config[CONF_MAKE_ID], rhs)
binary_sensor.setup_binary_sensor(gpio.Pgpio, gpio.Pmqtt, config)

View File

@@ -5,16 +5,16 @@ from esphomeyaml.helpers import App, Application, variable
DEPENDENCIES = ['mqtt']
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('status_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
MakeStatusBinarySensor = Application.MakeStatusBinarySensor
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeStatusBinarySensor),
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
def to_code(config):
rhs = App.make_status_binary_sensor(config[CONF_NAME])
status = variable(MakeStatusBinarySensor, config[CONF_MAKE_ID], rhs)
status = variable(config[CONF_MAKE_ID], rhs)
binary_sensor.setup_binary_sensor(status.Pstatus, status.Pmqtt, config)

View File

@@ -3,20 +3,23 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import binary_sensor
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME
from esphomeyaml.helpers import App, Application, process_lambda, variable
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('template_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_LAMBDA): cv.lambda_,
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
from esphomeyaml.helpers import App, Application, process_lambda, variable, optional, bool_
MakeTemplateBinarySensor = Application.MakeTemplateBinarySensor
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateBinarySensor),
vol.Required(CONF_LAMBDA): cv.lambda_,
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
def to_code(config):
template_ = process_lambda(config[CONF_LAMBDA], [])
template_ = None
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=optional.template(bool_)):
yield
rhs = App.make_template_binary_sensor(config[CONF_NAME], template_)
make = variable(MakeTemplateBinarySensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
binary_sensor.setup_binary_sensor(make.Ptemplate_, make.Pmqtt, config)

View File

@@ -6,11 +6,6 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID('cover'): cv.register_variable_id,
cv.GenerateID('mqtt_cover', CONF_MQTT_ID): cv.register_variable_id,
})
cover_ns = esphomelib_ns.namespace('cover')
Cover = cover_ns.Cover
MQTTCoverComponent = cover_ns.MQTTCoverComponent
@@ -21,15 +16,19 @@ OpenAction = cover_ns.OpenAction
CloseAction = cover_ns.CloseAction
StopAction = cover_ns.StopAction
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(Cover),
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTCoverComponent),
})
def setup_cover_core_(cover_var, mqtt_var, config):
setup_mqtt_component(mqtt_var, config)
def setup_cover(cover_obj, mqtt_obj, config):
cover_var = Pvariable(Cover, config[CONF_ID], cover_obj, has_side_effects=False)
mqtt_var = Pvariable(MQTTCoverComponent, config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False)
cover_var = Pvariable(config[CONF_ID], cover_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
setup_cover_core_(cover_var, mqtt_var, config)

View File

@@ -5,35 +5,44 @@ from esphomeyaml import automation
from esphomeyaml.components import cover
from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \
CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable, optional
MakeTemplateCover = Application.MakeTemplateCover
PLATFORM_SCHEMA = vol.All(cover.PLATFORM_SCHEMA.extend({
cv.GenerateID('template_cover', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateCover),
vol.Optional(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_OPEN_ACTION): automation.ACTIONS_SCHEMA,
vol.Optional(CONF_CLOSE_ACTION): automation.ACTIONS_SCHEMA,
vol.Optional(CONF_STOP_ACTION): automation.ACTIONS_SCHEMA,
}).extend(cover.COVER_SCHEMA.schema), cv.has_at_exactly_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
MakeTemplateCover = Application.MakeTemplateCover
}).extend(cover.COVER_SCHEMA.schema), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
def to_code(config):
rhs = App.make_template_cover(config[CONF_NAME])
make = variable(MakeTemplateCover, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
if CONF_LAMBDA in config:
template_ = process_lambda(config[CONF_LAMBDA], [])
add(make.Ptemplate.set_state_lambda(template_))
template_ = None
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=optional.template(cover.CoverState)):
yield
add(make.Ptemplate_.set_state_lambda(template_))
if CONF_OPEN_ACTION in config:
actions = automation.build_actions(config[CONF_OPEN_ACTION], NoArg)
actions = None
for actions in automation.build_actions(config[CONF_OPEN_ACTION], NoArg):
yield
add(make.Ptemplate_.add_open_actions(actions))
if CONF_CLOSE_ACTION in config:
actions = automation.build_actions(config[CONF_CLOSE_ACTION], NoArg)
actions = None
for actions in automation.build_actions(config[CONF_CLOSE_ACTION], NoArg):
yield
add(make.Ptemplate_.add_close_actions(actions))
if CONF_STOP_ACTION in config:
actions = automation.build_actions(config[CONF_STOP_ACTION], NoArg)
actions = None
for actions in automation.build_actions(config[CONF_STOP_ACTION], NoArg):
yield
add(make.Ptemplate_.add_stop_actions(actions))
if CONF_OPTIMISTIC in config:
add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC]))

View File

@@ -9,7 +9,7 @@ from esphomeyaml.helpers import App, Pvariable
DallasComponent = sensor.sensor_ns.DallasComponent
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
cv.GenerateID('dallas'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(DallasComponent),
vol.Required(CONF_PIN): pins.input_output_pin,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})])
@@ -18,7 +18,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
def to_code(config):
for conf in config:
rhs = App.make_dallas_component(conf[CONF_PIN], conf.get(CONF_UPDATE_INTERVAL))
Pvariable(DallasComponent, conf[CONF_ID], rhs)
Pvariable(conf[CONF_ID], rhs)
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'

View File

@@ -14,26 +14,40 @@ def validate_pin_number(value):
return value
DeepSleepComponent = esphomelib_ns.DeepSleepComponent
WAKEUP_PIN_MODES = {
'IGNORE': esphomelib_ns.WAKEUP_PIN_MODE_IGNORE,
'KEEP_AWAKE': esphomelib_ns.WAKEUP_PIN_MODE_KEEP_AWAKE,
'INVERT_WAKEUP': esphomelib_ns.WAKEUP_PIN_MODE_INVERT_WAKEUP,
}
CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('deep_sleep'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent),
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
validate_pin_number),
vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32, vol.Upper,
cv.one_of(*WAKEUP_PIN_MODES)),
vol.Optional(CONF_RUN_CYCLES): cv.positive_int,
vol.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
})
DeepSleepComponent = esphomelib_ns.DeepSleepComponent
def to_code(config):
rhs = App.make_deep_sleep_component()
deep_sleep = Pvariable(DeepSleepComponent, config[CONF_ID], rhs)
deep_sleep = Pvariable(config[CONF_ID], rhs)
if CONF_SLEEP_DURATION in config:
add(deep_sleep.set_sleep_duration(config[CONF_SLEEP_DURATION]))
if CONF_WAKEUP_PIN in config:
pin = gpio_input_pin_expression(config[CONF_WAKEUP_PIN])
pin = None
for pin in gpio_input_pin_expression(config[CONF_WAKEUP_PIN]):
yield
add(deep_sleep.set_wakeup_pin(pin))
if CONF_WAKEUP_PIN_MODE in config:
add(deep_sleep.set_wakeup_pin_mode(WAKEUP_PIN_MODES[config[CONF_WAKEUP_PIN_MODE]]))
if CONF_RUN_CYCLES in config:
add(deep_sleep.set_run_cycles(config[CONF_RUN_CYCLES]))
if CONF_RUN_DURATION in config:

View File

@@ -6,17 +6,17 @@ from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
ESP32BLETracker = esphomelib_ns.ESP32BLETracker
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('esp32_ble'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker),
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
})
ESP32BLETracker = esphomelib_ns.ESP32BLETracker
def to_code(config):
rhs = App.make_esp32_ble_tracker()
ble = Pvariable(ESP32BLETracker, config[CONF_ID], rhs)
ble = Pvariable(config[CONF_ID], rhs)
if CONF_SCAN_INTERVAL in config:
add(ble.set_scan_interval(config[CONF_SCAN_INTERVAL]))

View File

@@ -41,8 +41,10 @@ VOLTAGE_ATTENUATION = {
'0V': global_ns.TOUCH_HVOLT_ATTEN_0V,
}
ESP32TouchComponent = binary_sensor.binary_sensor_ns.ESP32TouchComponent
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('esp32_ble'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent),
vol.Optional(CONF_SETUP_MODE): cv.boolean,
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
vol.Optional(CONF_SLEEP_DURATION):
@@ -54,18 +56,16 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_VOLTAGE_ATTENUATION): validate_voltage(VOLTAGE_ATTENUATION),
})
ESP32TouchComponent = binary_sensor.binary_sensor_ns.ESP32TouchComponent
def to_code(config):
rhs = App.make_esp32_touch_component()
touch = Pvariable(ESP32TouchComponent, config[CONF_ID], rhs)
touch = Pvariable(config[CONF_ID], rhs)
if CONF_SETUP_MODE in config:
add(touch.set_setup_mode(config[CONF_SETUP_MODE]))
if CONF_IIR_FILTER in config:
add(touch.set_iir_filter(config[CONF_IIR_FILTER]))
if CONF_SLEEP_DURATION in config:
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 6.6667)
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 0.15)
add(touch.set_sleep_duration(sleep_duration))
if CONF_MEASUREMENT_DURATION in config:
measurement_duration = int(config[CONF_MEASUREMENT_DURATION].total_microseconds * 0.125)

View File

@@ -9,13 +9,6 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID('fan'): cv.register_variable_id,
cv.GenerateID('mqtt_fan', CONF_MQTT_ID): cv.register_variable_id,
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.publish_topic,
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic,
})
fan_ns = esphomelib_ns.namespace('fan')
FanState = fan_ns.FanState
MQTTFanComponent = fan_ns.MQTTFanComponent
@@ -29,6 +22,13 @@ FAN_SPEED_LOW = fan_ns.FAN_SPEED_LOW
FAN_SPEED_MEDIUM = fan_ns.FAN_SPEED_MEDIUM
FAN_SPEED_HIGH = fan_ns.FAN_SPEED_HIGH
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(FanState),
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTFanComponent),
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.publish_topic,
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic,
})
FAN_SPEEDS = {
'OFF': FAN_SPEED_OFF,
@@ -55,8 +55,8 @@ def setup_fan_core_(fan_var, mqtt_var, config):
def setup_fan(fan_obj, mqtt_obj, config):
fan_var = Pvariable(FanState, config[CONF_ID], fan_obj, has_side_effects=False)
mqtt_var = Pvariable(MQTTFanComponent, config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
fan_var = Pvariable(config[CONF_ID], fan_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
setup_fan_core_(fan_var, mqtt_var, config)

View File

@@ -6,19 +6,24 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT,
from esphomeyaml.helpers import App, add, get_variable, variable
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
cv.GenerateID('binary_fan', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_OUTPUT): cv.variable_id,
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
}).extend(fan.FAN_SCHEMA.schema)
def to_code(config):
output = get_variable(config[CONF_OUTPUT])
output = None
for output in get_variable(config[CONF_OUTPUT]):
yield
rhs = App.make_fan(config[CONF_NAME])
fan_struct = variable(fan.MakeFan, config[CONF_MAKE_ID], rhs)
fan_struct = variable(config[CONF_MAKE_ID], rhs)
add(fan_struct.Poutput.set_binary(output))
if CONF_OSCILLATION_OUTPUT in config:
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
oscillation_output = None
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
yield
add(fan_struct.Poutput.set_oscillation(oscillation_output))
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)

View File

@@ -8,11 +8,11 @@ from esphomeyaml.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CO
from esphomeyaml.helpers import App, add, get_variable, variable
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
cv.GenerateID('speed_fan', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_OUTPUT): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
vol.Optional(CONF_SPEED): vol.Schema({
vol.Required(CONF_LOW): cv.percentage,
vol.Required(CONF_MEDIUM): cv.percentage,
@@ -22,9 +22,11 @@ PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
def to_code(config):
output = get_variable(config[CONF_OUTPUT])
output = None
for output in get_variable(config[CONF_OUTPUT]):
yield
rhs = App.make_fan(config[CONF_NAME])
fan_struct = variable(fan.MakeFan, config[CONF_MAKE_ID], rhs)
fan_struct = variable(config[CONF_MAKE_ID], rhs)
if CONF_SPEED in config:
speeds = config[CONF_SPEED]
add(fan_struct.Poutput.set_speed(output, 0.0,
@@ -35,7 +37,9 @@ def to_code(config):
add(fan_struct.Poutput.set_speed(output))
if CONF_OSCILLATION_OUTPUT in config:
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
oscillation_output = None
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
yield
add(fan_struct.Poutput.set_oscillation(oscillation_output))
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)

View File

@@ -6,21 +6,21 @@ from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CON
CONF_RECEIVE_TIMEOUT
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
I2CComponent = esphomelib_ns.I2CComponent
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('i2c'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(I2CComponent),
vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin,
vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin,
vol.Optional(CONF_FREQUENCY): cv.positive_int,
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)),
vol.Optional(CONF_RECEIVE_TIMEOUT): cv.positive_time_period_milliseconds,
vol.Optional(CONF_SCAN): cv.boolean,
})
I2CComponent = esphomelib_ns.I2CComponent
def to_code(config):
rhs = App.init_i2c(config[CONF_SDA], config[CONF_SCL], config.get(CONF_SCAN))
i2c = Pvariable(I2CComponent, config[CONF_ID], rhs)
i2c = Pvariable(config[CONF_ID], rhs)
if CONF_FREQUENCY in config:
add(i2c.set_frequency(config[CONF_FREQUENCY]))
if CONF_RECEIVE_TIMEOUT in config:

View File

@@ -6,21 +6,23 @@ from esphomeyaml.components import switch
from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
IRTransmitterComponent = switch.switch_ns.namespace('IRTransmitterComponent')
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
cv.GenerateID('ir_transmitter'): cv.register_variable_id,
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
cv.GenerateID(): cv.declare_variable_id(IRTransmitterComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int),
vol.Range(min=1, max=100)),
})])
IRTransmitterComponent = switch.switch_ns.namespace('IRTransmitterComponent')
def to_code(config):
for conf in config:
pin = gpio_output_pin_expression(conf[CONF_PIN])
pin = None
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
yield
rhs = App.make_ir_transmitter(pin, conf.get(CONF_CARRIER_DUTY_PERCENT))
Pvariable(IRTransmitterComponent, conf[CONF_ID], rhs)
Pvariable(conf[CONF_ID], rhs)
BUILD_FLAGS = '-DUSE_IR_TRANSMITTER'

View File

@@ -7,11 +7,6 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID('light'): cv.register_variable_id,
cv.GenerateID('mqtt_light', CONF_MQTT_ID): cv.register_variable_id,
})
light_ns = esphomelib_ns.namespace('light')
LightState = light_ns.LightState
MQTTJSONLightComponent = light_ns.MQTTJSONLightComponent
@@ -20,6 +15,11 @@ TurnOffAction = light_ns.TurnOffAction
TurnOnAction = light_ns.TurnOnAction
MakeLight = Application.MakeLight
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(LightState),
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTJSONLightComponent),
})
def setup_light_core_(light_var, mqtt_var, config):
if CONF_DEFAULT_TRANSITION_LENGTH in config:
@@ -31,9 +31,8 @@ def setup_light_core_(light_var, mqtt_var, config):
def setup_light(light_obj, mqtt_obj, config):
light_var = Pvariable(LightState, config[CONF_ID], light_obj, has_side_effects=False)
mqtt_var = Pvariable(MQTTJSONLightComponent, config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False)
light_var = Pvariable(config[CONF_ID], light_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
setup_light_core_(light_var, mqtt_var, config)

View File

@@ -6,13 +6,15 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
from esphomeyaml.helpers import App, get_variable, variable
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
cv.GenerateID('binary_light', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_OUTPUT): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
}).extend(light.LIGHT_SCHEMA.schema)
def to_code(config):
output = get_variable(config[CONF_OUTPUT])
output = None
for output in get_variable(config[CONF_OUTPUT]):
yield
rhs = App.make_binary_light(config[CONF_NAME], output)
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)

View File

@@ -3,6 +3,7 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins
from esphomeyaml.components import light
from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, \
CONF_RGB_ORDER
@@ -52,8 +53,10 @@ def validate(value):
return value
MakeFastLEDLight = Application.MakeFastLEDLight
PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
cv.GenerateID('fast_led_clockless_light', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight),
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*TYPES)),
vol.Required(CONF_PIN): pins.output_pin,
@@ -64,15 +67,13 @@ PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
}).extend(light.LIGHT_SCHEMA.schema), validate)
MakeFastLEDLight = Application.MakeFastLEDLight
def to_code(config):
rhs = App.make_fast_led_light(config[CONF_NAME])
make = variable(MakeFastLEDLight, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
fast_led = make.Pfast_led
rgb_order = None
@@ -86,7 +87,9 @@ def to_code(config):
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
if CONF_POWER_SUPPLY in config:
power_supply = get_variable(config[CONF_POWER_SUPPLY])
power_supply = None
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
yield
add(fast_led.set_power_supply(power_supply))
light.setup_light(make.Pstate, make.Pmqtt, config)

View File

@@ -3,6 +3,7 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins
from esphomeyaml.components import light
from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \
CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, \
CONF_NAME, CONF_NUM_LEDS, CONF_POWER_SUPPLY, CONF_RGB_ORDER
@@ -29,8 +30,10 @@ RGB_ORDERS = [
'BGR',
]
MakeFastLEDLight = Application.MakeFastLEDLight
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
cv.GenerateID('fast_led_spi_light', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight),
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*CHIPSETS)),
vol.Required(CONF_DATA_PIN): pins.output_pin,
@@ -42,15 +45,13 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
}).extend(light.LIGHT_SCHEMA.schema)
MakeFastLEDLight = Application.MakeFastLEDLight
def to_code(config):
rhs = App.make_fast_led_light(config[CONF_NAME])
make = variable(MakeFastLEDLight, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
fast_led = make.Pfast_led
rgb_order = None
@@ -66,7 +67,9 @@ def to_code(config):
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
if CONF_POWER_SUPPLY in config:
power_supply = get_variable(config[CONF_POWER_SUPPLY])
power_supply = None
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
yield
add(fast_led.set_power_supply(power_supply))
light.setup_light(make.Pstate, make.Pmqtt, config)

View File

@@ -7,15 +7,17 @@ from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT
from esphomeyaml.helpers import App, get_variable, variable
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
cv.GenerateID('monochromatic_light', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_OUTPUT): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
}).extend(light.LIGHT_SCHEMA.schema)
def to_code(config):
output = get_variable(config[CONF_OUTPUT])
output = None
for output in get_variable(config[CONF_OUTPUT]):
yield
rhs = App.make_monochromatic_light(config[CONF_NAME], output)
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)

View File

@@ -7,19 +7,25 @@ from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GA
from esphomeyaml.helpers import App, get_variable, variable
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
cv.GenerateID('rgb_light', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_RED): cv.variable_id,
vol.Required(CONF_GREEN): cv.variable_id,
vol.Required(CONF_BLUE): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
vol.Required(CONF_RED): cv.use_variable_id(None),
vol.Required(CONF_GREEN): cv.use_variable_id(None),
vol.Required(CONF_BLUE): cv.use_variable_id(None),
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
}).extend(light.LIGHT_SCHEMA.schema)
def to_code(config):
red = get_variable(config[CONF_RED])
green = get_variable(config[CONF_GREEN])
blue = get_variable(config[CONF_BLUE])
red = None
for red in get_variable(config[CONF_RED]):
yield
green = None
for green in get_variable(config[CONF_GREEN]):
yield
blue = None
for blue in get_variable(config[CONF_BLUE]):
yield
rhs = App.make_rgb_light(config[CONF_NAME], red, green, blue)
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)

View File

@@ -7,21 +7,29 @@ from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GA
from esphomeyaml.helpers import App, get_variable, variable
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
cv.GenerateID('rgbw_light', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_RED): cv.variable_id,
vol.Required(CONF_GREEN): cv.variable_id,
vol.Required(CONF_BLUE): cv.variable_id,
vol.Required(CONF_WHITE): cv.variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
vol.Required(CONF_RED): cv.use_variable_id(None),
vol.Required(CONF_GREEN): cv.use_variable_id(None),
vol.Required(CONF_BLUE): cv.use_variable_id(None),
vol.Required(CONF_WHITE): cv.use_variable_id(None),
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
}).extend(light.LIGHT_SCHEMA.schema)
def to_code(config):
red = get_variable(config[CONF_RED])
green = get_variable(config[CONF_GREEN])
blue = get_variable(config[CONF_BLUE])
white = get_variable(config[CONF_WHITE])
red = None
for red in get_variable(config[CONF_RED]):
yield
green = None
for green in get_variable(config[CONF_GREEN]):
yield
blue = None
for blue in get_variable(config[CONF_BLUE]):
yield
white = None
for white in get_variable(config[CONF_WHITE]):
yield
rhs = App.make_rgbw_light(config[CONF_NAME], red, green, blue, white)
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)

View File

@@ -1,7 +1,7 @@
import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGGER, CONF_LOGS, \
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGS, \
CONF_TX_BUFFER_SIZE
from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, global_ns
@@ -31,8 +31,10 @@ def validate_local_no_higher_than_global(value):
return value
LogComponent = esphomelib_ns.LogComponent
CONFIG_SCHEMA = vol.All(vol.Schema({
cv.GenerateID(CONF_LOGGER): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(LogComponent),
vol.Optional(CONF_BAUD_RATE): cv.positive_int,
vol.Optional(CONF_TX_BUFFER_SIZE): cv.positive_int,
vol.Optional(CONF_LEVEL): is_log_level,
@@ -41,12 +43,10 @@ CONFIG_SCHEMA = vol.All(vol.Schema({
})
}), validate_local_no_higher_than_global)
LogComponent = esphomelib_ns.LogComponent
def to_code(config):
rhs = App.init_log(config.get(CONF_BAUD_RATE))
log = Pvariable(LogComponent, config[CONF_ID], rhs)
log = Pvariable(config[CONF_ID], rhs)
if CONF_TX_BUFFER_SIZE in config:
add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE]))
if CONF_LEVEL in config:

View File

@@ -6,16 +6,17 @@ import esphomeyaml.config_validation as cv
from esphomeyaml import automation
from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, CONF_DISCOVERY, \
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LOG_TOPIC, \
CONF_MQTT, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, \
CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, \
CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \
CONF_WILL_MESSAGE
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, StructInitializer, \
TemplateArguments, add, esphomelib_ns, optional, std_string, RawExpression
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, RawExpression, \
StructInitializer, \
TemplateArguments, add, esphomelib_ns, optional, std_string
def validate_message_just_topic(value):
value = cv.publish_topic(value)
return {CONF_TOPIC: value}
return MQTT_MESSAGE_BASE({CONF_TOPIC: value})
MQTT_MESSAGE_BASE = vol.Schema({
@@ -54,7 +55,7 @@ def validate_fingerprint(value):
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(CONF_MQTT): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
vol.Required(CONF_BROKER): validate_broker,
vol.Optional(CONF_PORT, default=1883): cv.port,
vol.Optional(CONF_USERNAME, default=''): cv.string,
@@ -71,8 +72,9 @@ CONFIG_SCHEMA = vol.Schema({
cv.ensure_list, [validate_fingerprint]),
vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds,
vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger),
vol.Required(CONF_TOPIC): cv.publish_topic,
vol.Optional(CONF_QOS, 0): cv.mqtt_qos,
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
})])
})
@@ -93,7 +95,7 @@ def exp_mqtt_message(config):
def to_code(config):
rhs = App.init_mqtt(config[CONF_BROKER], config[CONF_PORT],
config[CONF_USERNAME], config[CONF_PASSWORD])
mqtt = Pvariable(MQTTClientComponent, config[CONF_ID], rhs)
mqtt = Pvariable(config[CONF_ID], rhs)
if not config.get(CONF_DISCOVERY, True):
add(mqtt.disable_discovery())
if CONF_DISCOVERY_RETAIN in config or CONF_DISCOVERY_PREFIX in config:
@@ -104,13 +106,13 @@ def to_code(config):
add(mqtt.set_topic_prefix(config[CONF_TOPIC_PREFIX]))
if CONF_BIRTH_MESSAGE in config:
birth_message = config[CONF_BIRTH_MESSAGE]
if birth_message is None:
if not birth_message:
add(mqtt.disable_birth_message())
else:
add(mqtt.set_birth_message(exp_mqtt_message(birth_message)))
if CONF_WILL_MESSAGE in config:
will_message = config[CONF_WILL_MESSAGE]
if will_message is None:
if not will_message:
add(mqtt.disable_last_will())
else:
add(mqtt.set_last_will(exp_mqtt_message(will_message)))
@@ -118,10 +120,10 @@ def to_code(config):
add(mqtt.set_client_id(config[CONF_CLIENT_ID]))
if CONF_LOG_TOPIC in config:
log_topic = config[CONF_LOG_TOPIC]
if log_topic is None:
if not log_topic:
add(mqtt.disable_log_message())
else:
add(mqtt.set_log_topic(exp_mqtt_message(log_topic)))
add(mqtt.set_log_message_template(exp_mqtt_message(log_topic)))
if CONF_SSL_FINGERPRINTS in config:
for fingerprint in config[CONF_SSL_FINGERPRINTS]:
arr = [RawExpression("0x{}".format(fingerprint[i:i + 2])) for i in range(0, 40, 2)]
@@ -131,7 +133,7 @@ def to_code(config):
for conf in config.get(CONF_ON_MESSAGE, []):
rhs = mqtt.make_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS])
trigger = Pvariable(MQTTMessageTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, std_string, conf)

View File

@@ -12,23 +12,25 @@ from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns
_LOGGER = logging.getLogger(__name__)
OTAComponent = esphomelib_ns.OTAComponent
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(CONF_OTA): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(OTAComponent),
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
# TODO Num attempts + wait time
vol.Optional(CONF_PORT): cv.port,
vol.Optional(CONF_PASSWORD): cv.string,
})
OTAComponent = esphomelib_ns.OTAComponent
def to_code(config):
rhs = App.init_ota()
ota = Pvariable(OTAComponent, config[CONF_ID], rhs)
ota = Pvariable(config[CONF_ID], rhs)
if CONF_PASSWORD in config:
hash_ = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest()
add(ota.set_auth_password_hash(hash_))
if CONF_PORT in config:
add(ota.set_port(config[CONF_PORT]))
if config[CONF_SAFE_MODE]:
add(ota.start_safe_mode())

View File

@@ -1,6 +1,7 @@
import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY
from esphomeyaml.helpers import add, esphomelib_ns, get_variable
@@ -8,8 +9,8 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
BINARY_OUTPUT_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
BINARY_OUTPUT_SCHEMA = vol.Schema({
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
vol.Optional(CONF_INVERTED): cv.boolean,
})
@@ -24,7 +25,9 @@ def setup_output_platform(obj, config, skip_power_supply=False):
if CONF_INVERTED in config:
add(obj.set_inverted(config[CONF_INVERTED]))
if not skip_power_supply and CONF_POWER_SUPPLY in config:
power_supply = get_variable(config[CONF_POWER_SUPPLY])
power_supply = None
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
yield
add(obj.set_power_supply(power_supply))
if CONF_MAX_POWER in config:
add(obj.set_max_power(config[CONF_MAX_POWER]))

View File

@@ -1,8 +1,9 @@
import voluptuous as vol
from esphomeyaml import pins
import esphomeyaml.config_validation as cv
from esphomeyaml.components import output
from esphomeyaml.const import CONF_ID, CONF_PIN, ESP_PLATFORM_ESP8266, CONF_NUMBER
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266
from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
@@ -10,22 +11,25 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP8266]
def valid_pwm_pin(value):
if value[CONF_NUMBER] >= 16:
if value[CONF_NUMBER] > 16:
raise ESPHomeYAMLError(u"ESP8266: Only pins 0-16 support PWM.")
return value
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_PIN): vol.All(pins.GPIO_INTERNAL_OUTPUT_PIN_SCHEMA, valid_pwm_pin),
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema)
ESP8266PWMOutput = output.output_ns.ESP8266PWMOutput
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(ESP8266PWMOutput),
vol.Required(CONF_PIN): vol.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin),
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema)
def to_code(config):
pin = gpio_output_pin_expression(config[CONF_PIN])
pin = None
for pin in gpio_output_pin_expression(config[CONF_PIN]):
yield
rhs = App.make_esp8266_pwm_output(pin)
gpio = Pvariable(ESP8266PWMOutput, config[CONF_ID], rhs)
gpio = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(gpio, config)

View File

@@ -1,21 +1,25 @@
import voluptuous as vol
from esphomeyaml import pins
import esphomeyaml.config_validation as cv
from esphomeyaml.components import output
from esphomeyaml.const import CONF_ID, CONF_PIN
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
}).extend(output.BINARY_OUTPUT_SCHEMA.schema)
GPIOBinaryOutputComponent = output.output_ns.GPIOBinaryOutputComponent
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(GPIOBinaryOutputComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
}).extend(output.BINARY_OUTPUT_SCHEMA.schema)
def to_code(config):
pin = gpio_output_pin_expression(config[CONF_PIN])
pin = None
for pin in gpio_output_pin_expression(config[CONF_PIN]):
yield
rhs = App.make_gpio_output(pin)
gpio = Pvariable(GPIOBinaryOutputComponent, config[CONF_ID], rhs)
gpio = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(gpio, config)

View File

@@ -15,11 +15,14 @@ def validate_frequency_bit_depth(obj):
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
if frequency > max_freq:
raise vol.Invalid('Maximum frequency for bit depth {} is {}'.format(bit_depth, max_freq))
raise vol.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, max_freq))
return obj
LEDCOutputComponent = output.output_ns.LEDCOutputComponent
PLATFORM_SCHEMA = vol.All(output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(LEDCOutputComponent),
vol.Required(CONF_PIN): pins.output_pin,
vol.Optional(CONF_FREQUENCY): cv.frequency,
vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)),
@@ -27,15 +30,12 @@ PLATFORM_SCHEMA = vol.All(output.PLATFORM_SCHEMA.extend({
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema), validate_frequency_bit_depth)
LEDCOutputComponent = output.output_ns.LEDCOutputComponent
def to_code(config):
frequency = config.get(CONF_FREQUENCY)
if frequency is None and CONF_BIT_DEPTH in config:
frequency = 1000
rhs = App.make_ledc_output(config[CONF_PIN], frequency, config.get(CONF_BIT_DEPTH))
ledc = Pvariable(LEDCOutputComponent, config[CONF_ID], rhs)
ledc = Pvariable(config[CONF_ID], rhs)
if CONF_CHANNEL in config:
add(ledc.set_channel(config[CONF_CHANNEL]))
output.setup_output_platform(ledc, config)

View File

@@ -8,22 +8,26 @@ from esphomeyaml.helpers import Pvariable, get_variable
DEPENDENCIES = ['pca9685']
Channel = PCA9685OutputComponent.Channel
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(Channel),
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int),
vol.Range(min=0, max=15)),
vol.Optional(CONF_PCA9685_ID): cv.variable_id,
cv.GenerateID(CONF_PCA9685_ID): cv.use_variable_id(PCA9685OutputComponent),
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema)
Channel = PCA9685OutputComponent.Channel
def to_code(config):
power_supply = None
if CONF_POWER_SUPPLY in config:
power_supply = get_variable(config[CONF_POWER_SUPPLY])
pca9685 = get_variable(config.get(CONF_PCA9685_ID), PCA9685OutputComponent)
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
yield
pca9685 = None
for pca9685 in get_variable(config[CONF_PCA9685_ID]):
yield
rhs = pca9685.create_channel(config[CONF_CHANNEL], power_supply)
out = Pvariable(Channel, config[CONF_ID], rhs)
out = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(out, config, skip_power_supply=True)

View File

@@ -13,7 +13,7 @@ PHASE_BALANCER_MESSAGE = ("The phase_balancer option has been removed in version
"esphomelib will now automatically choose a suitable phase balancer.")
PCA9685_SCHEMA = vol.Schema({
cv.GenerateID('pca9685'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
vol.Range(min=23.84, max=1525.88)),
vol.Optional(CONF_ADDRESS): cv.i2c_address,
@@ -27,7 +27,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCA9685_SCHEMA])
def to_code(config):
for conf in config:
rhs = App.make_pca9685_component(conf.get(CONF_FREQUENCY))
pca9685 = Pvariable(PCA9685OutputComponent, conf[CONF_ID], rhs)
pca9685 = Pvariable(conf[CONF_ID], rhs)
if CONF_ADDRESS in conf:
add(pca9685.set_address(HexIntLiteral(conf[CONF_ADDRESS])))

View File

@@ -6,22 +6,22 @@ from esphomeyaml.helpers import App, Pvariable, esphomelib_ns
DEPENDENCIES = ['i2c']
io_ns = esphomelib_ns.namespace('io')
PCF8574Component = io_ns.PCF8574Component
PCF8574_SCHEMA = vol.Schema({
vol.Required(CONF_ID): cv.register_variable_id,
vol.Required(CONF_ID): cv.declare_variable_id(PCF8574Component),
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
vol.Optional(CONF_PCF8575, default=False): cv.boolean,
})
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCF8574_SCHEMA])
io_ns = esphomelib_ns.namespace('io')
PCF8574Component = io_ns.PCF8574Component
def to_code(config):
for conf in config:
rhs = App.make_pcf8574_component(conf[CONF_ADDRESS], conf[CONF_PCF8575])
Pvariable(PCF8574Component, conf[CONF_ID], rhs)
Pvariable(conf[CONF_ID], rhs)
BUILD_FLAGS = '-DUSE_PCF8574'

View File

@@ -5,21 +5,25 @@ from esphomeyaml import pins
from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
POWER_SUPPLY_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
PowerSupplyComponent = esphomelib_ns.PowerSupplyComponent
POWER_SUPPLY_SCHEMA = vol.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
})
CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
PowerSupplyComponent = esphomelib_ns.PowerSupplyComponent
def to_code(config):
for conf in config:
rhs = App.make_power_supply(gpio_output_pin_expression(conf[CONF_PIN]))
psu = Pvariable(PowerSupplyComponent, conf[CONF_ID], rhs)
pin = None
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
yield
rhs = App.make_power_supply(pin)
psu = Pvariable(conf[CONF_ID], rhs)
if CONF_ENABLE_TIME in conf:
add(psu.set_enable_time(conf[CONF_ENABLE_TIME]))
if CONF_KEEP_ON_TIME in conf:

View File

@@ -9,7 +9,7 @@ from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CO
CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SLIDING_WINDOW_MOVING_AVERAGE, \
CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, esphomelib_ns, float_, \
process_lambda, setup_mqtt_component, templatable
process_lambda, setup_mqtt_component, templatable, add_job
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@@ -44,25 +44,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
vol.Optional(CONF_OR): validate_recursive_filter,
}, cv.has_at_exactly_one_key(*FILTER_KEYS))])
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
cv.GenerateID('mqtt_sensor', CONF_MQTT_ID): cv.register_variable_id,
cv.GenerateID('sensor'): cv.register_variable_id,
vol.Required(CONF_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict,
vol.Optional(CONF_ICON): cv.icon,
vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int),
vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds),
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
vol.Optional(CONF_ON_VALUE_RANGE): vol.All(cv.ensure_list, [vol.All(
automation.AUTOMATION_SCHEMA.extend({
vol.Optional(CONF_ABOVE): vol.Coerce(float),
vol.Optional(CONF_BELOW): vol.Coerce(float),
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))]),
})
}, cv.has_exactly_one_key(*FILTER_KEYS))])
# pylint: disable=invalid-name
sensor_ns = esphomelib_ns.namespace('sensor')
@@ -86,41 +68,75 @@ SensorValueTrigger = sensor_ns.SensorValueTrigger
RawSensorValueTrigger = sensor_ns.RawSensorValueTrigger
ValueRangeTrigger = sensor_ns.ValueRangeTrigger
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent),
cv.GenerateID(): cv.declare_variable_id(Sensor),
vol.Required(CONF_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict,
vol.Optional(CONF_ICON): cv.icon,
vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int),
vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds),
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(SensorValueTrigger),
})]),
vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(RawSensorValueTrigger),
})]),
vol.Optional(CONF_ON_VALUE_RANGE): vol.All(cv.ensure_list, [vol.All(
automation.AUTOMATION_SCHEMA.extend({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ValueRangeTrigger),
vol.Optional(CONF_ABOVE): vol.Coerce(float),
vol.Optional(CONF_BELOW): vol.Coerce(float),
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))]),
})
def setup_filter(config):
if CONF_OFFSET in config:
return OffsetFilter.new(config[CONF_OFFSET])
if CONF_MULTIPLY in config:
return MultiplyFilter.new(config[CONF_MULTIPLY])
if CONF_FILTER_OUT in config:
return FilterOutValueFilter.new(config[CONF_FILTER_OUT])
if CONF_FILTER_NAN in config:
return FilterOutNANFilter()
if CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
yield OffsetFilter.new(config[CONF_OFFSET])
elif CONF_MULTIPLY in config:
yield MultiplyFilter.new(config[CONF_MULTIPLY])
elif CONF_FILTER_OUT in config:
yield FilterOutValueFilter.new(config[CONF_FILTER_OUT])
elif CONF_FILTER_NAN in config:
yield FilterOutNANFilter.new()
elif CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
conf = config[CONF_SLIDING_WINDOW_MOVING_AVERAGE]
return SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
if CONF_EXPONENTIAL_MOVING_AVERAGE in config:
yield SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
elif CONF_EXPONENTIAL_MOVING_AVERAGE in config:
conf = config[CONF_EXPONENTIAL_MOVING_AVERAGE]
return ExponentialMovingAverageFilter.new(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
if CONF_LAMBDA in config:
return LambdaFilter.new(process_lambda(config[CONF_LAMBDA], [(float_, 'x')]))
if CONF_THROTTLE in config:
return ThrottleFilter.new(config[CONF_THROTTLE])
if CONF_DELTA in config:
return DeltaFilter.new(config[CONF_DELTA])
if CONF_OR in config:
return OrFilter.new(setup_filters(config[CONF_OR]))
if CONF_HEARTBEAT in config:
return App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
if CONF_DEBOUNCE in config:
return App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
if CONF_UNIQUE in config:
return UniqueFilter.new()
raise ValueError(u"Filter unsupported: {}".format(config))
yield ExponentialMovingAverageFilter.new(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
elif CONF_LAMBDA in config:
lambda_ = None
for lambda_ in process_lambda(config[CONF_LAMBDA], [(float_, 'x')]):
yield None
yield LambdaFilter.new(lambda_)
elif CONF_THROTTLE in config:
yield ThrottleFilter.new(config[CONF_THROTTLE])
elif CONF_DELTA in config:
yield DeltaFilter.new(config[CONF_DELTA])
elif CONF_OR in config:
filters = None
for filters in setup_filters(config[CONF_OR]):
yield None
yield OrFilter.new(filters)
elif CONF_HEARTBEAT in config:
yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
elif CONF_DEBOUNCE in config:
yield App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
elif CONF_UNIQUE in config:
yield UniqueFilter.new()
def setup_filters(config):
return ArrayInitializer(*[setup_filter(x) for x in config])
filters = []
for conf in config:
filter = None
for filter in setup_filter(conf):
yield None
filters.append(filter)
yield ArrayInitializer(*filters)
def setup_sensor_core_(sensor_var, mqtt_var, config):
@@ -131,23 +147,32 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
if CONF_ACCURACY_DECIMALS in config:
add(sensor_var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS]))
if CONF_FILTERS in config:
add(sensor_var.set_filters(setup_filters(config[CONF_FILTERS])))
filters = None
for filters in setup_filters(config[CONF_FILTERS]):
yield
add(sensor_var.set_filters(filters))
for conf in config.get(CONF_ON_VALUE, []):
rhs = sensor_var.make_value_trigger()
trigger = Pvariable(SensorValueTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, float_, conf)
for conf in config.get(CONF_ON_RAW_VALUE, []):
rhs = sensor_var.make_raw_value_trigger()
trigger = Pvariable(RawSensorValueTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, float_, conf)
for conf in config.get(CONF_ON_VALUE_RANGE, []):
rhs = sensor_var.make_value_range_trigger()
trigger = Pvariable(ValueRangeTrigger, conf[CONF_TRIGGER_ID], rhs)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
if CONF_ABOVE in conf:
trigger.set_min(templatable(conf[CONF_ABOVE], float_, float_))
template_ = None
for template_ in templatable(conf[CONF_ABOVE], float_, float_):
yield
trigger.set_min(template_)
if CONF_BELOW in conf:
trigger.set_max(templatable(conf[CONF_BELOW], float_, float_))
template_ = None
for template_ in templatable(conf[CONF_BELOW], float_, float_):
yield
trigger.set_max(template_)
automation.build_automation(trigger, float_, conf)
if CONF_EXPIRE_AFTER in config:
@@ -159,18 +184,16 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
def setup_sensor(sensor_obj, mqtt_obj, config):
sensor_var = Pvariable(Sensor, config[CONF_ID], sensor_obj, has_side_effects=False)
mqtt_var = Pvariable(MQTTSensorComponent, config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False)
setup_sensor_core_(sensor_var, mqtt_var, config)
sensor_var = Pvariable(config[CONF_ID], sensor_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
def register_sensor(var, config):
sensor_var = Pvariable(Sensor, config[CONF_ID], var, has_side_effects=True)
sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
rhs = App.register_sensor(sensor_var)
mqtt_var = Pvariable(MQTTSensorComponent, config[CONF_MQTT_ID], rhs,
has_side_effects=True)
setup_sensor_core_(sensor_var, mqtt_var, config)
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
BUILD_FLAGS = '-DUSE_SENSOR'

View File

@@ -14,20 +14,31 @@ ATTENUATION_MODES = {
'11db': global_ns.ADC_11db,
}
def validate_adc_pin(value):
vcc = str(value).upper()
if vcc == 'VCC':
return cv.only_on_esp8266(vcc)
return pins.analog_pin(value)
MakeADCSensor = Application.MakeADCSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('adc', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN): pins.analog_pin,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeADCSensor),
vol.Required(CONF_PIN): validate_adc_pin,
vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES)),
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeADCSensor = Application.MakeADCSensor
def to_code(config):
rhs = App.make_adc_sensor(config[CONF_NAME], config[CONF_PIN],
pin = config[CONF_PIN]
if pin == 'VCC':
pin = 0
rhs = App.make_adc_sensor(config[CONF_NAME], pin,
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeADCSensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
adc = make.Padc
if CONF_ATTENUATION in config:
add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]]))
@@ -35,3 +46,9 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_ADC_SENSOR'
def required_build_flags(config):
if config[CONF_PIN] == 'VCC':
return '-DUSE_ADC_SENSOR_VCC'
return None

View File

@@ -46,16 +46,17 @@ def validate_mux(value):
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('ads1115_sensor'): cv.register_variable_id,
vol.Required(CONF_MULTIPLEXER): validate_mux,
vol.Required(CONF_GAIN): validate_gain,
vol.Optional(CONF_ADS1115_ID): cv.variable_id,
cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component),
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
def to_code(config):
hub = get_variable(config.get(CONF_ADS1115_ID), ADS1115Component)
hub = None
for hub in get_variable(config[CONF_ADS1115_ID]):
yield
mux = MUX[config[CONF_MULTIPLEXER]]
gain = GAIN[config[CONF_GAIN]]

View File

@@ -14,20 +14,20 @@ BH1750_RESOLUTIONS = {
0.5: sensor.sensor_ns.BH1750_RESOLUTION_0P5_LX,
}
MakeBH1750Sensor = Application.MakeBH1750Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('bh1750_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBH1750Sensor),
vol.Optional(CONF_ADDRESS, default=0x23): cv.i2c_address,
vol.Optional(CONF_RESOLUTION): vol.All(cv.positive_float, cv.one_of(*BH1750_RESOLUTIONS)),
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeBH1750Sensor = Application.MakeBH1750Sensor
def to_code(config):
rhs = App.make_bh1750_sensor(config[CONF_NAME], config[CONF_ADDRESS],
config.get(CONF_UPDATE_INTERVAL))
make_bh1750 = variable(MakeBH1750Sensor, config[CONF_MAKE_ID], rhs)
make_bh1750 = variable(config[CONF_MAKE_ID], rhs)
bh1750 = make_bh1750.Pbh1750
if CONF_RESOLUTION in config:
add(bh1750.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]))

View File

@@ -29,8 +29,10 @@ BME280_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
})
MakeBME280Sensor = Application.MakeBME280Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('bme280', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME280Sensor),
vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address,
vol.Required(CONF_TEMPERATURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
vol.Required(CONF_PRESSURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
@@ -39,8 +41,6 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeBME280Sensor = Application.MakeBME280Sensor
def to_code(config):
rhs = App.make_bme280_sensor(config[CONF_TEMPERATURE][CONF_NAME],
@@ -48,7 +48,7 @@ def to_code(config):
config[CONF_HUMIDITY][CONF_NAME],
config[CONF_ADDRESS],
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeBME280Sensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
bme280 = make.Pbme280
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]

View File

@@ -33,8 +33,10 @@ BME680_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
})
MakeBME680Sensor = Application.MakeBME680Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('bme680', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME680Sensor),
vol.Optional(CONF_ADDRESS, default=0x76): cv.i2c_address,
vol.Required(CONF_TEMPERATURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
vol.Required(CONF_PRESSURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
@@ -45,8 +47,6 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeBME680Sensor = Application.MakeBME680Sensor
def to_code(config):
rhs = App.make_bme680_sensor(config[CONF_TEMPERATURE][CONF_NAME],
@@ -55,7 +55,7 @@ def to_code(config):
config[CONF_GAS_RESISTANCE][CONF_NAME],
config[CONF_ADDRESS],
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeBME680Sensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
bme680 = make.Pbme680
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]

View File

@@ -4,26 +4,26 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, HexIntLiteral, add, variable, Application
from esphomeyaml.helpers import App, Application, HexIntLiteral, add, variable
DEPENDENCIES = ['i2c']
MakeBMP085Sensor = Application.MakeBMP085Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('bmp085_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBMP085Sensor),
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_PRESSURE): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_ADDRESS): cv.i2c_address,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeBMP085Sensor = Application.MakeBMP085Sensor
def to_code(config):
rhs = App.make_bmp085_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_PRESSURE][CONF_NAME],
config.get(CONF_UPDATE_INTERVAL))
bmp = variable(MakeBMP085Sensor, config[CONF_MAKE_ID], rhs)
bmp = variable(config[CONF_MAKE_ID], rhs)
if CONF_ADDRESS in config:
add(bmp.Pbmp.set_address(HexIntLiteral(config[CONF_ADDRESS])))

View File

@@ -4,30 +4,27 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.components.dallas import DallasComponent
from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \
CONF_RESOLUTION, CONF_UPDATE_INTERVAL
CONF_RESOLUTION
from esphomeyaml.helpers import HexIntLiteral, get_variable
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int,
vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int,
vol.Optional(CONF_DALLAS_ID): cv.variable_id,
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=8, max=12)),
cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent),
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=9, max=12)),
}).extend(sensor.SENSOR_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
def to_code(config):
hub = get_variable(config.get(CONF_DALLAS_ID), DallasComponent)
update_interval = config.get(CONF_UPDATE_INTERVAL)
if CONF_RESOLUTION in config and update_interval is None:
update_interval = 10000
hub = None
for hub in get_variable(config[CONF_DALLAS_ID]):
yield
if CONF_ADDRESS in config:
address = HexIntLiteral(config[CONF_ADDRESS])
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, update_interval,
config.get(CONF_RESOLUTION))
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, config.get(CONF_RESOLUTION))
else:
rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX],
update_interval, config.get(CONF_RESOLUTION))
config.get(CONF_RESOLUTION))
sensor.register_sensor(rhs, config)

View File

@@ -5,7 +5,7 @@ from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_MODEL, CONF_NAME, CONF_PIN, \
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, add, gpio_output_pin_expression, variable
from esphomeyaml.pins import GPIO_OUTPUT_PIN_SCHEMA
from esphomeyaml.pins import gpio_output_pin_schema
DHT_MODELS = {
'AUTO_DETECT': sensor.sensor_ns.DHT_MODEL_AUTO_DETECT,
@@ -15,24 +15,26 @@ DHT_MODELS = {
'RHT03': sensor.sensor_ns.DHT_MODEL_RHT03,
}
MakeDHTSensor = Application.MakeDHTSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('dht_sensor', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN): GPIO_OUTPUT_PIN_SCHEMA,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHTSensor),
vol.Required(CONF_PIN): gpio_output_pin_schema,
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_MODEL): vol.All(vol.Upper, cv.one_of(*DHT_MODELS)),
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeDHTSensor = Application.MakeDHTSensor
def to_code(config):
pin = gpio_output_pin_expression(config[CONF_PIN])
pin = None
for pin in gpio_output_pin_expression(config[CONF_PIN]):
yield
rhs = App.make_dht_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_HUMIDITY][CONF_NAME],
pin, config.get(CONF_UPDATE_INTERVAL))
dht = variable(MakeDHTSensor, config[CONF_MAKE_ID], rhs)
dht = variable(config[CONF_MAKE_ID], rhs)
if CONF_MODEL in config:
constant = DHT_MODELS[config[CONF_MODEL]]
add(dht.Pdht.set_dht_model(constant))

View File

@@ -8,25 +8,25 @@ from esphomeyaml.helpers import App, Application, variable
DEPENDENCIES = ['i2c']
MakeDHT12Sensor = Application.MakeDHT12Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('dht_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHT12Sensor),
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeDHT12Sensor = Application.MakeDHT12Sensor
def to_code(config):
rhs = App.make_dht12_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_HUMIDITY][CONF_NAME],
config.get(CONF_UPDATE_INTERVAL))
dht = variable(MakeDHT12Sensor, config[CONF_MAKE_ID], rhs)
dht = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(dht.Pdht.Pget_temperature_sensor(), dht.Pmqtt_temperature,
sensor.setup_sensor(dht.Pdht12.Pget_temperature_sensor(), dht.Pmqtt_temperature,
config[CONF_TEMPERATURE])
sensor.setup_sensor(dht.Pdht.Pget_humidity_sensor(), dht.Pmqtt_humidity,
sensor.setup_sensor(dht.Pdht12.Pget_humidity_sensor(), dht.Pmqtt_humidity,
config[CONF_HUMIDITY])

View File

@@ -0,0 +1,24 @@
import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32
from esphomeyaml.helpers import App, Application, variable
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
MakeESP32HallSensor = Application.MakeESP32HallSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeESP32HallSensor),
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
def to_code(config):
rhs = App.make_esp32_hall_sensor(config[CONF_NAME], config.get(CONF_UPDATE_INTERVAL))
make = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(make.Phall, make.Pmqtt, config)
BUILD_FLAGS = '-DUSE_ESP32_HALL_SENSOR'

View File

@@ -4,27 +4,28 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, variable, Application
from esphomeyaml.helpers import App, Application, variable
DEPENDENCIES = ['i2c']
MakeHDC1080Sensor = Application.MakeHDC1080Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('hdc1080_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHDC1080Sensor),
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeHDC1080Sensor = Application.MakeHDC1080Sensor
def to_code(config):
rhs = App.make_hdc1080_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_HUMIDITY][CONF_NAME],
config.get(CONF_UPDATE_INTERVAL))
hdc1080 = variable(MakeHDC1080Sensor, config[CONF_MAKE_ID], rhs)
hdc1080 = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(), hdc1080.Pmqtt_temperature,
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(),
hdc1080.Pmqtt_temperature,
config[CONF_TEMPERATURE])
sensor.setup_sensor(hdc1080.Phdc1080.Pget_humidity_sensor(), hdc1080.Pmqtt_humidity,
config[CONF_HUMIDITY])

View File

@@ -4,25 +4,25 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, variable, Application
from esphomeyaml.helpers import App, Application, variable
DEPENDENCIES = ['i2c']
MakeHTU21DSensor = Application.MakeHTU21DSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('htu21d', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHTU21DSensor),
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeHTU21DSensor = Application.MakeHTU21DSensor
def to_code(config):
rhs = App.make_htu21d_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_HUMIDITY][CONF_NAME],
config.get(CONF_UPDATE_INTERVAL))
htu21d = variable(MakeHTU21DSensor, config[CONF_MAKE_ID], rhs)
htu21d = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(htu21d.Phtu21d.Pget_temperature_sensor(), htu21d.Pmqtt_temperature,
config[CONF_TEMPERATURE])
sensor.setup_sensor(htu21d.Phtu21d.Pget_humidity_sensor(), htu21d.Pmqtt_humidity,

View File

@@ -8,24 +8,30 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN_CLOCK, CONF_PIN_
from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, \
gpio_output_pin_expression, variable
MakeMAX6675Sensor = Application.MakeMAX6675Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('max6675', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN_CS): pins.GPIO_OUTPUT_PIN_SCHEMA,
vol.Required(CONF_PIN_CLOCK): pins.GPIO_OUTPUT_PIN_SCHEMA,
vol.Optional(CONF_PIN_MISO): pins.GPIO_INPUT_PIN_SCHEMA,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMAX6675Sensor),
vol.Required(CONF_PIN_CS): pins.gpio_output_pin_schema,
vol.Required(CONF_PIN_CLOCK): pins.gpio_output_pin_schema,
vol.Required(CONF_PIN_MISO): pins.gpio_input_pin_schema,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeMAX6675Sensor = Application.MakeMAX6675Sensor
def to_code(config):
pin_cs = gpio_output_pin_expression(config[CONF_PIN_CS])
pin_clock = gpio_output_pin_expression(config[CONF_PIN_CLOCK])
pin_miso = gpio_input_pin_expression(config[CONF_PIN_MISO])
pin_cs = None
for pin_cs in gpio_output_pin_expression(config[CONF_PIN_CS]):
yield
pin_clock = None
for pin_clock in gpio_output_pin_expression(config[CONF_PIN_CLOCK]):
yield
pin_miso = None
for pin_miso in gpio_input_pin_expression(config[CONF_PIN_MISO]):
yield
rhs = App.make_max6675_sensor(config[CONF_NAME], pin_cs, pin_clock, pin_miso,
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeMAX6675Sensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(make.Pmax6675, make.Pmqtt, config)

View File

@@ -2,8 +2,7 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_MQTT_ID, CONF_NAME, \
CONF_TEMPERATURE, \
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Pvariable
@@ -16,8 +15,13 @@ CONF_GYRO_X = 'gyro_x'
CONF_GYRO_Y = 'gyro_y'
CONF_GYRO_Z = 'gyro_z'
MPU6050Component = sensor.sensor_ns.MPU6050Component
MPU6050AccelSensor = sensor.sensor_ns.MPU6050AccelSensor
MPU6050GyroSensor = sensor.sensor_ns.MPU6050GyroSensor
MPU6050TemperatureSensor = sensor.sensor_ns.MPU6050TemperatureSensor
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('mpu6050', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(MPU6050Component),
vol.Optional(CONF_ADDRESS, default=0x68): cv.i2c_address,
vol.Optional(CONF_ACCEL_X): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_ACCEL_Y): sensor.SENSOR_SCHEMA,
@@ -30,50 +34,38 @@ PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
}), cv.has_at_least_one_key(CONF_ACCEL_X, CONF_ACCEL_Y, CONF_ACCEL_Z,
CONF_GYRO_X, CONF_GYRO_Y, CONF_GYRO_Z))
MPU6050Component = sensor.sensor_ns.MPU6050Component
MPU6050AccelSensor = sensor.sensor_ns.MPU6050AccelSensor
MPU6050GyroSensor = sensor.sensor_ns.MPU6050GyroSensor
MPU6050TemperatureSensor = sensor.sensor_ns.MPU6050TemperatureSensor
def to_code(config):
rhs = App.make_mpu6050_sensor(config[CONF_ADDRESS], config.get(CONF_UPDATE_INTERVAL))
mpu = Pvariable(MPU6050Component, config[CONF_MAKE_ID], rhs)
mpu = Pvariable(config[CONF_ID], rhs)
if CONF_ACCEL_X in config:
conf = config[CONF_ACCEL_X]
rhs = mpu.Pmake_accel_x_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050AccelSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_ACCEL_Y in config:
conf = config[CONF_ACCEL_Y]
rhs = mpu.Pmake_accel_y_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050AccelSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_ACCEL_Z in config:
conf = config[CONF_ACCEL_Z]
rhs = mpu.Pmake_accel_z_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050AccelSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_GYRO_X in config:
conf = config[CONF_GYRO_X]
rhs = mpu.Pmake_gyro_x_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050GyroSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_GYRO_Y in config:
conf = config[CONF_GYRO_Y]
rhs = mpu.Pmake_gyro_y_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050GyroSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_GYRO_Z in config:
conf = config[CONF_GYRO_Z]
rhs = mpu.Pmake_gyro_z_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050GyroSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
if CONF_TEMPERATURE in config:
conf = config[CONF_TEMPERATURE]
rhs = mpu.Pmake_temperature_sensor(conf[CONF_NAME])
sensor_ = Pvariable(MPU6050TemperatureSensor, conf[CONF_MQTT_ID], rhs)
sensor.register_sensor(sensor_, conf)
sensor.register_sensor(rhs, conf)
BUILD_FLAGS = '-DUSE_MPU6050'

View File

@@ -27,8 +27,10 @@ COUNT_MODES = {
COUNT_MODE_SCHEMA = vol.All(vol.Upper, cv.one_of(*COUNT_MODES))
MakePulseCounterSensor = Application.MakePulseCounterSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('pulse_counter', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakePulseCounterSensor),
vol.Required(CONF_PIN): pins.input_pin,
vol.Optional(CONF_PULL_MODE): GPIO_PULL_MODE_SCHEMA,
vol.Optional(CONF_COUNT_MODE): vol.Schema({
@@ -39,13 +41,11 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakePulseCounterSensor = Application.MakePulseCounterSensor
def to_code(config):
rhs = App.make_pulse_counter_sensor(config[CONF_NAME], config[CONF_PIN],
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakePulseCounterSensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
pcnt = make.Ppcnt
if CONF_PULL_MODE in config:
pull_mode = GPIO_PULL_MODES[config[CONF_PULL_MODE]]

View File

@@ -16,25 +16,31 @@ CONF_PIN_A = 'pin_a'
CONF_PIN_B = 'pin_b'
CONF_PIN_RESET = 'pin_reset'
MakeRotaryEncoderSensor = Application.MakeRotaryEncoderSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('rotary_encoder', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN_A): pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
vol.Required(CONF_PIN_B): pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
vol.Optional(CONF_PIN_RESET): pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRotaryEncoderSensor),
vol.Required(CONF_PIN_A): pins.internal_gpio_input_pin_schema,
vol.Required(CONF_PIN_B): pins.internal_gpio_input_pin_schema,
vol.Optional(CONF_PIN_RESET): pins.internal_gpio_input_pin_schema,
vol.Optional(CONF_RESOLUTION): vol.All(cv.string, cv.one_of(*RESOLUTIONS)),
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeRotaryEncoderSensor = Application.MakeRotaryEncoderSensor
def to_code(config):
pin_a = gpio_input_pin_expression(config[CONF_PIN_A])
pin_b = gpio_input_pin_expression(config[CONF_PIN_B])
pin_a = None
for pin_a in gpio_input_pin_expression(config[CONF_PIN_A]):
yield
pin_b = None
for pin_b in gpio_input_pin_expression(config[CONF_PIN_B]):
yield
rhs = App.make_rotary_encoder_sensor(config[CONF_NAME], pin_a, pin_b)
make = variable(MakeRotaryEncoderSensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
encoder = make.Protary_encoder
if CONF_PIN_RESET in config:
pin_i = gpio_input_pin_expression(config[CONF_PIN_RESET])
pin_i = None
for pin_i in gpio_input_pin_expression(config[CONF_PIN_RESET]):
yield
add(encoder.set_reset_pin(pin_i))
if CONF_RESOLUTION in config:
resolution = RESOLUTIONS[config[CONF_RESOLUTION]]

View File

@@ -14,8 +14,10 @@ SHT_ACCURACIES = {
'HIGH': sensor.sensor_ns.SHT3XD_ACCURACY_HIGH,
}
MakeSHT3XDSensor = Application.MakeSHT3XDSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('sht3xd', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSHT3XDSensor),
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
vol.Optional(CONF_ADDRESS, default=0x44): cv.i2c_address,
@@ -23,14 +25,13 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
})
MakeSHT3XDSensor = Application.MakeSHT3XDSensor
def to_code(config):
rhs = App.make_sht3xd_sensor(config[CONF_TEMPERATURE][CONF_NAME],
config[CONF_HUMIDITY][CONF_NAME],
config[CONF_ADDRESS],
config.get(CONF_UPDATE_INTERVAL))
sht3xd = variable(MakeSHT3XDSensor, config[CONF_MAKE_ID], rhs)
sht3xd = variable(config[CONF_MAKE_ID], rhs)
if CONF_ACCURACY in config:
add(sht3xd.Psht3xd.set_accuracy(SHT_ACCURACIES[config[CONF_ACCURACY]]))

View File

@@ -3,22 +3,25 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, process_lambda, variable, Application
from esphomeyaml.helpers import App, process_lambda, variable, Application, float_, optional
MakeTemplateSensor = Application.MakeTemplateSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('template_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSensor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeTemplateSensor = Application.MakeTemplateSensor
def to_code(config):
template_ = process_lambda(config[CONF_LAMBDA], [])
template_ = None
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=optional.template(float_)):
yield
rhs = App.make_template_sensor(config[CONF_NAME], template_,
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeTemplateSensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
sensor.setup_sensor(make.Ptemplate_, make.Pmqtt, config)

View File

@@ -28,8 +28,10 @@ def validate_integration_time(value):
return value
MakeTSL2561Sensor = Application.MakeTSL2561Sensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('tsl2561_sensor', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTSL2561Sensor),
vol.Optional(CONF_ADDRESS, default=0x39): cv.i2c_address,
vol.Optional(CONF_INTEGRATION_TIME): validate_integration_time,
vol.Optional(CONF_GAIN): vol.All(vol.Upper, cv.one_of(*GAINS)),
@@ -37,13 +39,11 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeTSL2561Sensor = Application.MakeTSL2561Sensor
def to_code(config):
rhs = App.make_tsl2561_sensor(config[CONF_NAME], config[CONF_ADDRESS],
config.get(CONF_UPDATE_INTERVAL))
make_tsl = variable(MakeTSL2561Sensor, config[CONF_MAKE_ID], rhs)
make_tsl = variable(config[CONF_MAKE_ID], rhs)
tsl2561 = make_tsl.Ptsl2561
if CONF_INTEGRATION_TIME in config:
add(tsl2561.set_integration_time(INTEGRATION_TIMES[config[CONF_INTEGRATION_TIME]]))

View File

@@ -8,24 +8,28 @@ from esphomeyaml.const import CONF_ECHO_PIN, CONF_MAKE_ID, CONF_NAME, CONF_TIMEO
from esphomeyaml.helpers import App, Application, add, gpio_input_pin_expression, \
gpio_output_pin_expression, variable
MakeUltrasonicSensor = Application.MakeUltrasonicSensor
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID('ultrasonic', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_TRIGGER_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
vol.Required(CONF_ECHO_PIN): pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeUltrasonicSensor),
vol.Required(CONF_TRIGGER_PIN): pins.gpio_output_pin_schema,
vol.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema,
vol.Exclusive(CONF_TIMEOUT_METER, 'timeout'): cv.positive_float,
vol.Exclusive(CONF_TIMEOUT_TIME, 'timeout'): cv.positive_time_period_microseconds,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(sensor.SENSOR_SCHEMA.schema)
MakeUltrasonicSensor = Application.MakeUltrasonicSensor
def to_code(config):
trigger = gpio_output_pin_expression(config[CONF_TRIGGER_PIN])
echo = gpio_input_pin_expression(config[CONF_ECHO_PIN])
trigger = None
for trigger in gpio_output_pin_expression(config[CONF_TRIGGER_PIN]):
yield
echo = None
for echo in gpio_input_pin_expression(config[CONF_ECHO_PIN]):
yield
rhs = App.make_ultrasonic_sensor(config[CONF_NAME], trigger, echo,
config.get(CONF_UPDATE_INTERVAL))
make = variable(MakeUltrasonicSensor, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
ultrasonic = make.Pultrasonic
if CONF_TIMEOUT_TIME in config:
add(ultrasonic.set_timeout_us(config[CONF_TIMEOUT_TIME]))

View File

@@ -8,13 +8,6 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID('switch_'): cv.register_variable_id,
cv.GenerateID('mqtt_switch', CONF_MQTT_ID): cv.register_variable_id,
vol.Optional(CONF_ICON): cv.icon,
vol.Optional(CONF_INVERTED): cv.boolean,
})
switch_ns = esphomelib_ns.namespace('switch_')
Switch = switch_ns.Switch
MQTTSwitchComponent = switch_ns.MQTTSwitchComponent
@@ -22,6 +15,13 @@ ToggleAction = switch_ns.ToggleAction
TurnOffAction = switch_ns.TurnOffAction
TurnOnAction = switch_ns.TurnOnAction
SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(Switch),
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSwitchComponent),
vol.Optional(CONF_ICON): cv.icon,
vol.Optional(CONF_INVERTED): cv.boolean,
})
def setup_switch_core_(switch_var, mqtt_var, config):
if CONF_ICON in config:
@@ -33,17 +33,15 @@ def setup_switch_core_(switch_var, mqtt_var, config):
def setup_switch(switch_obj, mqtt_obj, config):
switch_var = Pvariable(Switch, config[CONF_ID], switch_obj, has_side_effects=False)
mqtt_var = Pvariable(MQTTSwitchComponent, config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False)
switch_var = Pvariable(config[CONF_ID], switch_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
setup_switch_core_(switch_var, mqtt_var, config)
def register_switch(var, config):
switch_var = Pvariable(Switch, config[CONF_ID], var, has_side_effects=True)
switch_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
rhs = App.register_switch(switch_var)
mqtt_var = Pvariable(MQTTSwitchComponent, config[CONF_MQTT_ID], rhs,
has_side_effects=True)
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
setup_switch_core_(switch_var, mqtt_var, config)

View File

@@ -6,17 +6,20 @@ from esphomeyaml.components import switch
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
from esphomeyaml.helpers import App, Application, gpio_output_pin_expression, variable
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('gpio_switch', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
}).extend(switch.SWITCH_SCHEMA.schema)
MakeGPIOSwitch = Application.MakeGPIOSwitch
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOSwitch),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
}).extend(switch.SWITCH_SCHEMA.schema)
def to_code(config):
rhs = App.make_gpio_switch(config[CONF_NAME], gpio_output_pin_expression(config[CONF_PIN]))
gpio = variable(MakeGPIOSwitch, config[CONF_MAKE_ID], rhs)
pin = None
for pin in gpio_output_pin_expression(config[CONF_PIN]):
yield
rhs = App.make_gpio_switch(config[CONF_NAME], pin)
gpio = variable(config[CONF_MAKE_ID], rhs)
switch.setup_switch(gpio.Pswitch_, gpio.Pmqtt, config)

View File

@@ -17,7 +17,6 @@ WAIT_TIME_MESSAGE = "The wait_time_us option has been renamed to wait_time in or
"ambiguity. "
PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('ir_transmitter_switch'): cv.register_variable_id,
vol.Exclusive(CONF_NEC, 'code'): vol.Schema({
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
@@ -44,7 +43,7 @@ PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({
vol.Optional('wait_time_us'): cv.invalid(WAIT_TIME_MESSAGE),
})),
vol.Optional(CONF_IR_TRANSMITTER_ID): cv.variable_id,
cv.GenerateID(CONF_IR_TRANSMITTER_ID): cv.use_variable_id(IRTransmitterComponent),
vol.Optional(CONF_INVERTED): cv.invalid("IR Transmitters do not support inverted mode!"),
}).extend(switch.SWITCH_SCHEMA.schema), cv.has_at_least_one_key(*IR_KEYS))
@@ -94,7 +93,9 @@ def exp_send_data(config):
def to_code(config):
ir = get_variable(config.get(CONF_IR_TRANSMITTER_ID), IRTransmitterComponent)
ir = None
for ir in get_variable(config[CONF_IR_TRANSMITTER_ID]):
yield
send_data = exp_send_data(config)
rhs = App.register_component(ir.create_transmitter(config[CONF_NAME], send_data))
switch.register_switch(rhs, config)

View File

@@ -5,18 +5,20 @@ from esphomeyaml.components import switch
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
from esphomeyaml.helpers import App, Application, get_variable, variable
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('output_switch', CONF_MAKE_ID): cv.register_variable_id,
vol.Required(CONF_OUTPUT): cv.variable_id,
}).extend(switch.SWITCH_SCHEMA.schema)
MakeSimpleSwitch = Application.MakeSimpleSwitch
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSimpleSwitch),
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
}).extend(switch.SWITCH_SCHEMA.schema)
def to_code(config):
output = get_variable(config[CONF_OUTPUT])
output = None
for output in get_variable(config[CONF_OUTPUT]):
yield
rhs = App.make_simple_switch(config[CONF_NAME], output)
gpio = variable(MakeSimpleSwitch, config[CONF_MAKE_ID], rhs)
gpio = variable(config[CONF_MAKE_ID], rhs)
switch.setup_switch(gpio.Pswitch_, gpio.Pmqtt, config)

View File

@@ -5,17 +5,17 @@ from esphomeyaml.components import switch
from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME
from esphomeyaml.helpers import App, Application, variable
MakeRestartSwitch = Application.MakeRestartSwitch
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('restart_switch', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRestartSwitch),
vol.Optional(CONF_INVERTED): cv.invalid("Restart switches do not support inverted mode!"),
}).extend(switch.SWITCH_SCHEMA.schema)
MakeRestartSwitch = Application.MakeRestartSwitch
def to_code(config):
rhs = App.make_restart_switch(config[CONF_NAME])
restart = variable(MakeRestartSwitch, config[CONF_MAKE_ID], rhs)
restart = variable(config[CONF_MAKE_ID], rhs)
switch.setup_switch(restart.Prestart, restart.Pmqtt, config)

View File

@@ -5,17 +5,17 @@ from esphomeyaml.components import switch
from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME
from esphomeyaml.helpers import App, Application, variable
MakeShutdownSwitch = Application.MakeShutdownSwitch
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('shutdown_switch', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeShutdownSwitch),
vol.Optional(CONF_INVERTED): cv.invalid("Shutdown switches do not support inverted mode!"),
}).extend(switch.SWITCH_SCHEMA.schema)
MakeShutdownSwitch = Application.MakeShutdownSwitch
def to_code(config):
rhs = App.make_shutdown_switch(config[CONF_NAME])
shutdown = variable(MakeShutdownSwitch, config[CONF_MAKE_ID], rhs)
shutdown = variable(config[CONF_MAKE_ID], rhs)
switch.setup_switch(shutdown.Pshutdown, shutdown.Pmqtt, config)

View File

@@ -5,31 +5,39 @@ from esphomeyaml import automation
from esphomeyaml.components import switch
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_TURN_OFF_ACTION, \
CONF_TURN_ON_ACTION, CONF_OPTIMISTIC
from esphomeyaml.helpers import App, Application, process_lambda, variable, NoArg, add
from esphomeyaml.helpers import App, Application, process_lambda, variable, NoArg, add, bool_, \
optional
MakeTemplateSwitch = Application.MakeTemplateSwitch
PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({
cv.GenerateID('template_switch', CONF_MAKE_ID): cv.register_variable_id,
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSwitch),
vol.Optional(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_TURN_OFF_ACTION): automation.ACTIONS_SCHEMA,
vol.Optional(CONF_TURN_ON_ACTION): automation.ACTIONS_SCHEMA,
}).extend(switch.SWITCH_SCHEMA.schema), cv.has_at_exactly_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
MakeTemplateSwitch = Application.MakeTemplateSwitch
}).extend(switch.SWITCH_SCHEMA.schema), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
def to_code(config):
rhs = App.make_template_switch(config[CONF_NAME])
make = variable(MakeTemplateSwitch, config[CONF_MAKE_ID], rhs)
make = variable(config[CONF_MAKE_ID], rhs)
if CONF_LAMBDA in config:
template_ = process_lambda(config[CONF_LAMBDA], [])
add(make.Ptemplate.set_state_lambda(template_))
template_ = None
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=optional.template(bool_)):
yield
add(make.Ptemplate_.set_state_lambda(template_))
if CONF_TURN_OFF_ACTION in config:
actions = automation.build_actions(config[CONF_TURN_OFF_ACTION], NoArg)
actions = None
for actions in automation.build_actions(config[CONF_TURN_OFF_ACTION], NoArg):
yield
add(make.Ptemplate_.add_turn_off_actions(actions))
if CONF_TURN_ON_ACTION in config:
actions = automation.build_actions(config[CONF_TURN_ON_ACTION], NoArg)
actions = None
for actions in automation.build_actions(config[CONF_TURN_ON_ACTION], NoArg):
yield
add(make.Ptemplate_.add_turn_on_actions(actions))
if CONF_OPTIMISTIC in config:
add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC]))

View File

@@ -9,19 +9,19 @@ from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('web_server'): cv.register_variable_id,
vol.Optional(CONF_PORT): cv.port,
vol.Optional(CONF_CSS_URL): vol.Url,
vol.Optional(CONF_JS_URL): vol.Url,
})
WebServer = esphomelib_ns.WebServer
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(WebServer),
vol.Optional(CONF_PORT): cv.port,
vol.Optional(CONF_CSS_URL): cv.string,
vol.Optional(CONF_JS_URL): cv.string,
})
def to_code(config):
rhs = App.init_web_server(config.get(CONF_PORT))
web_server = Pvariable(WebServer, config[CONF_ID], rhs)
web_server = Pvariable(config[CONF_ID], rhs)
if CONF_CSS_URL in config:
add(web_server.set_css_url(config[CONF_CSS_URL]))
if CONF_JS_URL in config:

View File

@@ -30,8 +30,13 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({
vol.Inclusive(CONF_DNS2, 'dns'): cv.ipv4,
})
# pylint: disable=invalid-name
IPAddress = global_ns.IPAddress
ManualIP = esphomelib_ns.ManualIP
WiFiComponent = esphomelib_ns.WiFiComponent
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID('wifi'): cv.register_variable_id,
cv.GenerateID(): cv.declare_variable_id(WiFiComponent),
vol.Optional(CONF_SSID): cv.ssid,
vol.Optional(CONF_PASSWORD): validate_password,
vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
@@ -42,14 +47,9 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA,
}),
vol.Optional(CONF_HOSTNAME): cv.hostname,
vol.Required(CONF_DOMAIN, default='.local'): cv.domainname,
vol.Optional(CONF_DOMAIN, default='.local'): cv.domainname,
})
# pylint: disable=invalid-name
IPAddress = global_ns.IPAddress
ManualIP = esphomelib_ns.ManualIP
WiFiComponent = esphomelib_ns.WiFiComponent
def safe_ip(ip):
if ip is None:
@@ -75,7 +75,7 @@ def to_code(config):
rhs = App.init_wifi(config[CONF_SSID], config.get(CONF_PASSWORD))
else:
rhs = App.init_wifi()
wifi = Pvariable(WiFiComponent, config[CONF_ID], rhs)
wifi = Pvariable(config[CONF_ID], rhs)
if sta and CONF_MANUAL_IP in config:
add(wifi.set_sta_manual_ip(manual_ip(config[CONF_MANUAL_IP])))

View File

@@ -1,6 +1,6 @@
{
"name": "esphomeyaml",
"version": "1.6.0",
"version": "1.6.2",
"slug": "esphomeyaml",
"description": "esphomeyaml HassIO add-on for intelligently managing all your ESP8266/ESP32 devices.",
"url": "https://esphomelib.com/esphomeyaml/index.html",
@@ -19,5 +19,6 @@
"environment": {
"ESPHOMEYAML_OTA_HOST_PORT": "6053"
},
"schema": {}
"schema": {},
"image": "ottowinter/esphomeyaml-hassio-{arch}"
}

View File

@@ -18,7 +18,7 @@ from esphomeyaml.helpers import App, add, color
_LOGGER = logging.getLogger(__name__)
DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.6.0'
DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.6.2'
BUILD_FLASH_MODES = ['qio', 'qout', 'dio', 'dout']
@@ -93,6 +93,50 @@ class Config(OrderedDict):
self.errors.append((message, domain, config))
def iter_ids(config, prefix=None, parent=None):
prefix = prefix or []
parent = parent or {}
if isinstance(config, core.ID):
yield config, prefix, parent
elif isinstance(config, core.Lambda):
for id in config.requires_ids:
yield id, prefix, parent
elif isinstance(config, list):
for i, item in enumerate(config):
for result in iter_ids(item, prefix + [str(i)], config):
yield result
elif isinstance(config, dict):
for key, value in config.iteritems():
for result in iter_ids(value, prefix + [str(key)], config):
yield result
def do_id_pass(result):
declare_ids = []
searching_ids = []
for id, prefix, config in iter_ids(result):
if id.is_declaration:
if id.id is not None and any(v[0].id == id.id for v in declare_ids):
result.add_error("ID {} redefined!".format(id.id), '.'.join(prefix), config)
continue
declare_ids.append((id, prefix, config))
else:
searching_ids.append((id, prefix, config))
# Resolve default ids after manual IDs
for id, _, _ in declare_ids:
id.resolve([v[0].id for v in declare_ids])
# Check searched IDs
for id, prefix, config in searching_ids:
if id.id is not None and not any(v[0].id == id.id for v in declare_ids):
result.add_error("Couldn't find ID {}".format(id.id), '.'.join(prefix), config)
if id.id is None and id.type is not None:
id.id = next((v[0].id for v in declare_ids if v[0].type == id.type), None)
if id.id is None:
result.add_error("Couldn't resolve ID for type {}".format(id.type),
'.'.join(prefix), config)
def validate_config(config):
global _ALL_COMPONENTS
@@ -131,7 +175,7 @@ def validate_config(config):
dependencies = getattr(component, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in _ALL_COMPONENTS:
result.add_error(u"Component {} requires {}".format(domain, dependency))
result.add_error(u"Component {} requires component {}".format(domain, dependency))
success = False
if not success:
continue
@@ -165,8 +209,8 @@ def validate_config(config):
dependencies = getattr(platform, 'DEPENDENCIES', [])
for dependency in dependencies:
if dependency not in _ALL_COMPONENTS:
result.add_error(u"Platform {}.{} requires {}".format(domain, p_name,
dependency))
result.add_error(u"Platform {}.{} requires component {}".format(domain, p_name,
dependency))
success = False
if not success:
continue
@@ -185,6 +229,8 @@ def validate_config(config):
continue
platforms.append(p_validated)
result[domain] = platforms
do_id_pass(result)
return result
@@ -237,8 +283,10 @@ def load_config(path):
try:
result = validate_config(config)
except ESPHomeYAMLError:
raise
except Exception:
print(u"Unexpected exception while reading configuration:")
_LOGGER.error(u"Unexpected exception while reading configuration:")
raise
return result
@@ -279,18 +327,18 @@ def dump_dict(layer, indent_count=3, listi=False, **kwargs):
def read_config(path):
_LOGGER.debug("Reading configuration...")
_LOGGER.info("Reading configuration...")
try:
res = load_config(path)
except ESPHomeYAMLError as err:
_LOGGER.error(u"Error while reading config: %s", err)
return None
excepts = {}
for err in res.errors:
domain = err[1] or u"General Error"
excepts.setdefault(domain, []).append(err[0])
if err[2] is not None:
excepts[domain].append(err[2])
for message, domain, config in res.errors:
domain = domain or u"General Error"
excepts.setdefault(domain, []).append(message)
if config is not None:
excepts[domain].append(config)
if excepts:
print(color('bold_white', u"Failed config"))

View File

@@ -12,9 +12,8 @@ from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOV
CONF_NAME, CONF_PAYLOAD_AVAILABLE, \
CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
from esphomeyaml.core import HexInt, IPAddress, TimePeriod, TimePeriodMicroseconds, \
TimePeriodMilliseconds, TimePeriodSeconds, Lambda
from esphomeyaml.helpers import ensure_unique_string
from esphomeyaml.core import HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \
TimePeriodMilliseconds, TimePeriodSeconds
_LOGGER = logging.getLogger(__name__)
@@ -57,8 +56,10 @@ def alphanumeric(value):
def valid_name(value):
value = string_strict(value)
if not all(c in ALLOWED_NAME_CHARS for c in value):
raise vol.Invalid(u"Valid characters for name are {}".format(ALLOWED_NAME_CHARS))
for c in value:
if c not in ALLOWED_NAME_CHARS:
raise vol.Invalid(u"'{}' is an invalid character for names. Valid characters are: {}"
u"".format(c, ALLOWED_NAME_CHARS))
return value
@@ -136,7 +137,7 @@ def int_(value):
hex_int = vol.Coerce(hex_int_)
def variable_id(value):
def variable_id_str_(value):
value = string(value)
if not value:
raise vol.Invalid("ID must not be empty")
@@ -153,11 +154,32 @@ def variable_id(value):
return value
def use_variable_id(type):
def validator(value):
if value is None:
return core.ID(None, is_declaration=False, type=type)
return core.ID(variable_id_str_(value), is_declaration=False, type=type)
return validator
def declare_variable_id(type):
def validator(value):
if value is None:
return core.ID(None, is_declaration=True, type=type)
return core.ID(variable_id_str_(value), is_declaration=True, type=type)
return validator
def templatable(other_validators):
def validator(value):
if isinstance(value, Lambda):
return value
return other_validators(value)
return validator
@@ -194,7 +216,7 @@ def has_at_least_one_key(*keys):
return validate
def has_at_exactly_one_key(*keys):
def has_exactly_one_key(*keys):
def validate(obj):
if not isinstance(obj, dict):
raise vol.Invalid('expected dictionary')
@@ -224,7 +246,6 @@ time_period_dict = vol.All(
'seconds', 'milliseconds', 'microseconds'),
lambda value: TimePeriod(**value))
TIME_PERIOD_EXPLICIT_MESSAGE = ("The old way of being able to write time values without a "
"time unit (like \"1000\" for 1000 milliseconds) has been "
"removed in 1.5.0 as it was ambiguous in some places. Please "
@@ -322,7 +343,6 @@ positive_time_period_microseconds = vol.All(positive_time_period, time_period_in
positive_not_null_time_period = vol.All(time_period,
vol.Range(min=TimePeriod(), min_included=False))
METRIC_SUFFIXES = {
'E': 1e18, 'P': 1e15, 'T': 1e12, 'G': 1e9, 'M': 1e6, 'k': 1e3, 'da': 10, 'd': 1e-1,
'c': 1e-2, 'm': 0.001, u'µ': 1e-6, 'u': 1e-6, 'n': 1e-9, 'p': 1e-12, 'f': 1e-15, 'a': 1e-18,
@@ -479,6 +499,7 @@ def percentage(value):
def invalid(message):
def validator(value):
raise vol.Invalid(message)
return validator
@@ -493,6 +514,7 @@ def one_of(*values):
if value not in values:
raise vol.Invalid(u"Unknown value '{}', must be one of {}".format(value, options))
return value
return validator
@@ -505,26 +527,10 @@ def lambda_(value):
REGISTERED_IDS = set()
def register_variable_id(value):
s = variable_id(value)
if s in REGISTERED_IDS:
raise vol.Invalid("This ID has already been used")
REGISTERED_IDS.add(s)
return s
class GenerateID(vol.Optional):
def __init__(self, basename, key=CONF_ID):
self._basename = basename
super(GenerateID, self).__init__(key, default=self.default_variable_id)
def __init__(self, key=CONF_ID):
super(GenerateID, self).__init__(key, default=lambda: None)
def default_variable_id(self):
return ensure_unique_string(self._basename, REGISTERED_IDS)
REQUIRED_ID_SCHEMA = vol.Schema({
vol.Required(CONF_ID): register_variable_id,
})
PLATFORM_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): valid,
@@ -541,7 +547,7 @@ MQTT_COMPONENT_SCHEMA = vol.Schema({
vol.Optional(CONF_RETAIN): boolean,
vol.Optional(CONF_DISCOVERY): boolean,
vol.Optional(CONF_STATE_TOPIC): publish_topic,
vol.Optional(CONF_AVAILABILITY): MQTT_COMPONENT_AVAILABILITY_SCHEMA,
vol.Optional(CONF_AVAILABILITY): vol.Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA),
})
MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend({

View File

@@ -2,7 +2,7 @@
MAJOR_VERSION = 1
MINOR_VERSION = 6
PATCH_VERSION = '0'
PATCH_VERSION = '2'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
@@ -253,3 +253,5 @@ ESP_BOARDS_FOR_PLATFORM = {
ESP_PLATFORM_ESP32: ESP32_BOARDS,
ESP_PLATFORM_ESP8266: ESP8266_BOARDS
}
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_'

View File

@@ -1,4 +1,5 @@
import math
import re
from collections import OrderedDict
@@ -174,11 +175,59 @@ class TimePeriodSeconds(TimePeriod):
class Lambda(object):
def __init__(self, value):
self.value = value
self.parts = re.split(r'id\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)\.', value)
self.requires_ids = [ID(self.parts[i]) for i in range(1, len(self.parts), 2)]
def __str__(self):
return self.value
def __repr__(self):
return u'Lambda<{}>'.format(self.value)
def ensure_unique_string(preferred_string, current_strings):
test_string = preferred_string
current_strings_set = set(current_strings)
tries = 1
while test_string in current_strings_set:
tries += 1
test_string = u"{}_{}".format(preferred_string, tries)
return test_string
class ID(object):
def __init__(self, id, is_declaration=False, type=None):
self.id = id
self.is_manual = id is not None
self.is_declaration = is_declaration
self.type = type
def resolve(self, registered_ids):
if self.id is None:
base = str(self.type).replace('::', '_').lower()
name = ''.join(c for c in base if c.isalnum() or c == '_')
self.id = ensure_unique_string(name, registered_ids)
return self.id
def __str__(self):
return self.id
def __repr__(self):
return u'ID<{} declaration={}, type={}, manual={}>'.format(
self.id, self.is_declaration, self.type, self.is_manual)
def __eq__(self, other):
if not isinstance(other, ID):
raise ValueError("other must be ID")
return self.id == other.id
def __hash__(self):
return hash(self.id)
CONFIG_PATH = None
SIMPLIFY = True
ESP_PLATFORM = ''

View File

@@ -1,3 +1,4 @@
# pylint: disable=wrong-import-position
from __future__ import print_function
import codecs
@@ -7,6 +8,11 @@ import os
import random
import subprocess
from esphomeyaml.core import ESPHomeYAMLError
from esphomeyaml import const, core, __main__
from esphomeyaml.__main__ import get_serial_ports, get_base_path, get_name
from esphomeyaml.helpers import quote
try:
import tornado
import tornado.gen
@@ -17,15 +23,12 @@ try:
import tornado.websocket
import tornado.concurrent
except ImportError as err:
pass
from esphomeyaml import const, core, __main__
from esphomeyaml.__main__ import get_serial_ports, get_base_path, get_name
from esphomeyaml.helpers import quote
tornado = None
_LOGGER = logging.getLogger(__name__)
CONFIG_DIR = ''
# pylint: disable=abstract-method, arguments-differ
class EsphomeyamlCommandWebSocket(tornado.websocket.WebSocketHandler):
def __init__(self, application, request, **kwargs):
@@ -93,17 +96,27 @@ class EsphomeyamlCompileHandler(EsphomeyamlCommandWebSocket):
return ["esphomeyaml", config_file, "compile"]
class EsphomeyamlValidateHandler(EsphomeyamlCommandWebSocket):
def build_command(self, message):
js = json.loads(message)
config_file = os.path.join(CONFIG_DIR, js['configuration'])
return ["esphomeyaml", config_file, "config"]
class SerialPortRequestHandler(tornado.web.RequestHandler):
def get(self):
ports = get_serial_ports()
data = []
for port, desc in ports:
if port == '/dev/ttyAMA0':
# ignore RPi built-in serial port
continue
desc = 'UART pins on GPIO header'
split_desc = desc.split(' - ')
if len(split_desc) == 2 and split_desc[0] == split_desc[1]:
# Some serial ports repeat their values
desc = split_desc[0]
data.append({'port': port, 'desc': desc})
data.append({'port': 'OTA', 'desc': 'Over-The-Air Upload/Logs'})
self.write(json.dumps(data))
data.append({'port': 'OTA', 'desc': 'Over-The-Air'})
self.write(json.dumps(sorted(data, reverse=True)))
class WizardRequestHandler(tornado.web.RequestHandler):
@@ -116,7 +129,7 @@ class WizardRequestHandler(tornado.web.RequestHandler):
with codecs.open(destination, 'w') as f_handle:
f_handle.write(config)
self.redirect('/')
self.redirect('/?begin=True')
class DownloadBinaryRequestHandler(tornado.web.RequestHandler):
@@ -140,36 +153,43 @@ class DownloadBinaryRequestHandler(tornado.web.RequestHandler):
class MainRequestHandler(tornado.web.RequestHandler):
def get(self):
begin = bool(self.get_argument('begin', False))
files = sorted([f for f in os.listdir(CONFIG_DIR) if f.endswith('.yaml') and
not f.startswith('.')])
full_path_files = [os.path.join(CONFIG_DIR, f) for f in files]
self.render("templates/index.html", files=files, full_path_files=full_path_files,
version=const.__version__)
version=const.__version__, begin=begin)
def make_app():
def make_app(debug=False):
static_path = os.path.join(os.path.dirname(__file__), 'static')
return tornado.web.Application([
(r"/", MainRequestHandler),
(r"/logs", EsphomeyamlLogsHandler),
(r"/run", EsphomeyamlRunHandler),
(r"/compile", EsphomeyamlCompileHandler),
(r"/validate", EsphomeyamlValidateHandler),
(r"/download.bin", DownloadBinaryRequestHandler),
(r"/serial-ports", SerialPortRequestHandler),
(r"/wizard.html", WizardRequestHandler),
(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': static_path}),
], debug=False)
], debug=debug)
def start_web_server(args):
global CONFIG_DIR
if tornado is None:
raise ESPHomeYAMLError("Attempted to load dashboard, but tornado is not installed! "
"Please run \"pip2 install tornado esptool\" in your terminal.")
CONFIG_DIR = args.configuration
if not os.path.exists(CONFIG_DIR):
os.makedirs(CONFIG_DIR)
_LOGGER.info("Starting dashboard web server on port %s and configuration dir %s...",
args.port, CONFIG_DIR)
app = make_app()
app = make_app(args.verbose)
app.listen(args.port)
try:
tornado.ioloop.IOLoop.current().start()

View File

@@ -121,9 +121,9 @@
}
.modal {
width: 90%;
max-height: 85%;
height: 80% !important;
width: 95%;
max-height: 90%;
height: 85% !important;
}
.page-footer {
@@ -155,7 +155,9 @@
}
.select-port-container {
margin-top: 19px;
margin-top: 8px;
margin-right: 24px;
width: 350px;
}
</style>
</head>
@@ -165,9 +167,23 @@
<nav>
<div class="nav-wrapper indigo">
<a href="#" class="brand-logo left">esphomeyaml Dashboard</a>
<div class="select-port-container right" id="select-port-target">
<select></select>
</div>
</div>
</nav>
<div class="tap-target pink lighten-1 select-port" data-target="select-port-target">
<div class="tap-target-content">
<h5>Select Upload Port</h5>
<p>
Here you can select where esphomeyaml will attempt to show logs and upload firmwares to.
By default, this is "OTA", or Over-The-Air. Note that you might have to restart the HassIO add-on
for new serial ports to be detected.
</p>
</div>
</div>
<div class="ribbon"></div>
</header>
@@ -191,6 +207,7 @@
<a href="#" class="action-upload" data-node="{{ file }}">Upload</a>
<a href="#" class="action-compile" data-node="{{ file }}">Compile</a>
<a href="#" class="action-show-logs" data-node="{{ file }}">Show Logs</a>
<a href="#" class="action-validate" data-node="{{ file }}">Validate</a>
</div>
</div>
</div>
@@ -201,64 +218,50 @@
<div id="modal-logs" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Show Logs</h4>
<div class="upload-port row">
<div class="col s12">
<h5>Found multiple serial ports, please choose one:</h5>
</div>
<div class="input-field col s8">
<select></select>
</div>
<div class="col s4 select-port-container">
<button class="btn waves-effect waves-light upload-port-submit" type="submit" name="action">Select
<i class="material-icons right">send</i>
</button>
</div>
</div>
<h4>Show Logs <code class="inlinecode filename"></code></h4>
<div class="log-container">
<pre class="log"></pre>
</div>
</div>
<div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Close</a>
</div>
</div>
<div id="modal-upload" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Compile And Upload</h4>
<div class="upload-port row">
<div class="col s12">
<h5>Found multiple upload options, please choose one:</h5>
</div>
<div class="input-field col s8">
<select></select>
</div>
<div class="col s4 select-port-container">
<button class="btn waves-effect waves-light upload-port-submit" type="submit" name="action">Select
<i class="material-icons right">send</i>
</button>
</div>
</div>
<h4>Compile And Upload <code class="inlinecode filename"></code></h4>
<div class="log-container">
<pre class="log"></pre>
</div>
</div>
<div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat">Stop</a>
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
</div>
</div>
<div id="modal-compile" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Compile</h4>
<h4>Compile <code class="inlinecode filename"></code></h4>
<div class="log-container">
<pre class="log"></pre>
</div>
</div>
<div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat disabled download-binary">Download Binary</a>
<a class="modal-close waves-effect waves-green btn-flat">Stop</a>
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
</div>
</div>
<div id="modal-validate" class="modal modal-fixed-footer">
<div class="modal-content">
<h4>Validate <code class="inlinecode filename"></code></h4>
<div class="log-container">
<pre class="log"></pre>
</div>
</div>
<div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
</div>
</div>
@@ -278,7 +281,7 @@
their successors (the <a href="https://www.espressif.com/en/products/hardware/esp32/overview" target="_blank">ESP32s</a>)
are great low-cost microcontrollers that can communicate with the outside world using WiFi.
They're found in many devices such as the popular Sonoff/iTead, but also exist as development boards
such as the <a href="http://nodemcu.com/index_en.html" target="_blank">NodeMCU</a>.
such as the <a href="https://esphomelib.com/esphomeyaml/devices/nodemcu_esp8266.html" target="_blank">NodeMCU</a>.
<p>
</p>
<a href="https://esphomelib.com/esphomeyaml/index.html" target="_blank">esphomeyaml</a>,
@@ -303,7 +306,7 @@
</div>
</div>
<div class="step-actions">
<button class="waves-effect waves-dark btn indigo next-step"">CONTINUE</button>
<button class="waves-effect waves-dark btn indigo next-step">CONTINUE</button>
</div>
</div>
</li>
@@ -313,8 +316,7 @@
<div class="row">
<p>
Great! Now I need to know what type of microcontroller you're using so that I can compile firmware for them.
Please choose either ESP32 or ESP8266 (use ESP8266 for Sonoff devices). Note that the ESP32 is currently
unsupported if HassIO is running on a Raspberry Pi.
Please choose either ESP32 or ESP8266 (use ESP8266 for Sonoff devices).
</p>
<div class="input-field col s12">
<select id="esp_type" name="platform" required>
@@ -358,8 +360,8 @@
</div>
<p>
Esphomelib automatically sets up an Over-The-Air update server on the node
so that you only need to flash a firmware once. Optionally, you can set a password for this
upload process here.
so that you only need to flash a firmware via USB once.
Optionally, you can set a password for this upload process here:
</p>
<div class="input-field col s12">
<input id="ota_password" class="validate" name="ota_password" type="password">
@@ -384,7 +386,7 @@
<p>
When you're done with that, please enter your MQTT broker here. For example
<code class="inlinecode">192.168.1.100</code> (Note
<code class="inlinecode">hassio.local</code> often doesn't work, please use a static IP).
<code class="inlinecode">hassio.local</code> doesn't always work, please use a static IP).
Please also specify the MQTT username and password you wish esphomelib to use
(leave them empty if you're not using any authentication).
</p>
@@ -420,22 +422,29 @@
<ul class="browser-default">
<li>
Flash the firmware. This can be done using the “UPLOAD” option in the dashboard. See
<a href="https://esphomelib.com/esphomeyaml/index.html#using-with" target="_blank">this</a>
<a href="https://esphomelib.com/esphomeyaml/index.html#devices" target="_blank">this</a>
for guides on how to flash different types of devices. Note that you need to restart this add-on
for newly plugged in serial devices to be detected.
</li>
<li>
With the current configuration, your node will only connect to WiFi and MQTT. To make it actually <i>do</i>
stuff, follow
<a href="https://esphomelib.com/esphomeyaml/guides/getting_started_hassio.html#adding-some-basic-features">
the rest of the getting started guide
</a>.
</li>
<li>
See the <a href="https://esphomelib.com/esphomeyaml/index.html" target="_blank">esphomeyaml index</a>
for a list of supported sensors/devices.
</li>
<li>
Join the <a href="https://discord.gg/KhAMKrd" target="_blank">Discord server</a> and say hi. When I
Join the <a href="https://discord.gg/KhAMKrd" target="_blank">Discord server</a> and say hi! When I
have time, I would be happy to help with issues and discuss new features.
</li>
<li>
Star <a href="https://github.com/OttoWinter/esphomelib" target="_blank">esphomelib</a> and
<a href="https://github.com/OttoWinter/esphomeyaml" target="_blank">esphomeyaml</a> on GitHub and
report issues using the bug trackers there.
<a href="https://github.com/OttoWinter/esphomeyaml" target="_blank">esphomeyaml</a> on GitHub
if you find this software awesome and report issues using the bug trackers there.
</li>
</ul>
<div class="step-actions">
@@ -455,7 +464,7 @@
<i class="material-icons">add</i>
</a>
<div class="tap-target pink lighten-1" data-target="setup-wizard-start">
<div class="tap-target pink lighten-1 setup-wizard" data-target="setup-wizard-start">
<div class="tap-target-content">
<h5>Set up your first Node</h5>
<p>
@@ -505,19 +514,67 @@
};
let configuration = "";
const ws_url = 'ws://' + window.location.hostname + ':' + window.location.port;
let wsProtocol = "ws:";
if (window.location.protocol === "https:") {
wsProtocol = 'wss:';
}
const wsUrl = wsProtocol + '//' + window.location.hostname + ':' + window.location.port;
const portSelect = document.querySelector('.nav-wrapper select');
let ports = [];
const fetchSerialPorts = (begin=false) => {
fetch('/serial-ports').then(res => res.json())
.then(response => {
if (ports.length === response.length) {
let allEqual = true;
for (let i = 0; i < response.length; i++) {
if (ports[i].port !== response[i].port) {
allEqual = false;
break;
}
}
if (allEqual)
return;
}
ports = response;
const inst = M.FormSelect.getInstance(portSelect);
if (inst !== undefined) {
inst.destroy();
}
portSelect.innerHTML = "";
const prevSelected = getUploadPort();
for (let i = 0; i < response.length; i++) {
const val = response[i];
if (val.port === prevSelected) {
portSelect.innerHTML += `<option value="${val.port}" selected>${val.port} (${val.desc})</option>`;
} else {
portSelect.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
}
}
M.FormSelect.init(portSelect, {});
if (!begin)
M.toast({html: "Discovered new serial port."});
});
};
const getUploadPort = () => {
const inst = M.FormSelect.getInstance(portSelect);
if (inst === undefined) {
return "OTA";
}
inst._setSelectedStates();
return inst.getSelectedValues()[0];
};
setInterval(fetchSerialPorts, 5000);
fetchSerialPorts(true);
const logsModalElem = document.getElementById("modal-logs");
const logsPortSelect = logsModalElem.querySelector('select');
const logsPortDiv = logsModalElem.querySelector(".upload-port");
const logsPortSubmit = logsModalElem.querySelector('.upload-port-submit');
let logsStart = undefined;
logsPortSubmit.addEventListener('click', () => {
const inst = M.FormSelect.getInstance(logsPortSelect);
logsStart(inst.getSelectedValues()[0]);
inst.destroy();
});
document.querySelectorAll(".action-show-logs").forEach((showLogs) => {
showLogs.addEventListener('click', (e) => {
@@ -525,145 +582,15 @@
const modalInstance = M.Modal.getInstance(logsModalElem);
const log = logsModalElem.querySelector(".log");
log.innerHTML = "";
if (M.FormSelect.getInstance(logsPortSelect) !== undefined) {
M.FormSelect.getInstance(logsPortSelect).destroy();
}
const stopLogsButton = logsModalElem.querySelector(".stop-logs");
let stopped = false;
stopLogsButton.innerHTML = "Stop";
modalInstance.open();
if (logsPortDiv.classList.contains('hide')) {
logsPortDiv.classList.remove('hide');
}
const filenameField = logsModalElem.querySelector('.filename');
filenameField.innerHTML = configuration;
logsStart = (port) => {
logsPortDiv.classList.add('hide');
const logSocket = new WebSocket(ws_url + "/logs");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully!"});
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration, port: port});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
M.toast({html: 'Terminated process.'});
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
};
fetch('/serial-ports').then(res => res.json())
.then(response => {
if (response.length > 1) {
logsPortSelect.innerHTML = "";
for (let i = 0; i < response.length; i++) {
const val = response[i];
logsPortSelect.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
}
M.FormSelect.init(logsPortSelect, {});
} else {
logsStart("OTA");
}
});
});
});
const uploadModalElem = document.getElementById("modal-upload");
const uploadPortSelect = uploadModalElem.querySelector('select');
const uploadPortDiv = uploadModalElem.querySelector(".upload-port");
const uploadPortSubmit = uploadModalElem.querySelector('.upload-port-submit');
let uploadStart = undefined;
uploadPortSubmit.addEventListener('click', () => {
const inst = M.FormSelect.getInstance(uploadPortSelect);
uploadStart(inst.getSelectedValues()[0]);
inst.destroy();
});
document.querySelectorAll(".action-upload").forEach((showLogs) => {
showLogs.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(uploadModalElem);
const log = uploadModalElem.querySelector(".log");
log.innerHTML = "";
if (M.FormSelect.getInstance(uploadPortSelect) !== undefined) {
M.FormSelect.getInstance(uploadPortSelect).destroy();
}
modalInstance.open();
if (uploadPortDiv.classList.contains('hide')) {
uploadPortDiv.classList.remove('hide');
}
uploadStart = (port) => {
uploadPortDiv.classList.add('hide');
const logSocket = new WebSocket(ws_url + "/run");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully!"});
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration, port: port});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
M.toast({html: 'Terminated process.'});
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
};
fetch('/serial-ports').then(res => res.json())
.then(response => {
if (response.length > 1) {
uploadPortSelect.innerHTML = "";
for (let i = 0; i < response.length; i++) {
const val = response[i];
uploadPortSelect.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
}
M.FormSelect.init(uploadPortSelect, {});
} else {
uploadStart("OTA");
}
});
});
});
const compileModalElem = document.getElementById("modal-compile");
const downloadButton = compileModalElem.querySelector('.download-binary');
document.querySelectorAll(".action-compile").forEach((showLogs) => {
showLogs.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(compileModalElem);
const log = compileModalElem.querySelector(".log");
log.innerHTML = "";
downloadButton.classList.add('disabled');
modalInstance.open();
const logSocket = new WebSocket(ws_url + "/compile");
const logSocket = new WebSocket(wsUrl + "/logs");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
@@ -671,19 +598,23 @@
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully!"});
downloadButton.classList.remove('disabled');
M.toast({html: "Program exited successfully."});
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
stopLogsButton.innerHTML = "Close";
stopped = true;
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration});
const msg = JSON.stringify({configuration: configuration, port: getUploadPort()});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
M.toast({html: 'Terminated process.'});
if (!stopped) {
M.toast({html: 'Terminated process.'});
}
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
@@ -691,6 +622,159 @@
});
});
const uploadModalElem = document.getElementById("modal-upload");
document.querySelectorAll(".action-upload").forEach((upload) => {
upload.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(uploadModalElem);
const log = uploadModalElem.querySelector(".log");
log.innerHTML = "";
const stopLogsButton = uploadModalElem.querySelector(".stop-logs");
let stopped = false;
stopLogsButton.innerHTML = "Stop";
modalInstance.open();
const filenameField = uploadModalElem.querySelector('.filename');
filenameField.innerHTML = configuration;
const logSocket = new WebSocket(wsUrl + "/run");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully."});
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
stopLogsButton.innerHTML = "Close";
stopped = true;
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration, port: getUploadPort()});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
if (!stopped) {
M.toast({html: 'Terminated process.'});
}
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
});
});
const validateModalElem = document.getElementById("modal-validate");
document.querySelectorAll(".action-validate").forEach((upload) => {
upload.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(validateModalElem);
const log = validateModalElem.querySelector(".log");
log.innerHTML = "";
const stopLogsButton = validateModalElem.querySelector(".stop-logs");
let stopped = false;
stopLogsButton.innerHTML = "Stop";
modalInstance.open();
const filenameField = validateModalElem.querySelector('.filename');
filenameField.innerHTML = configuration;
const logSocket = new WebSocket(wsUrl + "/validate");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({
html: `<code class="inlinecode">${configuration}</code> is valid 👍`,
displayLength: 5000,
});
} else {
M.toast({
html: `<code class="inlinecode">${configuration}</code> is invalid 😕`,
displayLength: 5000,
});
}
stopLogsButton.innerHTML = "Close";
stopped = true;
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
if (!stopped) {
M.toast({html: 'Terminated process.'});
}
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
});
});
const compileModalElem = document.getElementById("modal-compile");
const downloadButton = compileModalElem.querySelector('.download-binary');
document.querySelectorAll(".action-compile").forEach((upload) => {
upload.addEventListener('click', (e) => {
configuration = e.target.getAttribute('data-node');
const modalInstance = M.Modal.getInstance(compileModalElem);
const log = compileModalElem.querySelector(".log");
log.innerHTML = "";
const stopLogsButton = compileModalElem.querySelector(".stop-logs");
let stopped = false;
stopLogsButton.innerHTML = "Stop";
downloadButton.classList.add('disabled');
modalInstance.open();
const filenameField = compileModalElem.querySelector('.filename');
filenameField.innerHTML = configuration;
const logSocket = new WebSocket(wsUrl + "/compile");
logSocket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
if (data.event === "line") {
const msg = data.data;
log.innerHTML += colorReplace(msg);
} else if (data.event === "exit") {
if (data.code === 0) {
M.toast({html: "Program exited successfully."});
downloadButton.classList.remove('disabled');
} else {
M.toast({html: `Program failed with code ${data.code}`});
}
stopLogsButton.innerHTML = "Close";
stopped = true;
}
});
logSocket.addEventListener('open', () => {
const msg = JSON.stringify({configuration: configuration});
logSocket.send(msg);
});
logSocket.addEventListener('close', () => {
if (!stopped) {
M.toast({html: 'Terminated process.'});
}
});
modalInstance.options.onCloseStart = () => {
logSocket.close();
};
});
});
downloadButton.addEventListener('click', () => {
const link = document.createElement("a");
link.download = name;
@@ -722,7 +806,7 @@
{% if len(files) == 0 %}
<script>
document.addEventListener('DOMContentLoaded', () => {
const tapTargetElem = document.querySelector('.tap-target');
const tapTargetElem = document.querySelector('.tap-target.setup-wizard');
const tapTargetInstance = M.TapTarget.getInstance(tapTargetElem);
tapTargetInstance.options.onOpen = () => {
$('.tap-target-origin').on('click', () => {
@@ -734,5 +818,23 @@
</script>
{% end %}
{% if begin %}
<script>
window.history.replaceState({}, document.title, "/");
document.addEventListener('DOMContentLoaded', () => {
const tapTargetElem = document.querySelector('.tap-target.select-port');
const tapTargetInstance = M.TapTarget.getInstance(tapTargetElem);
tapTargetInstance.open();
tapTargetInstance.contentEl.style["top"] = "300px";
tapTargetInstance.contentEl.style["padding"] = "250px";
tapTargetInstance.waveEl.style["top"] = "250px";
tapTargetInstance.waveEl.style["left"] = "250px";
tapTargetInstance.waveEl.style["width"] = "300px";
tapTargetInstance.waveEl.style["height"] = "300px";
});
</script>
{% end %}
</body>
</html>
</html>

View File

@@ -1,5 +1,6 @@
from __future__ import print_function
import inspect
import logging
import re
from collections import OrderedDict, deque
@@ -9,8 +10,8 @@ from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOV
CONF_INVERTED, \
CONF_MODE, CONF_NUMBER, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PCF8574, \
CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC
from esphomeyaml.core import ESPHomeYAMLError, HexInt, TimePeriodMicroseconds, \
TimePeriodMilliseconds, TimePeriodSeconds, Lambda
from esphomeyaml.core import ESPHomeYAMLError, HexInt, Lambda, TimePeriodMicroseconds, \
TimePeriodMilliseconds, TimePeriodSeconds
_LOGGER = logging.getLogger(__name__)
@@ -356,87 +357,112 @@ def statement(expression):
return ExpressionStatement(expression)
def register_variable(type, id, obj):
_VARIABLES[id] = obj, type
def register_variable(id, obj):
_LOGGER.debug("Registered variable %s of type %s", id.id, id.type)
_VARIABLES[id] = obj
# pylint: disable=redefined-builtin, invalid-name
def variable(type, id, rhs):
def variable(id, rhs, type=None):
rhs = safe_exp(rhs)
obj = MockObj(id, u'.')
assignment = AssignmentExpression(type, '', id, rhs, obj)
id.type = type or id.type
assignment = AssignmentExpression(id.type, '', id, rhs, obj)
add(assignment)
register_variable(type, id, obj)
register_variable(id, obj)
obj.requires.append(assignment)
return obj
def Pvariable(type, id, rhs, has_side_effects=True):
def Pvariable(id, rhs, has_side_effects=True, type=None):
rhs = safe_exp(rhs)
if not has_side_effects and hasattr(rhs, '_has_side_effects'):
# pylint: disable=attribute-defined-outside-init, protected-access
rhs._has_side_effects = False
obj = MockObj(id, u'->', has_side_effects=has_side_effects)
assignment = AssignmentExpression(type, '*', id, rhs, obj)
id.type = type or id.type
assignment = AssignmentExpression(id.type, '*', id, rhs, obj)
add(assignment)
register_variable(type, id, obj)
register_variable(id, obj)
obj.requires.append(assignment)
return obj
_QUEUE = deque()
_TASKS = deque()
_VARIABLES = {}
_EXPRESSIONS = []
def get_variable(id, type=None):
def get_result():
if id is not None:
if id in _VARIABLES:
return _VARIABLES[id][0]
elif type is not None:
return next((x[0] for x in _VARIABLES.itervalues() if x[1] == type), None)
return None
while _QUEUE:
result = get_result()
if result is not None:
return result
func, config = _QUEUE.popleft()
func(config)
if id is None and type is None:
return None
result = get_result()
if result is None:
if type is None:
raise ESPHomeYAMLError(u"Couldn't find ID '{}'".format(id))
raise ESPHomeYAMLError(u"Couldn't find ID '{}' with type '{}'".format(id, type))
return result
def get_variable(id):
while True:
if id in _VARIABLES:
yield _VARIABLES[id]
return
_LOGGER.debug("Waiting for variable %s", id)
yield None
def process_lambda(value, parameters, capture='=', return_type=None):
if value is None:
return None
parts = re.split(r'id\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)\.', value.value)
for i in range(1, len(parts), 2):
parts[i] = get_variable(parts[i])._
return LambdaExpression(parts, parameters, capture, return_type)
yield
return
parts = value.parts[:]
for i, id in enumerate(value.requires_ids):
var = None
for var in get_variable(id):
yield
parts[i*2 + 1] = var._
yield LambdaExpression(parts, parameters, capture, return_type)
return
def templatable(value, input_type, output_type):
if isinstance(value, Lambda):
return process_lambda(value, [(input_type, 'x')], return_type=output_type)
return value
lambda_ = None
for lambda_ in process_lambda(value, [(input_type, 'x')], return_type=output_type):
yield None
yield lambda_
else:
yield value
def add_task(func, config):
_QUEUE.append((func, config))
def add_job(func, *args, **kwargs):
domain = kwargs.get('domain')
if inspect.isgeneratorfunction(func):
def func_():
yield
for _ in func(*args):
yield
else:
def func_():
yield
func(*args)
gen = func_()
_TASKS.append((gen, domain))
return gen
def flush_tasks():
i = 0
while _TASKS:
i += 1
if i > 1000000:
raise ESPHomeYAMLError("Circular dependency detected!")
task, domain = _TASKS.popleft()
_LOGGER.debug("Executing task for domain=%s", domain)
try:
task.next()
_TASKS.append((task, domain))
except StopIteration:
_LOGGER.debug(" -> %s finished", domain)
def add(expression, require=True):
if require and isinstance(expression, Expression):
expression.require()
_EXPRESSIONS.append(expression)
_LOGGER.debug("Adding: %s", statement(expression))
return expression
@@ -457,7 +483,7 @@ class MockObj(Expression):
obj.requires.append(self)
return obj
next_op = u'.'
if attr.startswith(u'P') and self.op != '::':
if attr.startswith(u'P') and self.op not in ['::', '']:
attr = attr[1:]
next_op = u'->'
if attr.startswith(u'_'):
@@ -528,32 +554,43 @@ def get_gpio_pin_number(conf):
def generic_gpio_pin_expression_(conf, mock_obj, default_mode):
if conf is None:
return None
return
number = conf[CONF_NUMBER]
inverted = conf.get(CONF_INVERTED)
if CONF_PCF8574 in conf:
hub = get_variable(conf[CONF_PCF8574], 'io::PCF8574Component')
hub = None
for hub in get_variable(conf[CONF_PCF8574]):
yield None
if default_mode == u'INPUT':
mode = conf.get(CONF_MODE, u'INPUT')
return hub.make_input_pin(number,
RawExpression('PCF8574_' + mode),
inverted)
yield hub.make_input_pin(number,
RawExpression('PCF8574_' + mode),
inverted)
return
elif default_mode == u'OUTPUT':
return hub.make_output_pin(number, inverted)
yield hub.make_output_pin(number, inverted)
return
else:
raise ESPHomeYAMLError(u"Unknown default mode {}".format(default_mode))
if len(conf) == 1:
return IntLiteral(number)
yield IntLiteral(number)
return
mode = RawExpression(conf.get(CONF_MODE, default_mode))
return mock_obj(number, mode, inverted)
yield mock_obj(number, mode, inverted)
def gpio_output_pin_expression(conf):
return generic_gpio_pin_expression_(conf, GPIOOutputPin, 'OUTPUT')
exp = None
for exp in generic_gpio_pin_expression_(conf, GPIOOutputPin, 'OUTPUT'):
yield None
yield exp
def gpio_input_pin_expression(conf):
return generic_gpio_pin_expression_(conf, GPIOInputPin, 'INPUT')
exp = None
for exp in generic_gpio_pin_expression_(conf, GPIOInputPin, 'INPUT'):
yield None
yield exp
def setup_mqtt_component(obj, config):
@@ -567,8 +604,11 @@ def setup_mqtt_component(obj, config):
add(obj.set_custom_command_topic(config[CONF_COMMAND_TOPIC]))
if CONF_AVAILABILITY in config:
availability = config[CONF_AVAILABILITY]
add(obj.set_availability(availability[CONF_TOPIC], availability[CONF_PAYLOAD_AVAILABLE],
availability[CONF_PAYLOAD_NOT_AVAILABLE]))
if not availability:
add(obj.disable_availability())
else:
add(obj.set_availability(availability[CONF_TOPIC], availability[CONF_PAYLOAD_AVAILABLE],
availability[CONF_PAYLOAD_NOT_AVAILABLE]))
# shlex's quote for Python 2.7

View File

@@ -10,7 +10,7 @@ from esphomeyaml import core
from esphomeyaml.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOMEYAML, \
CONF_LOG_TOPIC, \
CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_TOPIC_PREFIX, \
CONF_USERNAME
CONF_USERNAME, CONF_TOPIC
from esphomeyaml.helpers import color
_LOGGER = logging.getLogger(__name__)
@@ -45,7 +45,7 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None,
elif CONF_MQTT in config:
conf = config[CONF_MQTT]
if CONF_LOG_TOPIC in conf:
topic = config[CONF_MQTT][CONF_LOG_TOPIC]
topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC]
elif CONF_TOPIC_PREFIX in config[CONF_MQTT]:
topic = config[CONF_MQTT][CONF_TOPIC_PREFIX] + u'/debug'
else:
@@ -57,10 +57,13 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None,
def on_message(client, userdata, msg):
time = datetime.now().time().strftime(u'[%H:%M:%S]')
message = msg.payload.decode('utf-8')
message = time + msg.payload
if escape:
message = message.replace('\033', '\\033')
print(time + message)
try:
print(message)
except UnicodeEncodeError:
print(message.encode('ascii', 'backslashreplace'))
return initialize(config, [topic], on_message, username, password, client_id)

View File

@@ -4,6 +4,7 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import core
from esphomeyaml.components import pcf8574
from esphomeyaml.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_PCF8574, \
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
@@ -202,20 +203,40 @@ def shorthand_input_pin(value):
PCF8574_OUTPUT_PIN_SCHEMA = vol.Schema({
vol.Required(CONF_PCF8574): cv.variable_id,
vol.Required(CONF_PCF8574): cv.use_variable_id(pcf8574.PCF8574Component),
vol.Required(CONF_NUMBER): vol.Coerce(int),
vol.Optional(CONF_MODE): vol.All(vol.Upper, "OUTPUT"),
vol.Optional(CONF_MODE): vol.All(vol.Upper, cv.one_of("OUTPUT")),
vol.Optional(CONF_INVERTED, default=False): cv.boolean,
})
PCF8574_INPUT_PIN_SCHEMA = PCF8574_OUTPUT_PIN_SCHEMA.extend({
vol.Optional(CONF_MODE): vol.All(vol.Upper, vol.Any("INPUT", "INPUT_PULLUP")),
vol.Optional(CONF_MODE): vol.All(vol.Upper, cv.one_of("INPUT", "INPUT_PULLUP")),
})
GPIO_INTERNAL_OUTPUT_PIN_SCHEMA = vol.Any(shorthand_output_pin, GPIO_FULL_OUTPUT_PIN_SCHEMA)
GPIO_OUTPUT_PIN_SCHEMA = vol.Any(PCF8574_OUTPUT_PIN_SCHEMA, GPIO_INTERNAL_OUTPUT_PIN_SCHEMA)
def internal_gpio_output_pin_schema(value):
if isinstance(value, dict):
return GPIO_FULL_OUTPUT_PIN_SCHEMA(value)
return shorthand_output_pin(value)
GPIO_INTERNAL_INPUT_PIN_SCHEMA = vol.Any(shorthand_input_pin, GPIO_FULL_INPUT_PIN_SCHEMA)
GPIO_INPUT_PIN_SCHEMA = vol.Any(PCF8574_INPUT_PIN_SCHEMA, GPIO_INTERNAL_INPUT_PIN_SCHEMA)
def gpio_output_pin_schema(value):
if isinstance(value, dict):
if CONF_PCF8574 in value:
return PCF8574_OUTPUT_PIN_SCHEMA(value)
return GPIO_FULL_OUTPUT_PIN_SCHEMA(value)
return shorthand_output_pin(value)
def internal_gpio_input_pin_schema(value):
if isinstance(value, dict):
return GPIO_FULL_INPUT_PIN_SCHEMA(value)
return shorthand_input_pin(value)
def gpio_input_pin_schema(value):
if isinstance(value, dict):
if CONF_PCF8574 in value:
return PCF8574_INPUT_PIN_SCHEMA(value)
return GPIO_FULL_INPUT_PIN_SCHEMA(value)
return shorthand_input_pin(value)

View File

@@ -0,0 +1,12 @@
; This file allows the docker build file to install the required platformio
; platforms
[env:espressif8266]
platform = espressif8266
board = nodemcuv2
framework = arduino
[env:espressif32]
platform = espressif32
board = nodemcu-32s
framework = arduino

View File

@@ -306,5 +306,5 @@ def wizard(path):
print(color('bold_white', " discovery: True"))
print()
print(" > Then follow the rest of the getting started guide:")
print(" > https://esphomelib.com/esphomeyaml/getting-started.html")
print(" > https://esphomelib.com/esphomeyaml/guides/getting_started_command_line.html")
return 0

View File

@@ -8,6 +8,7 @@ from collections import OrderedDict
import yaml
from esphomeyaml import core
from esphomeyaml.core import ESPHomeYAMLError, HexInt, IPAddress, Lambda, MACAddress, TimePeriod
_LOGGER = logging.getLogger(__name__)
@@ -47,8 +48,9 @@ def load_yaml(fname):
with codecs.open(fname, encoding='utf-8') as conf_file:
return yaml.load(conf_file, Loader=SafeLineLoader) or OrderedDict()
except yaml.YAMLError as exc:
_LOGGER.error(exc)
raise ESPHomeYAMLError(exc)
except IOError as exc:
raise ESPHomeYAMLError(u"Error accessing file {}: {}".format(fname, exc))
except UnicodeDecodeError as exc:
_LOGGER.error(u"Unable to read file %s: %s", fname, exc)
raise ESPHomeYAMLError(exc)
@@ -279,6 +281,10 @@ def represent_lambda(_, data):
return node
def represent_id(_, data):
return yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=data.id)
yaml.SafeDumper.add_representer(
OrderedDict,
lambda dumper, value:
@@ -297,3 +303,4 @@ yaml.SafeDumper.add_representer(IPAddress, stringify_representer)
yaml.SafeDumper.add_representer(MACAddress, stringify_representer)
yaml.SafeDumper.add_multi_representer(TimePeriod, represent_time_period)
yaml.SafeDumper.add_multi_representer(Lambda, represent_lambda)
yaml.SafeDumper.add_multi_representer(core.ID, represent_id)

91
examples/sonoff_4ch.yaml Normal file
View File

@@ -0,0 +1,91 @@
esphomeyaml:
name: <NAME_OF_NODE>
platform: ESP8266
board: esp01_1m
board_flash_mode: dout
wifi:
ssid: <YOUR_SSID>
password: <YOUR_PASSWORD>
mqtt:
broker: <YOUR_MQTT_BROKER>
username: <YOUR_USERNAME>
password: <YOUR_PASSWORD>
logger:
ota:
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: "Sonoff 4CH Button 1"
on_press:
then:
switch.toggle:
id: relay_1
- platform: gpio
pin:
number: GPIO9
mode: INPUT_PULLUP
inverted: True
name: "Sonoff 4CH Button 2"
on_press:
then:
switch.toggle:
id: relay_2
- platform: gpio
pin:
number: GPIO10
mode: INPUT_PULLUP
inverted: True
name: "Sonoff 4CH Button 3"
on_press:
then:
switch.toggle:
id: relay_3
- platform: gpio
pin:
number: GPIO14
mode: INPUT_PULLUP
inverted: True
name: "Sonoff 4CH Button 4"
on_press:
then:
switch.toggle:
id: relay_4
- platform: status
name: "Sonoff 4CH Status"
switch:
- platform: gpio
name: "Sonoff 4CH Relay 1"
pin: GPIO12
id: relay_1
- platform: gpio
name: "Sonoff 4CH Relay 2"
pin: GPIO5
id: relay_2
- platform: gpio
name: "Sonoff 4CH Relay 3"
pin: GPIO4
id: relay_3
- platform: gpio
name: "Sonoff 4CH Relay 4"
pin: GPIO15
id: relay_4
output:
- platform: esp8266_pwm
id: blue_led
pin: GPIO13
inverted: True
light:
- platform: monochromatic
name: "Sonoff 4CH Blue LED"
output: blue_led

50
examples/sonoff_s20.yaml Normal file
View File

@@ -0,0 +1,50 @@
esphomeyaml:
name: <NAME_OF_NODE>
platform: ESP8266
board: esp01_1m
board_flash_mode: dout
wifi:
ssid: <YOUR_SSID>
password: <YOUR_PASSWORD>
mqtt:
broker: <YOUR_MQTT_BROKER>
username: <YOUR_USERNAME>
password: <YOUR_PASSWORD>
logger:
ota:
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: "Sonoff S20 Button"
on_press:
then:
- switch.toggle:
id: relay
- platform: status
name: "Sonoff S20 Status"
switch:
- platform: gpio
name: "Sonoff S20 Relay"
pin: GPIO12
id: relay
output:
- platform: esp8266_pwm
id: s20_green_led
pin: GPIO13
inverted: True
light:
- platform: monochromatic
name: "Sonoff S20 Green LED"
output: s20_green_led

View File

@@ -16,6 +16,7 @@ disable=
duplicate-code,
invalid-name,
cyclic-import,
redefined-builtin,
additional-builtins=

View File

@@ -3,3 +3,5 @@ platformio==3.5.2
pyyaml==3.12
paho-mqtt==1.3.1
colorlog==3.1.2
tornado==5.0.2
esptool==2.3.1

View File

@@ -27,6 +27,8 @@ REQUIRES = [
'pyyaml>=3.12',
'paho-mqtt>=1.3.1',
'colorlog>=3.1.2',
'tornado>=5.0.0',
'esptool>=2.3.1',
]
CLASSIFIERS = [