Merge pull request #1 from esphome/dev

update dev branch
This commit is contained in:
Michiel van Turnhout 2019-04-29 19:40:25 +02:00 committed by GitHub
commit 0c7d341a15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
399 changed files with 6073 additions and 5061 deletions

View file

@ -4,11 +4,10 @@
**Related issue (if applicable):** fixes <link to issue> **Related issue (if applicable):** fixes <link to issue>
**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here>
**Pull request in [esphome-core](https://github.com/esphome/esphome-core) with C++ framework changes (if applicable):** esphome/esphome-core#<esphome-core PR number goes here>
## Checklist: ## Checklist:
- [ ] The code change is tested and works locally. - [ ] The code change is tested and works locally.
- [ ] Tests have been added to verify that the new code works (under `tests/` folder). - [ ] Tests have been added to verify that the new code works (under `tests/` folder).
If user exposed functionality or configuration variables are added/changed: If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs). - [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs).

View file

@ -41,11 +41,11 @@ stages:
- | - |
if [[ "${IS_HASSIO}" == "YES" ]]; then if [[ "${IS_HASSIO}" == "YES" ]]; then
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3 BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.5.1
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH} BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
DOCKERFILE=docker/Dockerfile.hassio DOCKERFILE=docker/Dockerfile.hassio
else else
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3 BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.5.1
if [[ "${BUILD_ARCH}" == "amd64" ]]; then if [[ "${BUILD_ARCH}" == "amd64" ]]; then
BUILD_TO=esphome/esphome BUILD_TO=esphome/esphome
else else

View file

@ -1,9 +1,8 @@
ARG BUILD_FROM=esphome/esphome-base-amd64:1.4.3 ARG BUILD_FROM=esphome/esphome-base-amd64:1.5.1
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
COPY . . COPY . .
RUN \ RUN pip2 install --no-cache-dir -e .
pip2 install --no-cache-dir --no-binary :all: -e .
WORKDIR /config WORKDIR /config
ENTRYPOINT ["esphome"] ENTRYPOINT ["esphome"]

View file

@ -1,4 +1,4 @@
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.4.3 ARG BUILD_FROM
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
# Copy root filesystem # Copy root filesystem
@ -6,8 +6,7 @@ COPY docker/rootfs/ /
COPY setup.py setup.cfg MANIFEST.in /opt/esphome/ COPY setup.py setup.cfg MANIFEST.in /opt/esphome/
COPY esphome /opt/esphome/esphome COPY esphome /opt/esphome/esphome
RUN \ RUN pip2 install --no-cache-dir -e /opt/esphome
pip2 install --no-cache-dir --no-binary :all: -e /opt/esphome
# Build arguments # Build arguments
ARG BUILD_VERSION=dev ARG BUILD_VERSION=dev

View file

@ -7,7 +7,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python-pil \ python-pil \
git \ git \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
pip install --no-cache-dir --no-binary :all: platformio && \ pip install --no-cache-dir platformio && \
platformio settings set enable_telemetry No && \ platformio settings set enable_telemetry No && \
platformio settings set check_libraries_interval 1000000 && \ platformio settings set check_libraries_interval 1000000 && \
platformio settings set check_platformio_interval 1000000 && \ platformio settings set check_platformio_interval 1000000 && \

View file

@ -1,26 +0,0 @@
#!/usr/bin/env bash
# the Docker repository tag being built.
declare CACHE_TAG
echo "CACHE_TAG: ${CACHE_TAG}"
# the name and tag of the Docker repository being built. (This variable is a combination of DOCKER_REPO:CACHE_TAG.)
declare IMAGE_NAME
echo "IMAGE_NAME: ${IMAGE_NAME}"
# the architecture to build
declare BUILD_ARCH
echo "BUILD_ARCH: ${BUILD_ARCH}"
# whether this is a hassio build
declare IS_HASSIO
echo "IS_HASSIO: ${IS_HASSIO}"
echo "PWD: $PWD"
if [[ ${IS_HASSIO} = "YES" ]]; then
docker build \
--build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3" \
--build-arg "BUILD_VERSION=${CACHE_TAG}" \
-t "${IMAGE_NAME}" -f ../docker/Dockerfile.hassio ..
else
docker build \
--build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3" \
-t "${IMAGE_NAME}" -f ../docker/Dockerfile ..
fi

View file

@ -1,18 +0,0 @@
#!/usr/bin/env bash
# the architecture to build
declare BUILD_ARCH
echo "BUILD_ARCH: ${BUILD_ARCH}"
if [[ ${BUILD_ARCH} = "amd64" ]]; then
echo "No qemu required..."
exit 0
fi
if [[ ${BUILD_ARCH} = "i386" ]]; then
echo "No qemu required..."
exit 0
fi
echo "Installing qemu..."
docker run --rm --privileged multiarch/qemu-user-static:register --reset

View file

@ -6,21 +6,29 @@
declare certfile declare certfile
declare keyfile declare keyfile
declare port declare direct_port
declare ingress_interface
declare ingress_port
mkdir -p /var/log/nginx mkdir -p /var/log/nginx
# Enable SSL direct_port=$(bashio::addon.port 6052)
if bashio::var.has_value "${direct_port}"; then
if bashio::config.true 'ssl'; then if bashio::config.true 'ssl'; then
rm /etc/nginx/nginx.conf
mv /etc/nginx/nginx-ssl.conf /etc/nginx/nginx.conf
certfile=$(bashio::config 'certfile') certfile=$(bashio::config 'certfile')
keyfile=$(bashio::config 'keyfile') keyfile=$(bashio::config 'keyfile')
sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/nginx.conf mv /etc/nginx/servers/direct-ssl.disabled /etc/nginx/servers/direct.conf
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/nginx.conf sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/servers/direct.conf
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/servers/direct.conf
else
mv /etc/nginx/servers/direct.disabled /etc/nginx/servers/direct.conf
fi fi
port=$(bashio::config 'port') sed -i "s/%%port%%/${direct_port}/g" /etc/nginx/servers/direct.conf
sed -i "s/%%port%%/${port}/g" /etc/nginx/nginx.conf fi
ingress_port=$(bashio::addon.ingress_port)
ingress_interface=$(bashio::addon.ip_address)
sed -i "s/%%port%%/${ingress_port}/g" /etc/nginx/servers/ingress.conf
sed -i "s/%%interface%%/${ingress_interface}/g" /etc/nginx/servers/ingress.conf

View file

@ -10,6 +10,6 @@ if bashio::config.has_value 'esphome_version'; then
esphome_version=$(bashio::config 'esphome_version') esphome_version=$(bashio::config 'esphome_version')
full_url="https://github.com/esphome/esphome/archive/${esphome_version}.zip" full_url="https://github.com/esphome/esphome/archive/${esphome_version}.zip"
bashio::log.info "Installing esphome version '${esphome_version}' (${full_url})..." bashio::log.info "Installing esphome version '${esphome_version}' (${full_url})..."
pip2 install --no-cache-dir --no-binary :all: "${full_url}" \ pip2 install -U --no-cache-dir "${full_url}" \
|| bashio::exit.nok "Failed installing esphome pinned version." || bashio::exit.nok "Failed installing esphome pinned version."
fi fi

View file

@ -0,0 +1,96 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}

View file

@ -0,0 +1,16 @@
proxy_http_version 1.1;
proxy_ignore_client_abort off;
proxy_read_timeout 86400s;
proxy_redirect off;
proxy_send_timeout 86400s;
proxy_max_temp_file_size 0;
proxy_set_header Accept-Encoding "";
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "";

View file

@ -0,0 +1,6 @@
root /dev/null;
server_name $hostname;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;

View file

@ -0,0 +1,9 @@
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

View file

@ -1,62 +0,0 @@
worker_processes 1;
pid /var/run/nginx.pid;
error_log stderr;
events {
worker_connections 1024;
}
http {
access_log stdout;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream esphome {
ip_hash;
server unix:/var/run/esphome.sock;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name hassio.local;
listen %%port%% default_server ssl;
root /dev/null;
ssl_certificate /ssl/%%certfile%%;
ssl_certificate_key /ssl/%%keyfile%%;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# Redirect http requests to https on the same port.
# https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
error_page 497 https://$http_host$request_uri;
location / {
proxy_redirect off;
proxy_pass http://esphome;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Authorization "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
}
}

View file

@ -1,46 +1,33 @@
worker_processes 1; daemon off;
user root;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
error_log stderr; worker_processes 1;
# Hass.io addon log
error_log /proc/1/fd/1 error;
events { events {
worker_connections 1024; worker_connections 1024;
} }
http { http {
include /etc/nginx/includes/mime.types;
access_log stdout; access_log stdout;
include mime.types;
default_type application/octet-stream; default_type application/octet-stream;
sendfile on; gzip on;
keepalive_timeout 65; keepalive_timeout 65;
sendfile on;
server_tokens off;
upstream esphome {
ip_hash;
server unix:/var/run/esphome.sock;
}
map $http_upgrade $connection_upgrade { map $http_upgrade $connection_upgrade {
default upgrade; default upgrade;
'' close; '' close;
} }
server { # Use Hass.io supervisor as resolver
server_name hassio.local; resolver 172.30.32.2;
listen %%port%% default_server;
root /dev/null;
location / { upstream esphome {
proxy_redirect off; server unix:/var/run/esphome.sock;
proxy_pass http://esphome; }
proxy_http_version 1.1; include /etc/nginx/servers/*.conf;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Authorization "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
}
} }

View file

@ -0,0 +1,17 @@
server {
listen %%port%% default_server ssl http2;
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
include /etc/nginx/includes/ssl_params.conf;
# Clear Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "";
# Redirect http requests to https on the same port.
# https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
error_page 497 https://$http_host$request_uri;
location / {
proxy_pass http://esphome;
}
}

View file

@ -0,0 +1,12 @@
server {
listen %%port%% default_server;
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
# Clear Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "";
location / {
proxy_pass http://esphome;
}
}

View file

@ -0,0 +1,16 @@
server {
listen %%interface%%:%%port%% default_server;
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
# Set Hass.io Ingress header
proxy_set_header X-Hassio-Ingress "YES";
location / {
# Only allow from Hass.io supervisor
allow 172.30.32.2;
deny all;
proxy_pass http://esphome;
}
}

View file

@ -4,5 +4,11 @@
# Runs the NGINX proxy # Runs the NGINX proxy
# ============================================================================== # ==============================================================================
bashio::log.info "Waiting for dashboard to come up..."
while [[ ! -S /var/run/esphome.sock ]]; do
sleep 0.5
done
bashio::log.info "Starting NGINX..." bashio::log.info "Starting NGINX..."
exec nginx -g "daemon off;" exec nginx

View file

@ -195,8 +195,13 @@ def clean_mqtt(config, args):
return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id) return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id)
def setup_log(debug=False): def setup_log(debug=False, quiet=False):
log_level = logging.DEBUG if debug else logging.INFO if debug:
log_level = logging.DEBUG
elif quiet:
log_level = logging.CRITICAL
else:
log_level = logging.INFO
logging.basicConfig(level=log_level) logging.basicConfig(level=log_level)
fmt = "%(levelname)s %(message)s" fmt = "%(levelname)s %(message)s"
colorfmt = "%(log_color)s{}%(reset)s".format(fmt) colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
@ -236,6 +241,13 @@ def command_config(args, config):
return 0 return 0
def command_vscode(args):
from esphome import vscode
CORE.config_path = args.configuration
vscode.read_config()
def command_compile(args, config): def command_compile(args, config):
exit_code = write_cpp(config) exit_code = write_cpp(config)
if exit_code != 0: if exit_code != 0:
@ -321,7 +333,8 @@ def command_dashboard(args):
PRE_CONFIG_ACTIONS = { PRE_CONFIG_ACTIONS = {
'wizard': command_wizard, 'wizard': command_wizard,
'version': command_version, 'version': command_version,
'dashboard': command_dashboard 'dashboard': command_dashboard,
'vscode': command_vscode,
} }
POST_CONFIG_ACTIONS = { POST_CONFIG_ACTIONS = {
@ -340,8 +353,9 @@ def parse_args(argv):
parser = argparse.ArgumentParser(prog='esphome') parser = argparse.ArgumentParser(prog='esphome')
parser.add_argument('-v', '--verbose', help="Enable verbose esphome logs.", parser.add_argument('-v', '--verbose', help="Enable verbose esphome logs.",
action='store_true') action='store_true')
parser.add_argument('--dashboard', help="Internal flag to set if the command is run from the " parser.add_argument('-q', '--quiet', help="Disable all esphome logs.",
"dashboard.", action='store_true') action='store_true')
parser.add_argument('--dashboard', help=argparse.SUPPRESS, action='store_true')
parser.add_argument('configuration', help='Your YAML configuration file.') parser.add_argument('configuration', help='Your YAML configuration file.')
subparsers = parser.add_subparsers(help='Commands', dest='command') subparsers = parser.add_subparsers(help='Commands', dest='command')
@ -404,12 +418,13 @@ def parse_args(argv):
dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.", dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.",
action='store_true') action='store_true')
dashboard.add_argument("--hassio", dashboard.add_argument("--hassio",
help="Internal flag used to tell esphome is started as a Hass.io " help=argparse.SUPPRESS,
"add-on.",
action="store_true") action="store_true")
dashboard.add_argument("--socket", dashboard.add_argument("--socket",
help="Make the dashboard serve under a unix socket", type=str) help="Make the dashboard serve under a unix socket", type=str)
subparsers.add_parser('vscode', help=argparse.SUPPRESS)
return parser.parse_args(argv[1:]) return parser.parse_args(argv[1:])
@ -417,7 +432,7 @@ def run_esphome(argv):
args = parse_args(argv) args = parse_args(argv)
CORE.dashboard = args.dashboard CORE.dashboard = args.dashboard
setup_log(args.verbose) setup_log(args.verbose, args.quiet)
if args.command in PRE_CONFIG_ACTIONS: if args.command in PRE_CONFIG_ACTIONS:
try: try:
return PRE_CONFIG_ACTIONS[args.command](args) return PRE_CONFIG_ACTIONS[args.command](args)

View file

@ -1,15 +1,9 @@
import copy import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, CONF_BELOW, \ from esphome.const import CONF_AUTOMATION_ID, CONF_CONDITION, CONF_ELSE, CONF_ID, CONF_THEN, \
CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, CONF_ELSE, CONF_ID, CONF_IF, CONF_LAMBDA, \ CONF_TRIGGER_ID, CONF_TYPE_ID, CONF_TIME
CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID, CONF_WAIT_UNTIL, CONF_WHILE
from esphome.core import coroutine from esphome.core import coroutine
from esphome.cpp_generator import Pvariable, TemplateArguments, add, get_variable, \ from esphome.util import Registry
process_lambda, templatable
from esphome.cpp_types import Action, App, Component, PollingComponent, Trigger, bool_, \
esphome_ns, float_, uint32, void
from esphome.util import ServiceRegistry
def maybe_simple_id(*validators): def maybe_simple_id(*validators):
@ -18,97 +12,50 @@ def maybe_simple_id(*validators):
def validate(value): def validate(value):
if isinstance(value, dict): if isinstance(value, dict):
return validator(value) return validator(value)
with cv.remove_prepend_path([CONF_ID]):
return validator({CONF_ID: value}) return validator({CONF_ID: value})
return validate return validate
def validate_recursive_condition(value): def register_action(name, action_type, schema):
is_list = isinstance(value, list) return ACTION_REGISTRY.register(name, action_type, schema)
value = cv.ensure_list()(value)[:]
for i, item in enumerate(value):
path = [i] if is_list else []
item = copy.deepcopy(item)
if not isinstance(item, dict):
raise cv.Invalid(u"Condition must consist of key-value mapping! Got {}".format(item),
path)
key = next((x for x in item if x != CONF_CONDITION_ID), None)
if key is None:
raise cv.Invalid(u"Key missing from action! Got {}".format(item), path)
if key not in CONDITION_REGISTRY:
raise cv.Invalid(u"Unable to find condition with the name '{}', is the "
u"component loaded?".format(key), path + [key])
item.setdefault(CONF_CONDITION_ID, None)
key2 = next((x for x in item if x not in (CONF_CONDITION_ID, key)), None)
if key2 is not None:
raise cv.Invalid(u"Cannot have two conditions in one item. Key '{}' overrides '{}'! "
u"Did you forget to indent the block inside the condition?"
u"".format(key, key2), path)
validator = CONDITION_REGISTRY[key][0]
try:
condition = validator(item[key] or {})
except cv.Invalid as err:
err.prepend(path)
raise err
value[i] = {
CONF_CONDITION_ID: cv.declare_variable_id(Condition)(item[CONF_CONDITION_ID]),
key: condition,
}
return value
def validate_recursive_action(value): def register_condition(name, condition_type, schema):
is_list = isinstance(value, list) return CONDITION_REGISTRY.register(name, condition_type, schema)
if not is_list:
value = [value]
for i, item in enumerate(value):
path = [i] if is_list else []
item = copy.deepcopy(item)
if not isinstance(item, dict):
raise cv.Invalid(u"Action must consist of key-value mapping! Got {}".format(item),
path)
key = next((x for x in item if x != CONF_ACTION_ID), None)
if key is None:
raise cv.Invalid(u"Key missing from action! Got {}".format(item), path)
if key not in ACTION_REGISTRY:
raise cv.Invalid(u"Unable to find action with the name '{}', is the component loaded?"
u"".format(key), path + [key])
item.setdefault(CONF_ACTION_ID, None)
key2 = next((x for x in item if x not in (CONF_ACTION_ID, key)), None)
if key2 is not None:
raise cv.Invalid(u"Cannot have two actions in one item. Key '{}' overrides '{}'! "
u"Did you forget to indent the block inside the action?"
u"".format(key, key2), path)
validator = ACTION_REGISTRY[key][0]
try:
action = validator(item[key] or {})
except cv.Invalid as err:
err.prepend(path)
raise err
value[i] = {
CONF_ACTION_ID: cv.declare_variable_id(Action)(item[CONF_ACTION_ID]),
key: action,
}
return value
ACTION_REGISTRY = ServiceRegistry() Action = cg.esphome_ns.class_('Action')
CONDITION_REGISTRY = ServiceRegistry() Trigger = cg.esphome_ns.class_('Trigger')
ACTION_REGISTRY = Registry()
Condition = cg.esphome_ns.class_('Condition')
CONDITION_REGISTRY = Registry()
validate_action = cv.validate_registry_entry('action', ACTION_REGISTRY)
validate_action_list = cv.validate_registry('action', ACTION_REGISTRY)
validate_condition = cv.validate_registry_entry('condition', CONDITION_REGISTRY)
validate_condition_list = cv.validate_registry('condition', CONDITION_REGISTRY)
# pylint: disable=invalid-name
DelayAction = esphome_ns.class_('DelayAction', Action, Component)
LambdaAction = esphome_ns.class_('LambdaAction', Action)
IfAction = esphome_ns.class_('IfAction', Action)
WhileAction = esphome_ns.class_('WhileAction', Action)
WaitUntilAction = esphome_ns.class_('WaitUntilAction', Action, Component)
UpdateComponentAction = esphome_ns.class_('UpdateComponentAction', Action)
Automation = esphome_ns.class_('Automation')
Condition = esphome_ns.class_('Condition') def validate_potentially_and_condition(value):
AndCondition = esphome_ns.class_('AndCondition', Condition) if isinstance(value, list):
OrCondition = esphome_ns.class_('OrCondition', Condition) with cv.remove_prepend_path(['and']):
RangeCondition = esphome_ns.class_('RangeCondition', Condition) return validate_condition({
LambdaCondition = esphome_ns.class_('LambdaCondition', Condition) 'and': value
})
return validate_condition(value)
DelayAction = cg.esphome_ns.class_('DelayAction', Action, cg.Component)
LambdaAction = cg.esphome_ns.class_('LambdaAction', Action)
IfAction = cg.esphome_ns.class_('IfAction', Action)
WhileAction = cg.esphome_ns.class_('WhileAction', Action)
WaitUntilAction = cg.esphome_ns.class_('WaitUntilAction', Action, cg.Component)
UpdateComponentAction = cg.esphome_ns.class_('UpdateComponentAction', Action)
Automation = cg.esphome_ns.class_('Automation')
LambdaCondition = cg.esphome_ns.class_('LambdaCondition', Condition)
ForCondition = cg.esphome_ns.class_('ForCondition', Condition)
def validate_automation(extra_schema=None, extra_validators=None, single=False): def validate_automation(extra_schema=None, extra_validators=None, single=False):
@ -120,23 +67,27 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
def validator_(value): def validator_(value):
if isinstance(value, list): if isinstance(value, list):
# List of items, there are two possible options here, either a sequence of
# actions (no then:) or a list of automations.
try: try:
# First try as a sequence of actions # First try as a sequence of actions
# If that succeeds, return immediately
with cv.remove_prepend_path([CONF_THEN]):
return [schema({CONF_THEN: value})] return [schema({CONF_THEN: value})]
except cv.Invalid as err: except cv.Invalid as err:
if err.path and err.path[0] == CONF_THEN:
err.path.pop(0)
# Next try as a sequence of automations # Next try as a sequence of automations
try: try:
return cv.Schema([schema])(value) return cv.Schema([schema])(value)
except cv.Invalid as err2: except cv.Invalid as err2:
if 'Unable to find action' in str(err): if u'extra keys not allowed' in str(err2) and len(err2.path) == 2:
raise err
if u'Unable to find action' in str(err):
raise err2 raise err2
raise cv.MultipleInvalid([err, err2]) raise cv.MultipleInvalid([err, err2])
elif isinstance(value, dict): elif isinstance(value, dict):
if CONF_THEN in value: if CONF_THEN in value:
return [schema(value)] return [schema(value)]
with cv.remove_prepend_path([CONF_THEN]):
return [schema({CONF_THEN: value})] return [schema({CONF_THEN: value})]
# This should only happen with invalid configs, but let's have a nice error message. # This should only happen with invalid configs, but let's have a nice error message.
return [schema(value)] return [schema(value)]
@ -155,175 +106,132 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
AUTOMATION_SCHEMA = cv.Schema({ AUTOMATION_SCHEMA = cv.Schema({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger),
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation), cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_id(Automation),
cv.Required(CONF_THEN): validate_recursive_action, cv.Required(CONF_THEN): validate_action_list,
}) })
AND_CONDITION_SCHEMA = validate_recursive_condition AndCondition = cg.esphome_ns.class_('AndCondition', Condition)
OrCondition = cg.esphome_ns.class_('OrCondition', Condition)
NotCondition = cg.esphome_ns.class_('NotCondition', Condition)
@CONDITION_REGISTRY.register(CONF_AND, AND_CONDITION_SCHEMA) @register_condition('and', AndCondition, validate_condition_list)
def and_condition_to_code(config, condition_id, template_arg, args): def and_condition_to_code(config, condition_id, template_arg, args):
conditions = yield build_conditions(config, template_arg, args) conditions = yield build_condition_list(config, template_arg, args)
rhs = AndCondition.new(template_arg, conditions) yield cg.new_Pvariable(condition_id, template_arg, conditions)
type = AndCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
OR_CONDITION_SCHEMA = validate_recursive_condition @register_condition('or', OrCondition, validate_condition_list)
@CONDITION_REGISTRY.register(CONF_OR, OR_CONDITION_SCHEMA)
def or_condition_to_code(config, condition_id, template_arg, args): def or_condition_to_code(config, condition_id, template_arg, args):
conditions = yield build_conditions(config, template_arg, args) conditions = yield build_condition_list(config, template_arg, args)
rhs = OrCondition.new(template_arg, conditions) yield cg.new_Pvariable(condition_id, template_arg, conditions)
type = OrCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
RANGE_CONDITION_SCHEMA = cv.All(cv.Schema({ @register_condition('not', NotCondition, validate_condition)
cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), def not_condition_to_code(config, condition_id, template_arg, args):
cv.Optional(CONF_BELOW): cv.templatable(cv.float_), condition = yield build_condition(config, template_arg, args)
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)) yield cg.new_Pvariable(condition_id, template_arg, condition)
@CONDITION_REGISTRY.register(CONF_RANGE, RANGE_CONDITION_SCHEMA) @register_condition('lambda', LambdaCondition, cv.lambda_)
def range_condition_to_code(config, condition_id, template_arg, args): def lambda_condition_to_code(config, condition_id, template_arg, args):
conditions = yield build_conditions(config, template_arg, args) lambda_ = yield cg.process_lambda(config, args, return_type=bool)
rhs = RangeCondition.new(template_arg, conditions) yield cg.new_Pvariable(condition_id, template_arg, lambda_)
type = RangeCondition.template(template_arg)
condition = Pvariable(condition_id, rhs, type=type)
if CONF_ABOVE in config:
template_ = yield templatable(config[CONF_ABOVE], args, float_)
condition.set_min(template_)
if CONF_BELOW in config:
template_ = yield templatable(config[CONF_BELOW], args, float_)
condition.set_max(template_)
yield condition
DELAY_ACTION_SCHEMA = cv.templatable(cv.positive_time_period_milliseconds) @register_condition('for', ForCondition, cv.Schema({
cv.Required(CONF_TIME): cv.templatable(cv.positive_time_period_milliseconds),
cv.Required(CONF_CONDITION): validate_potentially_and_condition,
}).extend(cv.COMPONENT_SCHEMA))
def for_condition_to_code(config, condition_id, template_arg, args):
condition = yield build_condition(config[CONF_CONDITION], cg.TemplateArguments(), [])
var = cg.new_Pvariable(condition_id, template_arg, condition)
yield cg.register_component(var, config)
templ = yield cg.templatable(config[CONF_TIME], args, cg.uint32)
cg.add(var.set_time(templ))
yield var
@ACTION_REGISTRY.register(CONF_DELAY, DELAY_ACTION_SCHEMA) @register_action('delay', DelayAction, cv.templatable(cv.positive_time_period_milliseconds))
def delay_action_to_code(config, action_id, template_arg, args): def delay_action_to_code(config, action_id, template_arg, args):
rhs = App.register_component(DelayAction.new(template_arg)) var = cg.new_Pvariable(action_id, template_arg)
type = DelayAction.template(template_arg) yield cg.register_component(var, {})
action = Pvariable(action_id, rhs, type=type) template_ = yield cg.templatable(config, args, cg.uint32)
template_ = yield templatable(config, args, uint32) cg.add(var.set_delay(template_))
add(action.set_delay(template_)) yield var
yield action
IF_ACTION_SCHEMA = cv.All({ @register_action('if', IfAction, cv.All({
cv.Required(CONF_CONDITION): validate_recursive_condition, cv.Required(CONF_CONDITION): validate_potentially_and_condition,
cv.Optional(CONF_THEN): validate_recursive_action, cv.Optional(CONF_THEN): validate_action_list,
cv.Optional(CONF_ELSE): validate_recursive_action, cv.Optional(CONF_ELSE): validate_action_list,
}, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE)) }, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE)))
@ACTION_REGISTRY.register(CONF_IF, IF_ACTION_SCHEMA)
def if_action_to_code(config, action_id, template_arg, args): def if_action_to_code(config, action_id, template_arg, args):
conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) conditions = yield build_condition(config[CONF_CONDITION], template_arg, args)
rhs = IfAction.new(template_arg, conditions) var = cg.new_Pvariable(action_id, template_arg, conditions)
type = IfAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_THEN in config: if CONF_THEN in config:
actions = yield build_actions(config[CONF_THEN], template_arg, args) actions = yield build_action_list(config[CONF_THEN], template_arg, args)
add(action.add_then(actions)) cg.add(var.add_then(actions))
if CONF_ELSE in config: if CONF_ELSE in config:
actions = yield build_actions(config[CONF_ELSE], template_arg, args) actions = yield build_action_list(config[CONF_ELSE], template_arg, args)
add(action.add_else(actions)) cg.add(var.add_else(actions))
yield action yield var
WHILE_ACTION_SCHEMA = cv.Schema({ @register_action('while', WhileAction, cv.Schema({
cv.Required(CONF_CONDITION): validate_recursive_condition, cv.Required(CONF_CONDITION): validate_potentially_and_condition,
cv.Required(CONF_THEN): validate_recursive_action, cv.Required(CONF_THEN): validate_action_list,
}) }))
@ACTION_REGISTRY.register(CONF_WHILE, WHILE_ACTION_SCHEMA)
def while_action_to_code(config, action_id, template_arg, args): def while_action_to_code(config, action_id, template_arg, args):
conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) conditions = yield build_condition(config[CONF_CONDITION], template_arg, args)
rhs = WhileAction.new(template_arg, conditions) var = cg.new_Pvariable(action_id, template_arg, conditions)
type = WhileAction.template(template_arg) actions = yield build_action_list(config[CONF_THEN], template_arg, args)
action = Pvariable(action_id, rhs, type=type) cg.add(var.add_then(actions))
actions = yield build_actions(config[CONF_THEN], template_arg, args) yield var
add(action.add_then(actions))
yield action
def validate_wait_until(value): def validate_wait_until(value):
schema = cv.Schema({ schema = cv.Schema({
cv.Required(CONF_CONDITION): validate_recursive_condition cv.Required(CONF_CONDITION): validate_potentially_and_condition,
}) })
if isinstance(value, dict) and CONF_CONDITION in value: if isinstance(value, dict) and CONF_CONDITION in value:
return schema(value) return schema(value)
return validate_wait_until({CONF_CONDITION: value}) return validate_wait_until({CONF_CONDITION: value})
WAIT_UNTIL_ACTION_SCHEMA = validate_wait_until @register_action('wait_until', WaitUntilAction, validate_wait_until)
@ACTION_REGISTRY.register(CONF_WAIT_UNTIL, WAIT_UNTIL_ACTION_SCHEMA)
def wait_until_action_to_code(config, action_id, template_arg, args): def wait_until_action_to_code(config, action_id, template_arg, args):
conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) conditions = yield build_condition(config[CONF_CONDITION], template_arg, args)
rhs = WaitUntilAction.new(template_arg, conditions) var = cg.new_Pvariable(action_id, template_arg, conditions)
type = WaitUntilAction.template(template_arg) yield cg.register_component(var, {})
action = Pvariable(action_id, rhs, type=type) yield var
add(App.register_component(action))
yield action
LAMBDA_ACTION_SCHEMA = cv.lambda_ @register_action('lambda', LambdaAction, cv.lambda_)
@ACTION_REGISTRY.register(CONF_LAMBDA, LAMBDA_ACTION_SCHEMA)
def lambda_action_to_code(config, action_id, template_arg, args): def lambda_action_to_code(config, action_id, template_arg, args):
lambda_ = yield process_lambda(config, args, return_type=void) lambda_ = yield cg.process_lambda(config, args, return_type=cg.void)
rhs = LambdaAction.new(template_arg, lambda_) yield cg.new_Pvariable(action_id, template_arg, lambda_)
type = LambdaAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
LAMBDA_CONDITION_SCHEMA = cv.lambda_ @register_action('component.update', UpdateComponentAction, maybe_simple_id({
cv.Required(CONF_ID): cv.use_id(cg.PollingComponent),
}))
@CONDITION_REGISTRY.register(CONF_LAMBDA, LAMBDA_CONDITION_SCHEMA)
def lambda_condition_to_code(config, condition_id, template_arg, args):
lambda_ = yield process_lambda(config, args, return_type=bool_)
rhs = LambdaCondition.new(template_arg, lambda_)
type = LambdaCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
CONF_COMPONENT_UPDATE = 'component.update'
COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({
cv.Required(CONF_ID): cv.use_variable_id(PollingComponent),
})
@ACTION_REGISTRY.register(CONF_COMPONENT_UPDATE, COMPONENT_UPDATE_ACTION_SCHEMA)
def component_update_action_to_code(config, action_id, template_arg, args): def component_update_action_to_code(config, action_id, template_arg, args):
var = yield get_variable(config[CONF_ID]) comp = yield cg.get_variable(config[CONF_ID])
rhs = UpdateComponentAction.new(template_arg, var) yield cg.new_Pvariable(action_id, template_arg, comp)
type = UpdateComponentAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@coroutine @coroutine
def build_action(full_config, template_arg, args): def build_action(full_config, template_arg, args):
action_id = full_config[CONF_ACTION_ID] registry_entry, config = cg.extract_registry_entry_config(ACTION_REGISTRY, full_config)
key, config = next((k, v) for k, v in full_config.items() if k in ACTION_REGISTRY) action_id = full_config[CONF_TYPE_ID]
builder = registry_entry.coroutine_fun
builder = coroutine(ACTION_REGISTRY[key][1])
yield builder(config, action_id, template_arg, args) yield builder(config, action_id, template_arg, args)
@coroutine @coroutine
def build_actions(config, templ, arg_type): def build_action_list(config, templ, arg_type):
actions = [] actions = []
for conf in config: for conf in config:
action = yield build_action(conf, templ, arg_type) action = yield build_action(conf, templ, arg_type)
@ -333,15 +241,14 @@ def build_actions(config, templ, arg_type):
@coroutine @coroutine
def build_condition(full_config, template_arg, args): def build_condition(full_config, template_arg, args):
action_id = full_config[CONF_CONDITION_ID] registry_entry, config = cg.extract_registry_entry_config(CONDITION_REGISTRY, full_config)
key, config = next((k, v) for k, v in full_config.items() if k in CONDITION_REGISTRY) action_id = full_config[CONF_TYPE_ID]
builder = registry_entry.coroutine_fun
builder = coroutine(CONDITION_REGISTRY[key][1])
yield builder(config, action_id, template_arg, args) yield builder(config, action_id, template_arg, args)
@coroutine @coroutine
def build_conditions(config, templ, args): def build_condition_list(config, templ, args):
conditions = [] conditions = []
for conf in config: for conf in config:
condition = yield build_condition(conf, templ, args) condition = yield build_condition(conf, templ, args)
@ -352,10 +259,8 @@ def build_conditions(config, templ, args):
@coroutine @coroutine
def build_automation(trigger, args, config): def build_automation(trigger, args, config):
arg_types = [arg[0] for arg in args] arg_types = [arg[0] for arg in args]
templ = TemplateArguments(*arg_types) templ = cg.TemplateArguments(*arg_types)
type = Automation.template(templ) obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, trigger)
rhs = type.new(trigger) actions = yield build_action_list(config[CONF_THEN], templ, args)
obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type) cg.add(obj.add_actions(actions))
actions = yield build_actions(config[CONF_THEN], templ, args)
add(obj.add_actions(actions))
yield obj yield obj

View file

@ -13,14 +13,14 @@ from esphome.cpp_generator import ( # noqa
StructInitializer, ArrayInitializer, safe_exp, Statement, StructInitializer, ArrayInitializer, safe_exp, Statement,
progmem_array, statement, variable, Pvariable, new_Pvariable, progmem_array, statement, variable, Pvariable, new_Pvariable,
add, add_global, add_library, add_build_flag, add_define, add, add_global, add_library, add_build_flag, add_define,
get_variable, process_lambda, is_template, templatable, MockObj, get_variable, get_variable_with_full_id, process_lambda, is_template, templatable, MockObj,
MockObjClass) MockObjClass)
from esphome.cpp_helpers import ( # noqa from esphome.cpp_helpers import ( # noqa
gpio_pin_expression, register_component, build_registry_entry, gpio_pin_expression, register_component, build_registry_entry,
build_registry_list) build_registry_list, extract_registry_entry_config)
from esphome.cpp_types import ( # noqa from esphome.cpp_types import ( # noqa
global_ns, void, nullptr, float_, bool_, std_ns, std_string, global_ns, void, nullptr, float_, bool_, std_ns, std_string,
std_vector, uint8, uint16, uint32, int32, const_char_ptr, NAN, std_vector, uint8, uint16, uint32, int32, const_char_ptr, NAN,
esphome_ns, App, Nameable, Trigger, Action, Component, ComponentPtr, esphome_ns, App, Nameable, Component, ComponentPtr,
PollingComponent, Application, optional, arduino_json_ns, JsonObject, PollingComponent, Application, optional, arduino_json_ns, JsonObject,
JsonObjectRef, JsonObjectConstRef, Controller, GPIOPin) JsonObjectRef, JsonObjectConstRef, Controller, GPIOPin)

View file

@ -9,7 +9,8 @@ namespace a4988 {
class A4988 : public stepper::Stepper, public Component { class A4988 : public stepper::Stepper, public Component {
public: public:
A4988(GPIOPin *step_pin, GPIOPin *dir_pin) : step_pin_(step_pin), dir_pin_(dir_pin) {} void set_step_pin(GPIOPin *step_pin) { step_pin_ = step_pin; }
void set_dir_pin(GPIOPin *dir_pin) { dir_pin_ = dir_pin; }
void set_sleep_pin(GPIOPin *sleep_pin) { this->sleep_pin_ = sleep_pin; } void set_sleep_pin(GPIOPin *sleep_pin) { this->sleep_pin_ = sleep_pin; }
void setup() override; void setup() override;
void dump_config() override; void dump_config() override;

View file

@ -9,7 +9,7 @@ a4988_ns = cg.esphome_ns.namespace('a4988')
A4988 = a4988_ns.class_('A4988', stepper.Stepper, cg.Component) A4988 = a4988_ns.class_('A4988', stepper.Stepper, cg.Component)
CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({ CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({
cv.Required(CONF_ID): cv.declare_variable_id(A4988), cv.Required(CONF_ID): cv.declare_id(A4988),
cv.Required(CONF_STEP_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_STEP_PIN): pins.gpio_output_pin_schema,
cv.Required(CONF_DIR_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_DIR_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_SLEEP_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_SLEEP_PIN): pins.gpio_output_pin_schema,
@ -17,12 +17,15 @@ CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({
def to_code(config): def to_code(config):
step_pin = yield cg.gpio_pin_expression(config[CONF_STEP_PIN]) var = cg.new_Pvariable(config[CONF_ID])
dir_pin = yield cg.gpio_pin_expression(config[CONF_DIR_PIN])
var = cg.new_Pvariable(config[CONF_ID], step_pin, dir_pin)
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield stepper.register_stepper(var, config) yield stepper.register_stepper(var, config)
step_pin = yield cg.gpio_pin_expression(config[CONF_STEP_PIN])
cg.add(var.set_step_pin(step_pin))
dir_pin = yield cg.gpio_pin_expression(config[CONF_DIR_PIN])
cg.add(var.set_dir_pin(dir_pin))
if CONF_SLEEP_PIN in config: if CONF_SLEEP_PIN in config:
sleep_pin = yield cg.gpio_pin_expression(config[CONF_SLEEP_PIN]) sleep_pin = yield cg.gpio_pin_expression(config[CONF_SLEEP_PIN])
cg.add(var.set_sleep_pin(sleep_pin)) cg.add(var.set_sleep_pin(sleep_pin))

View file

@ -6,9 +6,6 @@ namespace adc {
static const char *TAG = "adc"; static const char *TAG = "adc";
ADCSensor::ADCSensor(const std::string &name, uint8_t pin, uint32_t update_interval)
: PollingSensorComponent(name, update_interval), pin_(pin) {}
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
void ADCSensor::set_attenuation(adc_attenuation_t attenuation) { this->attenuation_ = attenuation; } void ADCSensor::set_attenuation(adc_attenuation_t attenuation) { this->attenuation_ = attenuation; }
#endif #endif

View file

@ -7,11 +7,8 @@
namespace esphome { namespace esphome {
namespace adc { namespace adc {
class ADCSensor : public sensor::PollingSensorComponent { class ADCSensor : public sensor::Sensor, public PollingComponent {
public: public:
/// Construct the ADCSensor with the provided pin and update interval in ms.
explicit ADCSensor(const std::string &name, uint8_t pin, uint32_t update_interval);
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
/// Set the attenuation for this pin. Only available on the ESP32. /// Set the attenuation for this pin. Only available on the ESP32.
void set_attenuation(adc_attenuation_t attenuation); void set_attenuation(adc_attenuation_t attenuation);
@ -26,6 +23,7 @@ class ADCSensor : public sensor::PollingSensorComponent {
void dump_config() override; void dump_config() override;
/// `HARDWARE_LATE` setup priority. /// `HARDWARE_LATE` setup priority.
float get_setup_priority() const override; float get_setup_priority() const override;
void set_pin(uint8_t pin) { this->pin_ = pin; }
#ifdef ARDUINO_ARCH_ESP8266 #ifdef ARDUINO_ARCH_ESP8266
std::string unique_id() override; std::string unique_id() override;

View file

@ -2,8 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import pins from esphome import pins
from esphome.components import sensor from esphome.components import sensor
from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL, \ from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_PIN, ICON_FLASH, UNIT_VOLT
CONF_ICON, ICON_FLASH, CONF_UNIT_OF_MEASUREMENT, UNIT_VOLT, CONF_ACCURACY_DECIMALS
ATTENUATION_MODES = { ATTENUATION_MODES = {
'0db': cg.global_ns.ADC_0db, '0db': cg.global_ns.ADC_0db,
@ -23,30 +22,24 @@ def validate_adc_pin(value):
adc_ns = cg.esphome_ns.namespace('adc') adc_ns = cg.esphome_ns.namespace('adc')
ADCSensor = adc_ns.class_('ADCSensor', sensor.PollingSensorComponent) ADCSensor = adc_ns.class_('ADCSensor', sensor.PollingSensorComponent)
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 2).extend({
cv.GenerateID(): cv.declare_variable_id(ADCSensor), cv.GenerateID(): cv.declare_id(ADCSensor),
cv.Required(CONF_PIN): validate_adc_pin, cv.Required(CONF_PIN): validate_adc_pin,
cv.Optional(CONF_ATTENUATION): cv.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES, cv.SplitDefault(CONF_ATTENUATION, esp32='0db'):
lower=True)), cv.All(cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)),
}).extend(cv.polling_component_schema('60s'))
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
cv.Optional(CONF_ICON, default=ICON_FLASH): sensor.icon,
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_VOLT): sensor.unit_of_measurement,
cv.Optional(CONF_ACCURACY_DECIMALS, default=2): sensor.accuracy_decimals,
}).extend(cv.COMPONENT_SCHEMA))
def to_code(config): def to_code(config):
pin = config[CONF_PIN] var = cg.new_Pvariable(config[CONF_ID])
if pin == 'VCC': yield cg.register_component(var, config)
pin = 0 yield sensor.register_sensor(var, config)
if config[CONF_PIN] == 'VCC':
cg.add_define('USE_ADC_SENSOR_VCC') cg.add_define('USE_ADC_SENSOR_VCC')
cg.add_global(cg.global_ns.ADC_MODE(cg.global_ns.ADC_VCC)) cg.add_global(cg.global_ns.ADC_MODE(cg.global_ns.ADC_VCC))
rhs = ADCSensor.new(config[CONF_NAME], pin, config[CONF_UPDATE_INTERVAL]) else:
adc = cg.Pvariable(config[CONF_ID], rhs) cg.add(var.set_pin(config[CONF_PIN]))
yield cg.register_component(adc, config)
yield sensor.register_sensor(adc, config)
if CONF_ATTENUATION in config: if CONF_ATTENUATION in config:
cg.add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]])) cg.add(var.set_attenuation(config[CONF_ATTENUATION]))

View file

@ -11,7 +11,7 @@ ads1115_ns = cg.esphome_ns.namespace('ads1115')
ADS1115Component = ads1115_ns.class_('ADS1115Component', cg.Component, i2c.I2CDevice) ADS1115Component = ads1115_ns.class_('ADS1115Component', cg.Component, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ADS1115Component), cv.GenerateID(): cv.declare_id(ADS1115Component),
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(None)) }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(None))

View file

@ -48,9 +48,6 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. /// Internal holder class that is in instance of Sensor so that the hub can create individual sensors.
class ADS1115Sensor : public sensor::Sensor { class ADS1115Sensor : public sensor::Sensor {
public: public:
ADS1115Sensor(const std::string &name, uint32_t update_interval)
: sensor::Sensor(name), update_interval_(update_interval) {}
void set_multiplexer(ADS1115Multiplexer multiplexer); void set_multiplexer(ADS1115Multiplexer multiplexer);
void set_gain(ADS1115Gain gain); void set_gain(ADS1115Gain gain);

View file

@ -2,8 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.components.ads1115 import ADS1115Component from esphome.components.ads1115 import ADS1115Component
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, CONF_UPDATE_INTERVAL, \ from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
ICON_FLASH, UNIT_VOLT, CONF_ID, CONF_NAME
from esphome.py_compat import string_types from esphome.py_compat import string_types
from . import ads1115_ns from . import ads1115_ns
@ -38,27 +37,26 @@ def validate_gain(value):
elif not isinstance(value, string_types): elif not isinstance(value, string_types):
raise cv.Invalid('invalid gain "{}"'.format(value)) raise cv.Invalid('invalid gain "{}"'.format(value))
return cv.one_of(*GAIN)(value) return cv.enum(GAIN)(value)
ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor) ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor)
CONF_ADS1115_ID = 'ads1115_id' CONF_ADS1115_ID = 'ads1115_id'
CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({
cv.GenerateID(): cv.declare_variable_id(ADS1115Sensor), cv.GenerateID(): cv.declare_id(ADS1115Sensor),
cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component), cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component),
cv.Required(CONF_MULTIPLEXER): cv.one_of(*MUX, upper=True, space='_'), cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space='_'),
cv.Required(CONF_GAIN): validate_gain, cv.Required(CONF_GAIN): validate_gain,
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s'))
}))
def to_code(config): def to_code(config):
hub = yield cg.get_variable(config[CONF_ADS1115_ID]) var = cg.new_Pvariable(config[CONF_ID])
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL])
cg.add(var.set_multiplexer(MUX[config[CONF_MULTIPLEXER]]))
cg.add(var.set_gain(GAIN[config[CONF_GAIN]]))
yield sensor.register_sensor(var, config) yield sensor.register_sensor(var, config)
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
cg.add(var.set_gain(config[CONF_GAIN]))
hub = yield cg.get_variable(config[CONF_ADS1115_ID])
cg.add(hub.register_sensor(var)) cg.add(hub.register_sensor(var))

View file

@ -1,7 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c from esphome.components import i2c
from esphome.const import CONF_ID, CONF_UPDATE_INTERVAL from esphome.const import CONF_ID
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
AUTO_LOAD = ['sensor', 'binary_sensor'] AUTO_LOAD = ['sensor', 'binary_sensor']
@ -13,12 +13,11 @@ apds9960_nds = cg.esphome_ns.namespace('apds9960')
APDS9960 = apds9960_nds.class_('APDS9960', cg.PollingComponent, i2c.I2CDevice) APDS9960 = apds9960_nds.class_('APDS9960', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(APDS9960), cv.GenerateID(): cv.declare_id(APDS9960),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x39))
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x39))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)

View file

@ -10,7 +10,6 @@ namespace apds9960 {
class APDS9960 : public PollingComponent, public i2c::I2CDevice { class APDS9960 : public PollingComponent, public i2c::I2CDevice {
public: public:
APDS9960(uint32_t update_interval) : PollingComponent(update_interval) {}
void setup() override; void setup() override;
void dump_config() override; void dump_config() override;
float get_setup_priority() const override; float get_setup_priority() const override;

View file

@ -13,11 +13,11 @@ DIRECTIONS = {
'RIGHT': 'set_right_direction', 'RIGHT': 'set_right_direction',
} }
CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True), cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True),
cv.GenerateID(CONF_APDS9960_ID): cv.use_variable_id(APDS9960), cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960),
cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING): binary_sensor.device_class, cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING): binary_sensor.device_class,
})) })
def to_code(config): def to_code(config):

View file

@ -1,8 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.const import CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, CONF_ACCURACY_DECIMALS, CONF_ICON, \ from esphome.const import CONF_TYPE, UNIT_PERCENT, ICON_LIGHTBULB
UNIT_PERCENT, ICON_LIGHTBULB
from . import APDS9960, CONF_APDS9960_ID from . import APDS9960, CONF_APDS9960_ID
DEPENDENCIES = ['apds9960'] DEPENDENCIES = ['apds9960']
@ -15,14 +14,10 @@ TYPES = {
'PROXIMITY': 'set_proximity', 'PROXIMITY': 'set_proximity',
} }
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_LIGHTBULB, 1).extend({
cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True), cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True),
cv.GenerateID(CONF_APDS9960_ID): cv.use_variable_id(APDS9960), cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960),
})
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_PERCENT): sensor.unit_of_measurement,
cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals,
cv.Optional(CONF_ICON, default=ICON_LIGHTBULB): sensor.icon,
}))
def to_code(config): def to_code(config):

View file

@ -1,20 +1,21 @@
from esphome import automation
from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY, Condition
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation
from esphome.automation import Condition
from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \ from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \
CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
DEPENDENCIES = ['network']
api_ns = cg.esphome_ns.namespace('api') api_ns = cg.esphome_ns.namespace('api')
APIServer = api_ns.class_('APIServer', cg.Component, cg.Controller) APIServer = api_ns.class_('APIServer', cg.Component, cg.Controller)
HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', cg.Action) HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', automation.Action)
KeyValuePair = api_ns.class_('KeyValuePair') KeyValuePair = api_ns.class_('KeyValuePair')
TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair') TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair')
APIConnectedCondition = api_ns.class_('APIConnectedCondition', Condition) APIConnectedCondition = api_ns.class_('APIConnectedCondition', Condition)
UserService = api_ns.class_('UserService', cg.Trigger) UserService = api_ns.class_('UserService', automation.Trigger)
ServiceTypeArgument = api_ns.class_('ServiceTypeArgument') ServiceTypeArgument = api_ns.class_('ServiceTypeArgument')
ServiceArgType = api_ns.enum('ServiceArgType') ServiceArgType = api_ns.enum('ServiceArgType')
SERVICE_ARG_TYPES = { SERVICE_ARG_TYPES = {
@ -30,14 +31,13 @@ SERVICE_ARG_NATIVE_TYPES = {
'string': cg.std_string, 'string': cg.std_string,
} }
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(APIServer), cv.GenerateID(): cv.declare_id(APIServer),
cv.Optional(CONF_PORT, default=6053): cv.port, cv.Optional(CONF_PORT, default=6053): cv.port,
cv.Optional(CONF_PASSWORD, default=''): cv.string_strict, cv.Optional(CONF_PASSWORD, default=''): cv.string_strict,
cv.Optional(CONF_REBOOT_TIMEOUT, default='5min'): cv.positive_time_period_milliseconds, cv.Optional(CONF_REBOOT_TIMEOUT, default='5min'): cv.positive_time_period_milliseconds,
cv.Optional(CONF_SERVICES): automation.validate_automation({ cv.Optional(CONF_SERVICES): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(UserService), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserService),
cv.Required(CONF_SERVICE): cv.valid_name, cv.Required(CONF_SERVICE): cv.valid_name,
cv.Optional(CONF_VARIABLES, default={}): cv.Schema({ cv.Optional(CONF_VARIABLES, default={}): cv.Schema({
cv.validate_id_name: cv.one_of(*SERVICE_ARG_TYPES, lower=True), cv.validate_id_name: cv.one_of(*SERVICE_ARG_TYPES, lower=True),
@ -48,13 +48,12 @@ CONFIG_SCHEMA = cv.Schema({
@coroutine_with_priority(40.0) @coroutine_with_priority(40.0)
def to_code(config): def to_code(config):
rhs = APIServer.new() var = cg.new_Pvariable(config[CONF_ID])
api = cg.Pvariable(config[CONF_ID], rhs) yield cg.register_component(var, config)
yield cg.register_component(api, config)
cg.add(api.set_port(config[CONF_PORT])) cg.add(var.set_port(config[CONF_PORT]))
cg.add(api.set_password(config[CONF_PASSWORD])) cg.add(var.set_password(config[CONF_PASSWORD]))
cg.add(api.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
for conf in config.get(CONF_SERVICES, []): for conf in config.get(CONF_SERVICES, []):
template_args = [] template_args = []
@ -65,10 +64,9 @@ def to_code(config):
template_args.append(native) template_args.append(native)
func_args.append((native, name)) func_args.append((native, name))
service_type_args.append(ServiceTypeArgument(name, SERVICE_ARG_TYPES[var_])) service_type_args.append(ServiceTypeArgument(name, SERVICE_ARG_TYPES[var_]))
func = api.make_user_service_trigger.template(*template_args) templ = cg.TemplateArguments(*template_args)
rhs = func(conf[CONF_SERVICE], service_type_args) trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ,
type_ = UserService.template(*template_args) conf[CONF_SERVICE], service_type_args)
trigger = cg.Pvariable(conf[CONF_TRIGGER_ID], rhs, type=type_)
yield automation.build_automation(trigger, func_args, conf) yield automation.build_automation(trigger, func_args, conf)
cg.add_define('USE_API') cg.add_define('USE_API')
@ -78,9 +76,8 @@ def to_code(config):
cg.add_library('ESPAsyncTCP', '1.2.0') cg.add_library('ESPAsyncTCP', '1.2.0')
CONF_HOMEASSISTANT_SERVICE = 'homeassistant.service'
HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({ HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({
cv.GenerateID(): cv.use_variable_id(APIServer), cv.GenerateID(): cv.use_id(APIServer),
cv.Required(CONF_SERVICE): cv.string, cv.Required(CONF_SERVICE): cv.string,
cv.Optional(CONF_DATA): cv.Schema({ cv.Optional(CONF_DATA): cv.Schema({
cv.string: cv.string, cv.string: cv.string,
@ -94,34 +91,27 @@ HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({
}) })
@ACTION_REGISTRY.register(CONF_HOMEASSISTANT_SERVICE, HOMEASSISTANT_SERVICE_ACTION_SCHEMA) @automation.register_action('homeassistant.service', HomeAssistantServiceCallAction,
HOMEASSISTANT_SERVICE_ACTION_SCHEMA)
def homeassistant_service_to_code(config, action_id, template_arg, args): def homeassistant_service_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) serv = yield cg.get_variable(config[CONF_ID])
type = HomeAssistantServiceCallAction.template(template_arg) var = cg.new_Pvariable(action_id, template_arg, serv)
rhs = type.new(var) cg.add(var.set_service(config[CONF_SERVICE]))
act = cg.Pvariable(action_id, rhs, type=type)
cg.add(act.set_service(config[CONF_SERVICE]))
if CONF_DATA in config: if CONF_DATA in config:
datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA].items()] datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA].items()]
cg.add(act.set_data(datas)) cg.add(var.set_data(datas))
if CONF_DATA_TEMPLATE in config: if CONF_DATA_TEMPLATE in config:
datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA_TEMPLATE].items()] datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA_TEMPLATE].items()]
cg.add(act.set_data_template(datas)) cg.add(var.set_data_template(datas))
if CONF_VARIABLES in config: if CONF_VARIABLES in config:
datas = [] datas = []
for key, value in config[CONF_VARIABLES].items(): for key, value in config[CONF_VARIABLES].items():
value_ = yield cg.process_lambda(value, []) value_ = yield cg.process_lambda(value, [])
datas.append(TemplatableKeyValuePair(key, value_)) datas.append(TemplatableKeyValuePair(key, value_))
cg.add(act.set_variables(datas)) cg.add(var.set_variables(datas))
yield act yield var
CONF_API_CONNECTED = 'api.connected' @automation.register_condition('api.connected', APIConnectedCondition, {})
API_CONNECTED_CONDITION_SCHEMA = cv.Schema({})
@CONDITION_REGISTRY.register(CONF_API_CONNECTED, API_CONNECTED_CONDITION_SCHEMA)
def api_connected_to_code(config, condition_id, template_arg, args): def api_connected_to_code(config, condition_id, template_arg, args):
rhs = APIConnectedCondition.new(template_arg) yield cg.new_Pvariable(condition_id, template_arg)
type = APIConnectedCondition.template(template_arg)
yield cg.Pvariable(condition_id, rhs, type=type)

View file

@ -999,7 +999,7 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin
bool success = this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE); bool success = this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE);
if (!success) { if (!success) {
auto buffer = this->get_buffer(); buffer = this->get_buffer();
// bool send_failed = 4; // bool send_failed = 4;
buffer.encode_bool(4, true); buffer.encode_bool(4, true);
return this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE); return this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE);

View file

@ -226,10 +226,7 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
this->resp_.set_data_template(data_template); this->resp_.set_data_template(data_template);
} }
void set_variables(const std::vector<TemplatableKeyValuePair> &variables) { this->resp_.set_variables(variables); } void set_variables(const std::vector<TemplatableKeyValuePair> &variables) { this->resp_.set_variables(variables); }
void play(Ts... x) override { void play(Ts... x) override { this->parent_->send_service_call(this->resp_); }
this->parent_->send_service_call(this->resp_);
this->play_next(x...);
}
protected: protected:
APIServer *parent_; APIServer *parent_;

View file

@ -138,11 +138,8 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa
this->supports_away_ = true; this->supports_away_ = true;
this->away_config_ = away_config; this->away_config_ = away_config;
} }
BangBangClimate::BangBangClimate(const std::string &name) BangBangClimate::BangBangClimate()
: climate::Climate(name), : idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {}
idle_trigger_(new Trigger<>()),
cool_trigger_(new Trigger<>()),
heat_trigger_(new Trigger<>()) {}
void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; } void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; } Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; }
Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; } Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; }

View file

@ -19,7 +19,7 @@ struct BangBangClimateTargetTempConfig {
class BangBangClimate : public climate::Climate, public Component { class BangBangClimate : public climate::Climate, public Component {
public: public:
BangBangClimate(const std::string &name); BangBangClimate();
void setup() override; void setup() override;
void set_sensor(sensor::Sensor *sensor); void set_sensor(sensor::Sensor *sensor);

View file

@ -4,15 +4,15 @@ from esphome import automation
from esphome.components import climate, sensor from esphome.components import climate, sensor
from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \ from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \
CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION, \ CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION, \
CONF_ID, CONF_IDLE_ACTION, CONF_NAME, CONF_SENSOR CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR
bang_bang_ns = cg.esphome_ns.namespace('bang_bang') bang_bang_ns = cg.esphome_ns.namespace('bang_bang')
BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.ClimateDevice) BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.ClimateDevice)
BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig') BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig')
CONFIG_SCHEMA = cv.nameable(climate.CLIMATE_SCHEMA.extend({ CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(BangBangClimate), cv.GenerateID(): cv.declare_id(BangBangClimate),
cv.Required(CONF_SENSOR): cv.use_variable_id(sensor.Sensor), cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature,
cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True),
@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.nameable(climate.CLIMATE_SCHEMA.extend({
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield climate.register_climate(var, config) yield climate.register_climate(var, config)

View file

@ -8,9 +8,6 @@ static const char *TAG = "bh1750.sensor";
static const uint8_t BH1750_COMMAND_POWER_ON = 0b00000001; static const uint8_t BH1750_COMMAND_POWER_ON = 0b00000001;
BH1750Sensor::BH1750Sensor(const std::string &name, uint32_t update_interval)
: PollingSensorComponent(name, update_interval) {}
void BH1750Sensor::setup() { void BH1750Sensor::setup() {
ESP_LOGCONFIG(TAG, "Setting up BH1750 '%s'...", this->name_.c_str()); ESP_LOGCONFIG(TAG, "Setting up BH1750 '%s'...", this->name_.c_str());
if (!this->write_bytes(BH1750_COMMAND_POWER_ON, nullptr, 0)) { if (!this->write_bytes(BH1750_COMMAND_POWER_ON, nullptr, 0)) {

View file

@ -15,10 +15,8 @@ enum BH1750Resolution {
}; };
/// This class implements support for the i2c-based BH1750 ambient light sensor. /// This class implements support for the i2c-based BH1750 ambient light sensor.
class BH1750Sensor : public sensor::PollingSensorComponent, public i2c::I2CDevice { class BH1750Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
public: public:
BH1750Sensor(const std::string &name, uint32_t update_interval);
/** Set the resolution of this sensor. /** Set the resolution of this sensor.
* *
* Possible values are: * Possible values are:

View file

@ -1,8 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_ID, CONF_NAME, CONF_RESOLUTION, CONF_UPDATE_INTERVAL, UNIT_LUX, \ from esphome.const import CONF_ID, CONF_RESOLUTION, UNIT_LUX, ICON_BRIGHTNESS_5
ICON_BRIGHTNESS_5
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -16,17 +15,16 @@ BH1750_RESOLUTIONS = {
BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.PollingSensorComponent, i2c.I2CDevice) BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.PollingSensorComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({
cv.GenerateID(): cv.declare_variable_id(BH1750Sensor), cv.GenerateID(): cv.declare_id(BH1750Sensor),
cv.Optional(CONF_RESOLUTION, default=0.0): cv.one_of(*BH1750_RESOLUTIONS, float=True), cv.Optional(CONF_RESOLUTION, default=0.5): cv.enum(BH1750_RESOLUTIONS, float=True),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x23))
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x23)))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield sensor.register_sensor(var, config) yield sensor.register_sensor(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)
cg.add(var.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]])) cg.add(var.set_resolution(config[CONF_RESOLUTION]))

View file

@ -1,25 +1,27 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import fan, output from esphome.components import fan, output
from esphome.const import CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, \ from esphome.const import CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_OUTPUT_ID
CONF_OUTPUT_ID
from .. import binary_ns from .. import binary_ns
BinaryFan = binary_ns.class_('BinaryFan', cg.Component) BinaryFan = binary_ns.class_('BinaryFan', cg.Component)
CONFIG_SCHEMA = cv.nameable(fan.FAN_SCHEMA.extend({ CONFIG_SCHEMA = fan.FAN_SCHEMA.extend({
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(BinaryFan), cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryFan),
cv.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput), cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput), cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput),
}).extend(cv.COMPONENT_SCHEMA)) }).extend(cv.COMPONENT_SCHEMA)
def to_code(config): def to_code(config):
output_ = yield cg.get_variable(config[CONF_OUTPUT]) var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
state = yield fan.create_fan_state(config)
var = cg.new_Pvariable(config[CONF_OUTPUT_ID], state, output_)
yield cg.register_component(var, config) yield cg.register_component(var, config)
fan_ = yield fan.create_fan_state(config)
cg.add(var.set_fan(fan_))
output_ = yield cg.get_variable(config[CONF_OUTPUT])
cg.add(var.set_output(output_))
if CONF_OSCILLATION_OUTPUT in config: if CONF_OSCILLATION_OUTPUT in config:
oscillation_output = yield cg.get_variable(config[CONF_OSCILLATION_OUTPUT]) oscillation_output = yield cg.get_variable(config[CONF_OSCILLATION_OUTPUT])
cg.add(var.set_oscillation(oscillation_output)) cg.add(var.set_oscillation(oscillation_output))

View file

@ -9,7 +9,8 @@ namespace binary {
class BinaryFan : public Component { class BinaryFan : public Component {
public: public:
BinaryFan(fan::FanState *fan, output::BinaryOutput *output) : fan_(fan), output_(output) {} void set_fan(fan::FanState *fan) { fan_ = fan; }
void set_output(output::BinaryOutput *output) { output_ = output; }
void setup() override; void setup() override;
void loop() override; void loop() override;
void dump_config() override; void dump_config() override;

View file

@ -6,13 +6,15 @@ from .. import binary_ns
BinaryLightOutput = binary_ns.class_('BinaryLightOutput', light.LightOutput) BinaryLightOutput = binary_ns.class_('BinaryLightOutput', light.LightOutput)
CONFIG_SCHEMA = cv.nameable(light.BINARY_LIGHT_SCHEMA.extend({ CONFIG_SCHEMA = light.BINARY_LIGHT_SCHEMA.extend({
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(BinaryLightOutput), cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryLightOutput),
cv.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput), cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
})) })
def to_code(config): def to_code(config):
out = yield cg.get_variable(config[CONF_OUTPUT]) var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
var = cg.new_Pvariable(config[CONF_OUTPUT_ID], out)
yield light.register_light(var, config) yield light.register_light(var, config)
out = yield cg.get_variable(config[CONF_OUTPUT])
cg.add(var.set_output(out))

View file

@ -9,7 +9,7 @@ namespace binary {
class BinaryLightOutput : public light::LightOutput { class BinaryLightOutput : public light::LightOutput {
public: public:
BinaryLightOutput(output::BinaryOutput *output) : output_(output) {} void set_output(output::BinaryOutput *output) { output_ = output; }
light::LightTraits get_traits() override { light::LightTraits get_traits() override {
auto traits = light::LightTraits(); auto traits = light::LightTraits();
traits.set_supports_brightness(false); traits.set_supports_brightness(false);

View file

@ -1,16 +1,16 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import automation, core from esphome import automation, core
from esphome.automation import CONDITION_REGISTRY, Condition, maybe_simple_id from esphome.automation import Condition, maybe_simple_id
from esphome.components import mqtt from esphome.components import mqtt
from esphome.const import CONF_DEVICE_CLASS, CONF_FILTERS, \ from esphome.const import CONF_DEVICE_CLASS, CONF_FILTERS, \
CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERTED, \ CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERTED, \
CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_ON_CLICK, \ CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_ON_CLICK, \
CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_ON_STATE, \ CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_ON_STATE, \
CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_VALUE, CONF_NAME, CONF_MQTT_ID CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_NAME, CONF_MQTT_ID
from esphome.core import CORE, coroutine from esphome.core import CORE, coroutine, coroutine_with_priority
from esphome.py_compat import string_types from esphome.py_compat import string_types
from esphome.util import ServiceRegistry from esphome.util import Registry
DEVICE_CLASSES = [ DEVICE_CLASSES = [
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas', '', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
@ -26,15 +26,15 @@ BinarySensor = binary_sensor_ns.class_('BinarySensor', cg.Nameable)
BinarySensorPtr = BinarySensor.operator('ptr') BinarySensorPtr = BinarySensor.operator('ptr')
# Triggers # Triggers
PressTrigger = binary_sensor_ns.class_('PressTrigger', cg.Trigger.template()) PressTrigger = binary_sensor_ns.class_('PressTrigger', automation.Trigger.template())
ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', cg.Trigger.template()) ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', automation.Trigger.template())
ClickTrigger = binary_sensor_ns.class_('ClickTrigger', cg.Trigger.template()) ClickTrigger = binary_sensor_ns.class_('ClickTrigger', automation.Trigger.template())
DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', cg.Trigger.template()) DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', automation.Trigger.template())
MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', cg.Trigger.template(), MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', automation.Trigger.template(),
cg.Component) cg.Component)
MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent') MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent')
StateTrigger = binary_sensor_ns.class_('StateTrigger', cg.Trigger.template(bool)) StateTrigger = binary_sensor_ns.class_('StateTrigger', automation.Trigger.template(bool))
BinarySensorPublishAction = binary_sensor_ns.class_('BinarySensorPublishAction', cg.Action) BinarySensorPublishAction = binary_sensor_ns.class_('BinarySensorPublishAction', automation.Action)
# Condition # Condition
BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition) BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition)
@ -46,55 +46,34 @@ DelayedOffFilter = binary_sensor_ns.class_('DelayedOffFilter', Filter, cg.Compon
InvertFilter = binary_sensor_ns.class_('InvertFilter', Filter) InvertFilter = binary_sensor_ns.class_('InvertFilter', Filter)
LambdaFilter = binary_sensor_ns.class_('LambdaFilter', Filter) LambdaFilter = binary_sensor_ns.class_('LambdaFilter', Filter)
FILTER_REGISTRY = ServiceRegistry() FILTER_REGISTRY = Registry()
validate_filters = cv.validate_registry('filter', FILTER_REGISTRY, [CONF_ID]) validate_filters = cv.validate_registry('filter', FILTER_REGISTRY)
@FILTER_REGISTRY.register('invert', @FILTER_REGISTRY.register('invert', InvertFilter, {})
cv.Schema({ def invert_filter_to_code(config, filter_id):
cv.GenerateID(): cv.declare_variable_id(InvertFilter) yield cg.new_Pvariable(filter_id)
}))
def invert_filter_to_code(config):
rhs = InvertFilter.new() @FILTER_REGISTRY.register('delayed_on', DelayedOnFilter,
var = cg.Pvariable(config[CONF_ID], rhs) cv.positive_time_period_milliseconds)
def delayed_on_filter_to_code(config, filter_id):
var = cg.new_Pvariable(filter_id, config)
yield cg.register_component(var, {})
yield var yield var
@FILTER_REGISTRY.register('delayed_on', @FILTER_REGISTRY.register('delayed_off', DelayedOffFilter, cv.positive_time_period_milliseconds)
cv.maybe_simple_value(cv.Schema({ def delayed_off_filter_to_code(config, filter_id):
cv.GenerateID(): cv.declare_variable_id(DelayedOnFilter), var = cg.new_Pvariable(filter_id, config)
cv.Required(CONF_VALUE): cv.positive_time_period_milliseconds, yield cg.register_component(var, {})
}).extend(cv.COMPONENT_SCHEMA)))
def delayed_on_filter_to_code(config):
rhs = DelayedOnFilter.new(config[CONF_VALUE])
var = cg.Pvariable(config[CONF_ID], rhs)
yield cg.register_component(var, config)
yield var yield var
@FILTER_REGISTRY.register('delayed_off', @FILTER_REGISTRY.register('lambda', LambdaFilter, cv.lambda_)
cv.maybe_simple_value(cv.Schema({ def lambda_filter_to_code(config, filter_id):
cv.GenerateID(): cv.declare_variable_id(DelayedOffFilter), lambda_ = yield cg.process_lambda(config, [(bool, 'x')], return_type=cg.optional.template(bool))
cv.Required(CONF_VALUE): cv.positive_time_period_milliseconds, yield cg.new_Pvariable(filter_id, lambda_)
}).extend(cv.COMPONENT_SCHEMA)))
def delayed_off_filter_to_code(config):
rhs = DelayedOffFilter.new(config[CONF_VALUE])
var = cg.Pvariable(config[CONF_ID], rhs)
yield cg.register_component(var, config)
yield var
@FILTER_REGISTRY.register('lambda',
cv.maybe_simple_value(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(LambdaFilter),
cv.Required(CONF_VALUE): cv.lambda_,
})))
def lambda_filter_to_code(config):
lambda_ = yield cg.process_lambda(config[CONF_VALUE], [(bool, 'x')],
return_type=cg.optional.template(bool))
rhs = LambdaFilter.new(lambda_)
var = cg.Pvariable(config[CONF_ID], rhs)
yield var
MULTI_CLICK_TIMING_SCHEMA = cv.Schema({ MULTI_CLICK_TIMING_SCHEMA = cv.Schema({
@ -193,35 +172,35 @@ def validate_multi_click_timing(value):
device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space='_') device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space='_')
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(BinarySensor), cv.GenerateID(): cv.declare_id(BinarySensor),
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTBinarySensorComponent), cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTBinarySensorComponent),
cv.Optional(CONF_DEVICE_CLASS): device_class, cv.Optional(CONF_DEVICE_CLASS): device_class,
cv.Optional(CONF_FILTERS): validate_filters, cv.Optional(CONF_FILTERS): validate_filters,
cv.Optional(CONF_ON_PRESS): automation.validate_automation({ cv.Optional(CONF_ON_PRESS): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PressTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger),
}), }),
cv.Optional(CONF_ON_RELEASE): automation.validate_automation({ cv.Optional(CONF_ON_RELEASE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ReleaseTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger),
}), }),
cv.Optional(CONF_ON_CLICK): automation.validate_automation({ cv.Optional(CONF_ON_CLICK): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ClickTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger),
cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
}), }),
cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation({ cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(DoubleClickTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger),
cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
}), }),
cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation({ cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MultiClickTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger),
cv.Required(CONF_TIMING): cv.All([parse_multi_click_timing_str], cv.Required(CONF_TIMING): cv.All([parse_multi_click_timing_str],
validate_multi_click_timing), validate_multi_click_timing),
cv.Optional(CONF_INVALID_COOLDOWN, default='1s'): cv.positive_time_period_milliseconds, cv.Optional(CONF_INVALID_COOLDOWN, default='1s'): cv.positive_time_period_milliseconds,
}), }),
cv.Optional(CONF_ON_STATE): automation.validate_automation({ cv.Optional(CONF_ON_STATE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(StateTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
}), }),
cv.Optional(CONF_INVERTED): cv.invalid( cv.Optional(CONF_INVERTED): cv.invalid(
@ -234,6 +213,7 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
@coroutine @coroutine
def setup_binary_sensor_core_(var, config): def setup_binary_sensor_core_(var, config):
cg.add(var.set_name(config[CONF_NAME]))
if CONF_INTERNAL in config: if CONF_INTERNAL in config:
cg.add(var.set_internal(CONF_INTERNAL)) cg.add(var.set_internal(CONF_INTERNAL))
if CONF_DEVICE_CLASS in config: if CONF_DEVICE_CLASS in config:
@ -300,28 +280,28 @@ def new_binary_sensor(config):
yield var yield var
BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA = maybe_simple_id({ BINARY_SENSOR_CONDITION_SCHEMA = maybe_simple_id({
cv.Required(CONF_ID): cv.use_variable_id(BinarySensor), cv.Required(CONF_ID): cv.use_id(BinarySensor),
cv.Optional(CONF_FOR): cv.positive_time_period_milliseconds, cv.Optional(CONF_FOR): cv.invalid("This option has been removed in 1.13, please use the "
"'for' condition instead."),
}) })
@CONDITION_REGISTRY.register('binary_sensor.is_on', BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA) @automation.register_condition('binary_sensor.is_on', BinarySensorCondition,
BINARY_SENSOR_CONDITION_SCHEMA)
def binary_sensor_is_on_to_code(config, condition_id, template_arg, args): def binary_sensor_is_on_to_code(config, condition_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = BinarySensorCondition.template(template_arg) yield cg.new_Pvariable(condition_id, template_arg, paren, True)
rhs = type.new(var, True, config.get(CONF_FOR))
yield cg.Pvariable(condition_id, rhs, type=type)
@CONDITION_REGISTRY.register('binary_sensor.is_off', BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA) @automation.register_condition('binary_sensor.is_off', BinarySensorCondition,
BINARY_SENSOR_CONDITION_SCHEMA)
def binary_sensor_is_off_to_code(config, condition_id, template_arg, args): def binary_sensor_is_off_to_code(config, condition_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = BinarySensorCondition.template(template_arg) yield cg.new_Pvariable(condition_id, template_arg, paren, False)
rhs = type.new(var, False, config.get(CONF_FOR))
yield cg.Pvariable(condition_id, rhs, type=type)
@coroutine_with_priority(100.0)
def to_code(config): def to_code(config):
cg.add_define('USE_BINARY_SENSOR') cg.add_define('USE_BINARY_SENSOR')
cg.add_global(binary_sensor_ns.using) cg.add_global(binary_sensor_ns.using)

View file

@ -125,22 +125,12 @@ class StateTrigger : public Trigger<bool> {
template<typename... Ts> class BinarySensorCondition : public Condition<Ts...> { template<typename... Ts> class BinarySensorCondition : public Condition<Ts...> {
public: public:
BinarySensorCondition(BinarySensor *parent, bool state, uint32_t for_time = 0) BinarySensorCondition(BinarySensor *parent, bool state) : parent_(parent), state_(state) {}
: parent_(parent), state_(state), for_time_(for_time) { bool check(Ts... x) override { return this->parent_->state == this->state_; }
parent->add_on_state_callback([this](bool state) { this->last_state_time_ = millis(); });
}
bool check(Ts... x) override {
if (this->parent_->state != this->state_)
return false;
return millis() - this->last_state_time_ >= this->for_time_;
}
protected: protected:
BinarySensor *parent_; BinarySensor *parent_;
bool state_; bool state_;
uint32_t last_state_time_{0};
uint32_t for_time_{0};
}; };
template<typename... Ts> class BinarySensorPublishAction : public Action<Ts...> { template<typename... Ts> class BinarySensorPublishAction : public Action<Ts...> {
@ -150,7 +140,6 @@ template<typename... Ts> class BinarySensorPublishAction : public Action<Ts...>
void play(Ts... x) override { void play(Ts... x) override {
auto val = this->state_.value(x...); auto val = this->state_.value(x...);
this->sensor_->publish_state(val); this->sensor_->publish_state(val);
this->play_next(x...);
} }
protected: protected:

View file

@ -24,12 +24,12 @@ namespace binary_sensor {
*/ */
class BinarySensor : public Nameable { class BinarySensor : public Nameable {
public: public:
explicit BinarySensor();
/** Construct a binary sensor with the specified name /** Construct a binary sensor with the specified name
* *
* @param name Name of this binary sensor. * @param name Name of this binary sensor.
*/ */
explicit BinarySensor(const std::string &name); explicit BinarySensor(const std::string &name);
explicit BinarySensor();
/** Add a callback to be notified of state changes. /** Add a callback to be notified of state changes.
* *

View file

@ -11,10 +11,10 @@ ble_presence_ns = cg.esphome_ns.namespace('ble_presence')
BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor, BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor,
cg.Component, ESPBTDeviceListener) cg.Component, ESPBTDeviceListener)
CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(BLEPresenceDevice), cv.GenerateID(): cv.declare_id(BLEPresenceDevice),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) }).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)
def to_code(config): def to_code(config):

View file

@ -3,8 +3,7 @@ import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \
ESP_BLE_DEVICE_SCHEMA ESP_BLE_DEVICE_SCHEMA
from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, CONF_UNIT_OF_MEASUREMENT, \ from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL
CONF_ICON, CONF_ACCURACY_DECIMALS, UNIT_DECIBEL, ICON_SIGNAL
DEPENDENCIES = ['esp32_ble_tracker'] DEPENDENCIES = ['esp32_ble_tracker']
@ -12,14 +11,10 @@ ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi')
BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component, BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component,
ESPBTDeviceListener) ESPBTDeviceListener)
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_SIGNAL, 0).extend({
cv.GenerateID(): cv.declare_variable_id(BLERSSISensor), cv.GenerateID(): cv.declare_id(BLERSSISensor),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_DECIBEL): sensor.unit_of_measurement,
cv.Optional(CONF_ICON, default=ICON_SIGNAL): sensor.icon,
cv.Optional(CONF_ACCURACY_DECIMALS, default=0): sensor.accuracy_decimals
}).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA))
def to_code(config): def to_code(config):

View file

@ -60,8 +60,6 @@ enum BME280IIRFilter {
/// This class implements support for the BME280 Temperature+Pressure+Humidity i2c sensor. /// This class implements support for the BME280 Temperature+Pressure+Humidity i2c sensor.
class BME280Component : public PollingComponent, public i2c::I2CDevice { class BME280Component : public PollingComponent, public i2c::I2CDevice {
public: public:
BME280Component(uint32_t update_interval) : PollingComponent(update_interval) {}
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; }
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }

View file

@ -2,7 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, \ from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, \
CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, ICON_THERMOMETER, \ CONF_PRESSURE, CONF_TEMPERATURE, ICON_THERMOMETER, \
UNIT_CELSIUS, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT UNIT_CELSIUS, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -30,29 +30,28 @@ IIR_FILTER_OPTIONS = {
BME280Component = bme280_ns.class_('BME280Component', cg.PollingComponent, i2c.I2CDevice) BME280Component = bme280_ns.class_('BME280Component', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(BME280Component), cv.GenerateID(): cv.declare_id(BME280Component),
cv.Optional(CONF_TEMPERATURE): cv.nameable( cv.Optional(CONF_TEMPERATURE):
sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_PRESSURE): cv.nameable( cv.Optional(CONF_PRESSURE):
sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_HUMIDITY): cv.nameable( cv.Optional(CONF_HUMIDITY):
sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({ sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True), cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77))
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)
@ -60,18 +59,18 @@ def to_code(config):
conf = config[CONF_TEMPERATURE] conf = config[CONF_TEMPERATURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_temperature_sensor(sens)) cg.add(var.set_temperature_sensor(sens))
cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_PRESSURE in config: if CONF_PRESSURE in config:
conf = config[CONF_PRESSURE] conf = config[CONF_PRESSURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_pressure_sensor(sens)) cg.add(var.set_pressure_sensor(sens))
cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_HUMIDITY in config: if CONF_HUMIDITY in config:
conf = config[CONF_HUMIDITY] conf = config[CONF_HUMIDITY]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_humidity_sensor(sens)) cg.add(var.set_humidity_sensor(sens))
cg.add(var.set_humidity_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_humidity_oversampling(conf[CONF_OVERSAMPLING]))
cg.add(var.set_iir_filter(IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]])) cg.add(var.set_iir_filter(config[CONF_IIR_FILTER]))

View file

@ -68,8 +68,6 @@ struct BME680CalibrationData {
class BME680Component : public PollingComponent, public i2c::I2CDevice { class BME680Component : public PollingComponent, public i2c::I2CDevice {
public: public:
BME680Component(uint32_t update_interval) : PollingComponent(update_interval) {}
/// Set the temperature oversampling value. Defaults to 16X. /// Set the temperature oversampling value. Defaults to 16X.
void set_temperature_oversampling(BME680Oversampling temperature_oversampling); void set_temperature_oversampling(BME680Oversampling temperature_oversampling);
/// Set the pressure oversampling value. Defaults to 16X. /// Set the pressure oversampling value. Defaults to 16X.

View file

@ -4,7 +4,7 @@ from esphome import core
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_DURATION, CONF_GAS_RESISTANCE, CONF_HEATER, \ from esphome.const import CONF_DURATION, CONF_GAS_RESISTANCE, CONF_HEATER, \
CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, CONF_PRESSURE, \ CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, CONF_PRESSURE, \
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, UNIT_OHM, ICON_GAS_CYLINDER, UNIT_CELSIUS, \ CONF_TEMPERATURE, UNIT_OHM, ICON_GAS_CYLINDER, UNIT_CELSIUS, \
ICON_THERMOMETER, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT ICON_THERMOMETER, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -35,36 +35,35 @@ IIR_FILTER_OPTIONS = {
BME680Component = bme680_ns.class_('BME680Component', cg.PollingComponent, i2c.I2CDevice) BME680Component = bme680_ns.class_('BME680Component', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(BME680Component), cv.GenerateID(): cv.declare_id(BME680Component),
cv.Optional(CONF_TEMPERATURE): cv.nameable( cv.Optional(CONF_TEMPERATURE):
sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_PRESSURE): cv.nameable( cv.Optional(CONF_PRESSURE):
sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_HUMIDITY): cv.nameable( cv.Optional(CONF_HUMIDITY):
sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({ sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({
cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.Optional(CONF_OVERSAMPLING, default='16X'):
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.enum(OVERSAMPLING_OPTIONS, upper=True),
})), }),
cv.Optional(CONF_GAS_RESISTANCE): cv.nameable( cv.Optional(CONF_GAS_RESISTANCE):
sensor.sensor_schema(UNIT_OHM, ICON_GAS_CYLINDER, 1)), sensor.sensor_schema(UNIT_OHM, ICON_GAS_CYLINDER, 1),
cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True), cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True),
cv.Optional(CONF_HEATER): cv.Any(None, cv.All(cv.Schema({ cv.Optional(CONF_HEATER): cv.Any(None, cv.All(cv.Schema({
cv.Optional(CONF_TEMPERATURE, default=320): cv.All(cv.Coerce(int), cv.Range(200, 400)), cv.Optional(CONF_TEMPERATURE, default=320): cv.int_range(min=200, max=400),
cv.Optional(CONF_DURATION, default='150ms'): cv.All( cv.Optional(CONF_DURATION, default='150ms'): cv.All(
cv.positive_time_period_milliseconds, cv.Range(max=core.TimePeriod(milliseconds=4032))) cv.positive_time_period_milliseconds, cv.Range(max=core.TimePeriod(milliseconds=4032)))
}, cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION)))), }), cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION))),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x76))
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x76))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)
@ -72,19 +71,19 @@ def to_code(config):
conf = config[CONF_TEMPERATURE] conf = config[CONF_TEMPERATURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_temperature_sensor(sens)) cg.add(var.set_temperature_sensor(sens))
cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_PRESSURE in config: if CONF_PRESSURE in config:
conf = config[CONF_PRESSURE] conf = config[CONF_PRESSURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_pressure_sensor(sens)) cg.add(var.set_pressure_sensor(sens))
cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_HUMIDITY in config: if CONF_HUMIDITY in config:
conf = config[CONF_HUMIDITY] conf = config[CONF_HUMIDITY]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_humidity_sensor(sens)) cg.add(var.set_humidity_sensor(sens))
cg.add(var.set_humidity_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_humidity_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_GAS_RESISTANCE in config: if CONF_GAS_RESISTANCE in config:
conf = config[CONF_GAS_RESISTANCE] conf = config[CONF_GAS_RESISTANCE]

View file

@ -9,8 +9,6 @@ namespace bmp085 {
class BMP085Component : public PollingComponent, public i2c::I2CDevice { class BMP085Component : public PollingComponent, public i2c::I2CDevice {
public: public:
BMP085Component(uint32_t update_interval) : PollingComponent(update_interval) {}
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
void set_pressure(sensor::Sensor *pressure) { pressure_ = pressure; } void set_pressure(sensor::Sensor *pressure) { pressure_ = pressure; }

View file

@ -2,7 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \ from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -10,17 +10,14 @@ bmp085_ns = cg.esphome_ns.namespace('bmp085')
BMP085Component = bmp085_ns.class_('BMP085Component', cg.PollingComponent, i2c.I2CDevice) BMP085Component = bmp085_ns.class_('BMP085Component', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(BMP085Component), cv.GenerateID(): cv.declare_id(BMP085Component),
cv.Optional(CONF_TEMPERATURE): cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1),
cv.nameable(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1)), cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1),
cv.Optional(CONF_PRESSURE): }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77))
cv.nameable(sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1)),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)

View file

@ -233,7 +233,6 @@ uint16_t BMP280Component::read_u16_le_(uint8_t a_register) {
return (data >> 8) | (data << 8); return (data >> 8) | (data << 8);
} }
int16_t BMP280Component::read_s16_le_(uint8_t a_register) { return this->read_u16_le_(a_register); } int16_t BMP280Component::read_s16_le_(uint8_t a_register) { return this->read_u16_le_(a_register); }
BMP280Component::BMP280Component(uint32_t update_interval) : PollingComponent(update_interval) {}
} // namespace bmp280 } // namespace bmp280
} // namespace esphome } // namespace esphome

View file

@ -53,7 +53,6 @@ enum BMP280IIRFilter {
/// This class implements support for the BMP280 Temperature+Pressure i2c sensor. /// This class implements support for the BMP280 Temperature+Pressure i2c sensor.
class BMP280Component : public PollingComponent, public i2c::I2CDevice { class BMP280Component : public PollingComponent, public i2c::I2CDevice {
public: public:
BMP280Component(uint32_t update_interval);
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; }

View file

@ -2,7 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \ from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL, \ UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL, \
CONF_IIR_FILTER, CONF_OVERSAMPLING CONF_IIR_FILTER, CONF_OVERSAMPLING
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -30,24 +30,19 @@ IIR_FILTER_OPTIONS = {
BMP280Component = bmp280_ns.class_('BMP280Component', cg.PollingComponent, i2c.I2CDevice) BMP280Component = bmp280_ns.class_('BMP280Component', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(BMP280Component), cv.GenerateID(): cv.declare_id(BMP280Component),
cv.Optional(CONF_TEMPERATURE): cv.nameable( cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True),
cv.Optional(CONF_OVERSAMPLING, default='16X'): }),
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({
})), cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True),
cv.Optional(CONF_PRESSURE): cv.nameable( }),
sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True),
cv.Optional(CONF_OVERSAMPLING, default='16X'): }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77))
cv.one_of(*OVERSAMPLING_OPTIONS, upper=True),
})),
cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)
@ -55,10 +50,10 @@ def to_code(config):
conf = config[CONF_TEMPERATURE] conf = config[CONF_TEMPERATURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_temperature_sensor(sens)) cg.add(var.set_temperature_sensor(sens))
cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING]))
if CONF_PRESSURE in config: if CONF_PRESSURE in config:
conf = config[CONF_PRESSURE] conf = config[CONF_PRESSURE]
sens = yield sensor.new_sensor(conf) sens = yield sensor.new_sensor(conf)
cg.add(var.set_pressure_sensor(sens)) cg.add(var.set_pressure_sensor(sens))
cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING]))

View file

@ -1,19 +1,20 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.automation import ACTION_REGISTRY from esphome import automation
from esphome.components import mqtt from esphome.components import mqtt
from esphome.const import CONF_AWAY, CONF_ID, CONF_INTERNAL, CONF_MAX_TEMPERATURE, \ from esphome.const import CONF_AWAY, CONF_ID, CONF_INTERNAL, CONF_MAX_TEMPERATURE, \
CONF_MIN_TEMPERATURE, CONF_MODE, CONF_TARGET_TEMPERATURE, \ CONF_MIN_TEMPERATURE, CONF_MODE, CONF_TARGET_TEMPERATURE, \
CONF_TARGET_TEMPERATURE_HIGH, CONF_TARGET_TEMPERATURE_LOW, CONF_TEMPERATURE_STEP, CONF_VISUAL, \ CONF_TARGET_TEMPERATURE_HIGH, CONF_TARGET_TEMPERATURE_LOW, CONF_TEMPERATURE_STEP, CONF_VISUAL, \
CONF_MQTT_ID CONF_MQTT_ID, CONF_NAME
from esphome.core import CORE, coroutine from esphome.core import CORE, coroutine, coroutine_with_priority
IS_PLATFORM_COMPONENT = True
climate_ns = cg.esphome_ns.namespace('climate') climate_ns = cg.esphome_ns.namespace('climate')
ClimateDevice = climate_ns.class_('Climate', cg.Nameable) ClimateDevice = climate_ns.class_('Climate', cg.Nameable)
ClimateCall = climate_ns.class_('ClimateCall') ClimateCall = climate_ns.class_('ClimateCall')
ClimateTraits = climate_ns.class_('ClimateTraits') ClimateTraits = climate_ns.class_('ClimateTraits')
# MQTTClimateComponent = climate_ns.class_('MQTTClimateComponent', mqtt.MQTTComponent)
ClimateMode = climate_ns.enum('ClimateMode') ClimateMode = climate_ns.enum('ClimateMode')
CLIMATE_MODES = { CLIMATE_MODES = {
@ -23,14 +24,14 @@ CLIMATE_MODES = {
'HEAT': ClimateMode.CLIMATE_MODE_HEAT, 'HEAT': ClimateMode.CLIMATE_MODE_HEAT,
} }
validate_climate_mode = cv.one_of(*CLIMATE_MODES, upper=True) validate_climate_mode = cv.enum(CLIMATE_MODES, upper=True)
# Actions # Actions
ControlAction = climate_ns.class_('ControlAction', cg.Action) ControlAction = climate_ns.class_('ControlAction', automation.Action)
CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(ClimateDevice), cv.GenerateID(): cv.declare_id(ClimateDevice),
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTClimateComponent), cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTClimateComponent),
cv.Optional(CONF_VISUAL, default={}): cv.Schema({ cv.Optional(CONF_VISUAL, default={}): cv.Schema({
cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature,
cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature,
@ -42,6 +43,7 @@ CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
@coroutine @coroutine
def setup_climate_core_(var, config): def setup_climate_core_(var, config):
cg.add(var.set_name(config[CONF_NAME]))
if CONF_INTERNAL in config: if CONF_INTERNAL in config:
cg.add(var.set_internal(config[CONF_INTERNAL])) cg.add(var.set_internal(config[CONF_INTERNAL]))
visual = config[CONF_VISUAL] visual = config[CONF_VISUAL]
@ -66,7 +68,7 @@ def register_climate(var, config):
CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({
cv.Required(CONF_ID): cv.use_variable_id(ClimateDevice), cv.Required(CONF_ID): cv.use_id(ClimateDevice),
cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode), cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode),
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature), cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature),
cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature), cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature),
@ -75,31 +77,29 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({
}) })
@ACTION_REGISTRY.register('climate.control', CLIMATE_CONTROL_ACTION_SCHEMA) @automation.register_action('climate.control', ControlAction, CLIMATE_CONTROL_ACTION_SCHEMA)
def climate_control_to_code(config, action_id, template_arg, args): def climate_control_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = ControlAction.template(template_arg) var = cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
action = cg.Pvariable(action_id, rhs, type=type)
if CONF_MODE in config: if CONF_MODE in config:
template_ = yield cg.templatable(config[CONF_MODE], args, ClimateMode, template_ = yield cg.templatable(config[CONF_MODE], args, ClimateMode)
to_exp=CLIMATE_MODES) cg.add(var.set_mode(template_))
cg.add(action.set_mode(template_))
if CONF_TARGET_TEMPERATURE in config: if CONF_TARGET_TEMPERATURE in config:
template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE], args, float) template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE], args, float)
cg.add(action.set_target_temperature(template_)) cg.add(var.set_target_temperature(template_))
if CONF_TARGET_TEMPERATURE_LOW in config: if CONF_TARGET_TEMPERATURE_LOW in config:
template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_LOW], args, float) template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_LOW], args, float)
cg.add(action.set_target_temperature_low(template_)) cg.add(var.set_target_temperature_low(template_))
if CONF_TARGET_TEMPERATURE_HIGH in config: if CONF_TARGET_TEMPERATURE_HIGH in config:
template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_HIGH], args, float) template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_HIGH], args, float)
cg.add(action.set_target_temperature_high(template_)) cg.add(var.set_target_temperature_high(template_))
if CONF_AWAY in config: if CONF_AWAY in config:
template_ = yield cg.templatable(config[CONF_AWAY], args, bool) template_ = yield cg.templatable(config[CONF_AWAY], args, bool)
cg.add(action.set_away(template_)) cg.add(var.set_away(template_))
yield action yield var
@coroutine_with_priority(100.0)
def to_code(config): def to_code(config):
cg.add_define('USE_CLIMATE') cg.add_define('USE_CLIMATE')
cg.add_global(climate_ns.using) cg.add_global(climate_ns.using)

View file

@ -18,7 +18,8 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
void play(Ts... x) override { void play(Ts... x) override {
auto call = this->climate_->make_call(); auto call = this->climate_->make_call();
call.set_target_temperature(this->mode_.optional_value(x...)); call.set_mode(this->mode_.optional_value(x...));
call.set_target_temperature(this->target_temperature_.optional_value(x...));
call.set_target_temperature_low(this->target_temperature_low_.optional_value(x...)); call.set_target_temperature_low(this->target_temperature_low_.optional_value(x...));
call.set_target_temperature_high(this->target_temperature_high_.optional_value(x...)); call.set_target_temperature_high(this->target_temperature_high_.optional_value(x...));
call.set_away(this->away_.optional_value(x...)); call.set_away(this->away_.optional_value(x...));

View file

@ -114,10 +114,10 @@ struct ClimateDeviceRestoreState {
*/ */
class Climate : public Nameable { class Climate : public Nameable {
public: public:
/// Construct a climate device with a name.
Climate(const std::string &name);
/// Construct a climate device with empty name (will be set later). /// Construct a climate device with empty name (will be set later).
Climate(); Climate();
/// Construct a climate device with a name.
Climate(const std::string &name);
/// The active mode of the climate device. /// The active mode of the climate device.
ClimateMode mode{CLIMATE_MODE_OFF}; ClimateMode mode{CLIMATE_MODE_OFF};

View file

@ -1,10 +1,11 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.automation import ACTION_REGISTRY, maybe_simple_id, Condition from esphome import automation
from esphome.automation import maybe_simple_id, Condition
from esphome.components import mqtt from esphome.components import mqtt
from esphome.const import CONF_ID, CONF_INTERNAL, CONF_DEVICE_CLASS, CONF_STATE, \ from esphome.const import CONF_ID, CONF_INTERNAL, CONF_DEVICE_CLASS, CONF_STATE, \
CONF_POSITION, CONF_TILT, CONF_STOP, CONF_MQTT_ID CONF_POSITION, CONF_TILT, CONF_STOP, CONF_MQTT_ID, CONF_NAME
from esphome.core import CORE, coroutine from esphome.core import CORE, coroutine, coroutine_with_priority
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
@ -24,7 +25,7 @@ COVER_STATES = {
'OPEN': COVER_OPEN, 'OPEN': COVER_OPEN,
'CLOSED': COVER_CLOSED, 'CLOSED': COVER_CLOSED,
} }
validate_cover_state = cv.one_of(*COVER_STATES, upper=True) validate_cover_state = cv.enum(COVER_STATES, upper=True)
CoverOperation = cover_ns.enum('CoverOperation') CoverOperation = cover_ns.enum('CoverOperation')
COVER_OPERATIONS = { COVER_OPERATIONS = {
@ -32,20 +33,20 @@ COVER_OPERATIONS = {
'OPENING': CoverOperation.COVER_OPERATION_OPENING, 'OPENING': CoverOperation.COVER_OPERATION_OPENING,
'CLOSING': CoverOperation.COVER_OPERATION_CLOSING, 'CLOSING': CoverOperation.COVER_OPERATION_CLOSING,
} }
validate_cover_operation = cv.one_of(*COVER_OPERATIONS, upper=True) validate_cover_operation = cv.enum(COVER_OPERATIONS, upper=True)
# Actions # Actions
OpenAction = cover_ns.class_('OpenAction', cg.Action) OpenAction = cover_ns.class_('OpenAction', automation.Action)
CloseAction = cover_ns.class_('CloseAction', cg.Action) CloseAction = cover_ns.class_('CloseAction', automation.Action)
StopAction = cover_ns.class_('StopAction', cg.Action) StopAction = cover_ns.class_('StopAction', automation.Action)
ControlAction = cover_ns.class_('ControlAction', cg.Action) ControlAction = cover_ns.class_('ControlAction', automation.Action)
CoverPublishAction = cover_ns.class_('CoverPublishAction', cg.Action) CoverPublishAction = cover_ns.class_('CoverPublishAction', automation.Action)
CoverIsOpenCondition = cover_ns.class_('CoverIsOpenCondition', Condition) CoverIsOpenCondition = cover_ns.class_('CoverIsOpenCondition', Condition)
CoverIsClosedCondition = cover_ns.class_('CoverIsClosedCondition', Condition) CoverIsClosedCondition = cover_ns.class_('CoverIsClosedCondition', Condition)
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(Cover), cv.GenerateID(): cv.declare_id(Cover),
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTCoverComponent), cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTCoverComponent),
cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True),
# TODO: MQTT topic options # TODO: MQTT topic options
}) })
@ -53,6 +54,7 @@ COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
@coroutine @coroutine
def setup_cover_core_(var, config): def setup_cover_core_(var, config):
cg.add(var.set_name(config[CONF_NAME]))
if CONF_INTERNAL in config: if CONF_INTERNAL in config:
cg.add(var.set_internal(config[CONF_INTERNAL])) cg.add(var.set_internal(config[CONF_INTERNAL]))
if CONF_DEVICE_CLASS in config: if CONF_DEVICE_CLASS in config:
@ -72,65 +74,57 @@ def register_cover(var, config):
COVER_ACTION_SCHEMA = maybe_simple_id({ COVER_ACTION_SCHEMA = maybe_simple_id({
cv.Required(CONF_ID): cv.use_variable_id(Cover), cv.Required(CONF_ID): cv.use_id(Cover),
}) })
@ACTION_REGISTRY.register('cover.open', COVER_ACTION_SCHEMA) @automation.register_action('cover.open', OpenAction, COVER_ACTION_SCHEMA)
def cover_open_to_code(config, action_id, template_arg, args): def cover_open_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = OpenAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
@ACTION_REGISTRY.register('cover.close', COVER_ACTION_SCHEMA) @automation.register_action('cover.close', CloseAction, COVER_ACTION_SCHEMA)
def cover_close_to_code(config, action_id, template_arg, args): def cover_close_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = CloseAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
@ACTION_REGISTRY.register('cover.stop', COVER_ACTION_SCHEMA) @automation.register_action('cover.stop', StopAction, COVER_ACTION_SCHEMA)
def cover_stop_to_code(config, action_id, template_arg, args): def cover_stop_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = StopAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
COVER_CONTROL_ACTION_SCHEMA = cv.Schema({ COVER_CONTROL_ACTION_SCHEMA = cv.Schema({
cv.Required(CONF_ID): cv.use_variable_id(Cover), cv.Required(CONF_ID): cv.use_id(Cover),
cv.Optional(CONF_STOP): cv.templatable(cv.boolean), cv.Optional(CONF_STOP): cv.templatable(cv.boolean),
cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(cv.one_of(*COVER_STATES)), cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(validate_cover_state),
cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.percentage), cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.percentage),
cv.Optional(CONF_TILT): cv.templatable(cv.percentage), cv.Optional(CONF_TILT): cv.templatable(cv.percentage),
}) })
@ACTION_REGISTRY.register('cover.control', COVER_CONTROL_ACTION_SCHEMA) @automation.register_action('cover.control', ControlAction, COVER_CONTROL_ACTION_SCHEMA)
def cover_control_to_code(config, action_id, template_arg, args): def cover_control_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = StopAction.template(template_arg) var = cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
action = cg.Pvariable(action_id, rhs, type=type)
if CONF_STOP in config: if CONF_STOP in config:
template_ = yield cg.templatable(config[CONF_STOP], args, bool) template_ = yield cg.templatable(config[CONF_STOP], args, bool)
cg.add(action.set_stop(template_)) cg.add(var.set_stop(template_))
if CONF_STATE in config: if CONF_STATE in config:
template_ = yield cg.templatable(config[CONF_STATE], args, float, template_ = yield cg.templatable(config[CONF_STATE], args, float)
to_exp=COVER_STATES) cg.add(var.set_position(template_))
cg.add(action.set_position(template_))
if CONF_POSITION in config: if CONF_POSITION in config:
template_ = yield cg.templatable(config[CONF_POSITION], args, float) template_ = yield cg.templatable(config[CONF_POSITION], args, float)
cg.add(action.set_position(template_)) cg.add(var.set_position(template_))
if CONF_TILT in config: if CONF_TILT in config:
template_ = yield cg.templatable(config[CONF_TILT], args, float) template_ = yield cg.templatable(config[CONF_TILT], args, float)
cg.add(action.set_tilt(template_)) cg.add(var.set_tilt(template_))
yield action yield var
@coroutine_with_priority(100.0)
def to_code(config): def to_code(config):
cg.add_define('USE_COVER') cg.add_define('USE_COVER')
cg.add_global(cover_ns.using) cg.add_global(cover_ns.using)

View file

@ -11,10 +11,7 @@ template<typename... Ts> class OpenAction : public Action<Ts...> {
public: public:
explicit OpenAction(Cover *cover) : cover_(cover) {} explicit OpenAction(Cover *cover) : cover_(cover) {}
void play(Ts... x) override { void play(Ts... x) override { this->cover_->open(); }
this->cover_->open();
this->play_next(x...);
}
protected: protected:
Cover *cover_; Cover *cover_;
@ -24,10 +21,7 @@ template<typename... Ts> class CloseAction : public Action<Ts...> {
public: public:
explicit CloseAction(Cover *cover) : cover_(cover) {} explicit CloseAction(Cover *cover) : cover_(cover) {}
void play(Ts... x) override { void play(Ts... x) override { this->cover_->close(); }
this->cover_->close();
this->play_next(x...);
}
protected: protected:
Cover *cover_; Cover *cover_;
@ -37,10 +31,7 @@ template<typename... Ts> class StopAction : public Action<Ts...> {
public: public:
explicit StopAction(Cover *cover) : cover_(cover) {} explicit StopAction(Cover *cover) : cover_(cover) {}
void play(Ts... x) override { void play(Ts... x) override { this->cover_->stop(); }
this->cover_->stop();
this->play_next(x...);
}
protected: protected:
Cover *cover_; Cover *cover_;
@ -59,7 +50,6 @@ template<typename... Ts> class ControlAction : public Action<Ts...> {
if (this->tilt_.has_value()) if (this->tilt_.has_value())
call.set_tilt(this->tilt_.value(x...)); call.set_tilt(this->tilt_.value(x...));
call.perform(); call.perform();
this->play_next(x...);
} }
TEMPLATABLE_VALUE(bool, stop) TEMPLATABLE_VALUE(bool, stop)
@ -81,7 +71,6 @@ template<typename... Ts> class CoverPublishAction : public Action<Ts...> {
if (this->current_operation_.has_value()) if (this->current_operation_.has_value())
this->cover_->current_operation = this->current_operation_.value(x...); this->cover_->current_operation = this->current_operation_.value(x...);
this->cover_->publish_state(); this->cover_->publish_state();
this->play_next(x...);
} }
TEMPLATABLE_VALUE(float, position) TEMPLATABLE_VALUE(float, position)

View file

@ -105,8 +105,8 @@ const char *cover_operation_to_str(CoverOperation op);
*/ */
class Cover : public Nameable { class Cover : public Nameable {
public: public:
explicit Cover(const std::string &name);
explicit Cover(); explicit Cover();
explicit Cover(const std::string &name);
/// The current operation of the cover (idle, opening, closing). /// The current operation of the cover (idle, opening, closing).
CoverOperation current_operation{COVER_OPERATION_IDLE}; CoverOperation current_operation{COVER_OPERATION_IDLE};

View file

@ -9,8 +9,6 @@ namespace cse7766 {
class CSE7766Component : public PollingComponent, public uart::UARTDevice { class CSE7766Component : public PollingComponent, public uart::UARTDevice {
public: public:
CSE7766Component(uint32_t update_interval) : PollingComponent(update_interval) {}
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; } void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; } void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }

View file

@ -1,7 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor, uart from esphome.components import sensor, uart
from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_UPDATE_INTERVAL, CONF_VOLTAGE, \ from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, \
UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT
DEPENDENCIES = ['uart'] DEPENDENCIES = ['uart']
@ -10,18 +10,16 @@ cse7766_ns = cg.esphome_ns.namespace('cse7766')
CSE7766Component = cse7766_ns.class_('CSE7766Component', cg.PollingComponent, uart.UARTDevice) CSE7766Component = cse7766_ns.class_('CSE7766Component', cg.PollingComponent, uart.UARTDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CSE7766Component), cv.GenerateID(): cv.declare_id(CSE7766Component),
cv.Optional(CONF_VOLTAGE): cv.nameable(sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1)), cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1),
cv.Optional(CONF_CURRENT): cv.nameable( cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_FLASH, 2),
sensor.sensor_schema(UNIT_AMPERE, ICON_FLASH, 2)), cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_FLASH, 1),
cv.Optional(CONF_POWER): cv.nameable(sensor.sensor_schema(UNIT_WATT, ICON_FLASH, 1)), }).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA)
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA)
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield uart.register_uart_device(var, config) yield uart.register_uart_device(var, config)

View file

@ -1,16 +1,15 @@
from esphome.components import binary_sensor
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA, CONF_NAME import esphome.config_validation as cv
from esphome.components import binary_sensor
from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA
from .. import custom_ns from .. import custom_ns
CustomBinarySensorConstructor = custom_ns.class_('CustomBinarySensorConstructor') CustomBinarySensorConstructor = custom_ns.class_('CustomBinarySensorConstructor')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomBinarySensorConstructor), cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_BINARY_SENSORS): cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(binary_sensor.BINARY_SENSOR_SCHEMA),
cv.ensure_list(cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA)),
}) })
@ -22,5 +21,4 @@ def to_code(config):
custom = cg.variable(config[CONF_ID], rhs) custom = cg.variable(config[CONF_ID], rhs)
for i, conf in enumerate(config[CONF_BINARY_SENSORS]): for i, conf in enumerate(config[CONF_BINARY_SENSORS]):
rhs = custom.Pget_binary_sensor(i) rhs = custom.Pget_binary_sensor(i)
cg.add(rhs.set_name(conf[CONF_NAME]))
yield binary_sensor.register_binary_sensor(rhs, conf) yield binary_sensor.register_binary_sensor(rhs, conf)

View file

@ -8,22 +8,22 @@ CustomBinaryOutputConstructor = custom_ns.class_('CustomBinaryOutputConstructor'
CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor') CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor')
BINARY_SCHEMA = cv.Schema({ BINARY_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomBinaryOutputConstructor), cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_TYPE): 'binary', cv.Required(CONF_TYPE): 'binary',
cv.Required(CONF_OUTPUTS): cv.Required(CONF_OUTPUTS):
cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({ cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.BinaryOutput), cv.GenerateID(): cv.declare_id(output.BinaryOutput),
})), })),
}) })
FLOAT_SCHEMA = cv.Schema({ FLOAT_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomFloatOutputConstructor), cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_TYPE): 'float', cv.Required(CONF_TYPE): 'float',
cv.Required(CONF_OUTPUTS): cv.Required(CONF_OUTPUTS):
cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({ cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.FloatOutput), cv.GenerateID(): cv.declare_id(output.FloatOutput),
})), })),
}) })

View file

@ -1,17 +1,15 @@
from esphome.components import sensor
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_SENSORS from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_SENSORS
from .. import custom_ns from .. import custom_ns
CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor') CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomSensorConstructor), cv.GenerateID(): cv.declare_id(CustomSensorConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA.extend({ cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA),
cv.GenerateID(): cv.declare_variable_id(sensor.Sensor),
})),
}) })

View file

@ -8,11 +8,11 @@ from .. import custom_ns
CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor') CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomSwitchConstructor), cv.GenerateID(): cv.declare_id(CustomSwitchConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_SWITCHES): cv.Required(CONF_SWITCHES):
cv.ensure_list(switch.SWITCH_SCHEMA.extend({ cv.ensure_list(switch.SWITCH_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(switch.Switch), cv.GenerateID(): cv.declare_id(switch.Switch),
})), })),
}) })

View file

@ -7,11 +7,11 @@ from .. import custom_ns
CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor') CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomTextSensorConstructor), cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Required(CONF_TEXT_SENSORS): cv.Required(CONF_TEXT_SENSORS):
cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({ cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(text_sensor.TextSensor), cv.GenerateID(): cv.declare_id(text_sensor.TextSensor),
})), })),
}) })

View file

@ -7,10 +7,10 @@ CustomComponentConstructor = custom_component_ns.class_('CustomComponentConstruc
MULTI_CONF = True MULTI_CONF = True
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor), cv.GenerateID(): cv.declare_id(CustomComponentConstructor),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
cv.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({ cv.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(cg.Component) cv.GenerateID(): cv.declare_id(cg.Component)
}).extend(cv.COMPONENT_SCHEMA)), }).extend(cv.COMPONENT_SCHEMA)),
}) })

View file

@ -9,12 +9,10 @@ namespace cwww {
class CWWWLightOutput : public light::LightOutput { class CWWWLightOutput : public light::LightOutput {
public: public:
CWWWLightOutput(output::FloatOutput *cold_white, output::FloatOutput *warm_white, float cold_white_temperature, void set_cold_white(output::FloatOutput *cold_white) { cold_white_ = cold_white; }
float warm_white_temperature) void set_warm_white(output::FloatOutput *warm_white) { warm_white_ = warm_white; }
: cold_white_(cold_white), void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; }
warm_white_(warm_white), void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; }
cold_white_temperature_(cold_white_temperature),
warm_white_temperature_(warm_white_temperature) {}
light::LightTraits get_traits() override { light::LightTraits get_traits() override {
auto traits = light::LightTraits(); auto traits = light::LightTraits();
traits.set_supports_brightness(true); traits.set_supports_brightness(true);

View file

@ -7,19 +7,22 @@ from esphome.const import CONF_OUTPUT_ID, CONF_COLD_WHITE, CONF_WARM_WHITE, \
cwww_ns = cg.esphome_ns.namespace('cwww') cwww_ns = cg.esphome_ns.namespace('cwww')
CWWWLightOutput = cwww_ns.class_('CWWWLightOutput', light.LightOutput) CWWWLightOutput = cwww_ns.class_('CWWWLightOutput', light.LightOutput)
CONFIG_SCHEMA = cv.nameable(light.RGB_LIGHT_SCHEMA.extend({ CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(CWWWLightOutput), cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CWWWLightOutput),
cv.Required(CONF_COLD_WHITE): cv.use_variable_id(output.FloatOutput), cv.Required(CONF_COLD_WHITE): cv.use_id(output.FloatOutput),
cv.Required(CONF_WARM_WHITE): cv.use_variable_id(output.FloatOutput), cv.Required(CONF_WARM_WHITE): cv.use_id(output.FloatOutput),
cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature, cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature, cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature,
})) })
def to_code(config): def to_code(config):
cwhite = yield cg.get_variable(config[CONF_COLD_WHITE]) var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
wwhite = yield cg.get_variable(config[CONF_WARM_WHITE])
var = cg.new_Pvariable(config[CONF_OUTPUT_ID], cwhite, wwhite,
config[CONF_COLD_WHITE_COLOR_TEMPERATURE],
config[CONF_WARM_WHITE_COLOR_TEMPERATURE])
yield light.register_light(var, config) yield light.register_light(var, config)
cwhite = yield cg.get_variable(config[CONF_COLD_WHITE])
cg.add(var.set_cold_white(cwhite))
cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))
wwhite = yield cg.get_variable(config[CONF_WARM_WHITE])
cg.add(var.set_warm_white(wwhite))
cg.add(var.set_warm_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE]))

View file

@ -1,7 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import pins from esphome import pins
from esphome.const import CONF_ID, CONF_PIN, CONF_UPDATE_INTERVAL from esphome.const import CONF_ID, CONF_PIN
MULTI_CONF = True MULTI_CONF = True
AUTO_LOAD = ['sensor'] AUTO_LOAD = ['sensor']
@ -12,15 +12,14 @@ DallasComponent = dallas_ns.class_('DallasComponent', cg.PollingComponent)
ESPOneWire = dallas_ns.class_('ESPOneWire') ESPOneWire = dallas_ns.class_('ESPOneWire')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DallasComponent), cv.GenerateID(): cv.declare_id(DallasComponent),
cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_variable_id(ESPOneWire), cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_id(ESPOneWire),
cv.Required(CONF_PIN): pins.gpio_input_pin_schema, cv.Required(CONF_PIN): pins.gpio_input_pin_schema,
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s'))
}).extend(cv.COMPONENT_SCHEMA)
def to_code(config): def to_code(config):
pin = yield cg.gpio_pin_expression(config[CONF_PIN]) pin = yield cg.gpio_pin_expression(config[CONF_PIN])
one_wire = cg.new_Pvariable(config[CONF_ONE_WIRE_ID], pin) one_wire = cg.new_Pvariable(config[CONF_ONE_WIRE_ID], pin)
var = cg.new_Pvariable(config[CONF_ID], one_wire, config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID], one_wire)
yield cg.register_component(var, config) yield cg.register_component(var, config)

View file

@ -95,15 +95,13 @@ void DallasComponent::dump_config() {
} }
} }
DallasTemperatureSensor *DallasComponent::get_sensor_by_address(const std::string &name, uint64_t address, DallasTemperatureSensor *DallasComponent::get_sensor_by_address(uint64_t address, uint8_t resolution) {
uint8_t resolution) { auto s = new DallasTemperatureSensor(address, resolution, this);
auto s = new DallasTemperatureSensor(name, address, resolution, this);
this->sensors_.push_back(s); this->sensors_.push_back(s);
return s; return s;
} }
DallasTemperatureSensor *DallasComponent::get_sensor_by_index(const std::string &name, uint8_t index, DallasTemperatureSensor *DallasComponent::get_sensor_by_index(uint8_t index, uint8_t resolution) {
uint8_t resolution) { auto s = this->get_sensor_by_address(0, resolution);
auto s = this->get_sensor_by_address(name, 0, resolution);
s->set_index(index); s->set_index(index);
return s; return s;
} }
@ -148,12 +146,10 @@ void DallasComponent::update() {
}); });
} }
} }
DallasComponent::DallasComponent(ESPOneWire *one_wire, uint32_t update_interval) DallasComponent::DallasComponent(ESPOneWire *one_wire) : one_wire_(one_wire) {}
: PollingComponent(update_interval), one_wire_(one_wire) {}
DallasTemperatureSensor::DallasTemperatureSensor(const std::string &name, uint64_t address, uint8_t resolution, DallasTemperatureSensor::DallasTemperatureSensor(uint64_t address, uint8_t resolution, DallasComponent *parent)
DallasComponent *parent) : parent_(parent) {
: sensor::Sensor(name), parent_(parent) {
this->set_address(address); this->set_address(address);
this->set_resolution(resolution); this->set_resolution(resolution);
} }

View file

@ -11,10 +11,10 @@ class DallasTemperatureSensor;
class DallasComponent : public PollingComponent { class DallasComponent : public PollingComponent {
public: public:
explicit DallasComponent(ESPOneWire *one_wire, uint32_t update_interval); explicit DallasComponent(ESPOneWire *one_wire);
DallasTemperatureSensor *get_sensor_by_address(const std::string &name, uint64_t address, uint8_t resolution); DallasTemperatureSensor *get_sensor_by_address(uint64_t address, uint8_t resolution);
DallasTemperatureSensor *get_sensor_by_index(const std::string &name, uint8_t index, uint8_t resolution); DallasTemperatureSensor *get_sensor_by_index(uint8_t index, uint8_t resolution);
void setup() override; void setup() override;
void dump_config() override; void dump_config() override;
@ -33,7 +33,7 @@ class DallasComponent : public PollingComponent {
/// Internal class that helps us create multiple sensors for one Dallas hub. /// Internal class that helps us create multiple sensors for one Dallas hub.
class DallasTemperatureSensor : public sensor::Sensor { class DallasTemperatureSensor : public sensor::Sensor {
public: public:
DallasTemperatureSensor(const std::string &name, uint64_t address, uint8_t resolution, DallasComponent *parent); DallasTemperatureSensor(uint64_t address, uint8_t resolution, DallasComponent *parent);
/// Helper to get a pointer to the address as uint8_t. /// Helper to get a pointer to the address as uint8_t.
uint8_t *get_address8(); uint8_t *get_address8();

View file

@ -1,24 +1,19 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor
from esphome.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \ from esphome.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_RESOLUTION, UNIT_CELSIUS, \
CONF_RESOLUTION, CONF_UNIT_OF_MEASUREMENT, UNIT_CELSIUS, CONF_ICON, ICON_THERMOMETER, \ ICON_THERMOMETER, CONF_ID
CONF_ACCURACY_DECIMALS, CONF_ID
from . import DallasComponent, dallas_ns from . import DallasComponent, dallas_ns
DallasTemperatureSensor = dallas_ns.class_('DallasTemperatureSensor', sensor.Sensor) DallasTemperatureSensor = dallas_ns.class_('DallasTemperatureSensor', sensor.Sensor)
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = cv.All(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
cv.GenerateID(): cv.declare_variable_id(DallasTemperatureSensor), cv.GenerateID(): cv.declare_id(DallasTemperatureSensor),
cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent), cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent),
cv.Optional(CONF_ADDRESS): cv.hex_int, cv.Optional(CONF_ADDRESS): cv.hex_int,
cv.Optional(CONF_INDEX): cv.positive_int, cv.Optional(CONF_INDEX): cv.positive_int,
cv.Optional(CONF_RESOLUTION, default=12): cv.All(cv.int_, cv.Range(min=9, max=12)), cv.Optional(CONF_RESOLUTION, default=12): cv.All(cv.int_, cv.Range(min=9, max=12)),
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_CELSIUS): sensor.unit_of_measurement,
cv.Optional(CONF_ICON, default=ICON_THERMOMETER): sensor.icon,
cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals,
}), cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX)) }), cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX))
@ -26,9 +21,8 @@ def to_code(config):
hub = yield cg.get_variable(config[CONF_DALLAS_ID]) hub = yield cg.get_variable(config[CONF_DALLAS_ID])
if CONF_ADDRESS in config: if CONF_ADDRESS in config:
address = config[CONF_ADDRESS] address = config[CONF_ADDRESS]
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, config.get(CONF_RESOLUTION)) rhs = hub.Pget_sensor_by_address(address, config.get(CONF_RESOLUTION))
else: else:
rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX], rhs = hub.Pget_sensor_by_index(config[CONF_INDEX], config.get(CONF_RESOLUTION))
config.get(CONF_RESOLUTION))
var = cg.Pvariable(config[CONF_ID], rhs) var = cg.Pvariable(config[CONF_ID], rhs)
yield sensor.register_sensor(var, config) yield sensor.register_sensor(var, config)

View file

@ -7,11 +7,10 @@ DEPENDENCIES = ['logger']
debug_ns = cg.esphome_ns.namespace('debug') debug_ns = cg.esphome_ns.namespace('debug')
DebugComponent = debug_ns.class_('DebugComponent', cg.Component) DebugComponent = debug_ns.class_('DebugComponent', cg.Component)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DebugComponent), cv.GenerateID(): cv.declare_id(DebugComponent),
}).extend(cv.COMPONENT_SCHEMA) }).extend(cv.COMPONENT_SCHEMA)
def to_code(config): def to_code(config):
rhs = DebugComponent.new() var = cg.new_Pvariable(config[CONF_ID])
var = cg.Pvariable(config[CONF_ID], rhs)
yield cg.register_component(var, config) yield cg.register_component(var, config)

View file

@ -1,7 +1,7 @@
from esphome import pins
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.automation import ACTION_REGISTRY, maybe_simple_id import esphome.config_validation as cv
from esphome import pins, automation
from esphome.automation import maybe_simple_id
from esphome.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_CYCLES, \ from esphome.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_CYCLES, \
CONF_RUN_DURATION, CONF_SLEEP_DURATION, CONF_WAKEUP_PIN CONF_RUN_DURATION, CONF_SLEEP_DURATION, CONF_WAKEUP_PIN
@ -16,8 +16,8 @@ def validate_pin_number(value):
deep_sleep_ns = cg.esphome_ns.namespace('deep_sleep') deep_sleep_ns = cg.esphome_ns.namespace('deep_sleep')
DeepSleepComponent = deep_sleep_ns.class_('DeepSleepComponent', cg.Component) DeepSleepComponent = deep_sleep_ns.class_('DeepSleepComponent', cg.Component)
EnterDeepSleepAction = deep_sleep_ns.class_('EnterDeepSleepAction', cg.Action) EnterDeepSleepAction = deep_sleep_ns.class_('EnterDeepSleepAction', automation.Action)
PreventDeepSleepAction = deep_sleep_ns.class_('PreventDeepSleepAction', cg.Action) PreventDeepSleepAction = deep_sleep_ns.class_('PreventDeepSleepAction', automation.Action)
WakeupPinMode = deep_sleep_ns.enum('WakeupPinMode') WakeupPinMode = deep_sleep_ns.enum('WakeupPinMode')
WAKEUP_PIN_MODES = { WAKEUP_PIN_MODES = {
@ -37,17 +37,17 @@ CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup' CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup'
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent), cv.GenerateID(): cv.declare_id(DeepSleepComponent),
cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds, cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
cv.Optional(CONF_WAKEUP_PIN): cv.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema, cv.Optional(CONF_WAKEUP_PIN): cv.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
validate_pin_number), validate_pin_number),
cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All(cv.only_on_esp32, cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All(cv.only_on_esp32,
cv.one_of(*WAKEUP_PIN_MODES), upper=True), cv.enum(WAKEUP_PIN_MODES), upper=True),
cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All(cv.only_on_esp32, cv.Schema({ cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All(cv.only_on_esp32, cv.Schema({
cv.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number), cv.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number),
cv.Required(CONF_MODE): cv.one_of(*EXT1_WAKEUP_MODES, upper=True), cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True),
})), })),
cv.Optional(CONF_RUN_CYCLES): cv.invalid("The run_cycles option has been removed in 1.11.0 as " cv.Optional(CONF_RUN_CYCLES): cv.invalid("The run_cycles option has been removed in 1.11.0 as "
@ -66,7 +66,7 @@ def to_code(config):
pin = yield cg.gpio_pin_expression(config[CONF_WAKEUP_PIN]) pin = yield cg.gpio_pin_expression(config[CONF_WAKEUP_PIN])
cg.add(var.set_wakeup_pin(pin)) cg.add(var.set_wakeup_pin(pin))
if CONF_WAKEUP_PIN_MODE in config: if CONF_WAKEUP_PIN_MODE in config:
cg.add(var.set_wakeup_pin_mode(WAKEUP_PIN_MODES[config[CONF_WAKEUP_PIN_MODE]])) cg.add(var.set_wakeup_pin_mode(config[CONF_WAKEUP_PIN_MODE]))
if CONF_RUN_DURATION in config: if CONF_RUN_DURATION in config:
cg.add(var.set_run_duration(config[CONF_RUN_DURATION])) cg.add(var.set_run_duration(config[CONF_RUN_DURATION]))
@ -78,7 +78,7 @@ def to_code(config):
struct = cg.StructInitializer( struct = cg.StructInitializer(
Ext1Wakeup, Ext1Wakeup,
('mask', mask), ('mask', mask),
('wakeup_mode', EXT1_WAKEUP_MODES[conf[CONF_MODE]]) ('wakeup_mode', conf[CONF_MODE])
) )
cg.add(var.set_ext1_wakeup(struct)) cg.add(var.set_ext1_wakeup(struct))
@ -86,21 +86,17 @@ def to_code(config):
DEEP_SLEEP_ACTION_SCHEMA = maybe_simple_id({ DEEP_SLEEP_ACTION_SCHEMA = maybe_simple_id({
cv.Required(CONF_ID): cv.use_variable_id(DeepSleepComponent), cv.GenerateID(): cv.use_id(DeepSleepComponent),
}) })
@ACTION_REGISTRY.register('deep_sleep.enter', DEEP_SLEEP_ACTION_SCHEMA) @automation.register_action('deep_sleep.enter', EnterDeepSleepAction, DEEP_SLEEP_ACTION_SCHEMA)
def deep_sleep_enter_to_code(config, action_id, template_arg, args): def deep_sleep_enter_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = EnterDeepSleepAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)
@ACTION_REGISTRY.register('deep_sleep.prevent', DEEP_SLEEP_ACTION_SCHEMA) @automation.register_action('deep_sleep.prevent', PreventDeepSleepAction, DEEP_SLEEP_ACTION_SCHEMA)
def deep_sleep_prevent_to_code(config, action_id, template_arg, args): def deep_sleep_prevent_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = PreventDeepSleepAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
rhs = type.new(var)
yield cg.Pvariable(action_id, rhs, type=type)

View file

@ -85,10 +85,7 @@ template<typename... Ts> class EnterDeepSleepAction : public Action<Ts...> {
public: public:
EnterDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {} EnterDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {}
void play(Ts... x) override { void play(Ts... x) override { this->deep_sleep_->begin_sleep(true); }
this->deep_sleep_->begin_sleep(true);
this->play_next(x...);
}
protected: protected:
DeepSleepComponent *deep_sleep_; DeepSleepComponent *deep_sleep_;
@ -98,10 +95,7 @@ template<typename... Ts> class PreventDeepSleepAction : public Action<Ts...> {
public: public:
PreventDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {} PreventDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {}
void play(Ts... x) override { void play(Ts... x) override { this->deep_sleep_->prevent_deep_sleep(); }
this->deep_sleep_->prevent_deep_sleep();
this->play_next(x...);
}
protected: protected:
DeepSleepComponent *deep_sleep_; DeepSleepComponent *deep_sleep_;

View file

@ -7,12 +7,6 @@ namespace dht {
static const char *TAG = "dht"; static const char *TAG = "dht";
DHT::DHT(const std::string &temperature_name, const std::string &humidity_name, GPIOPin *pin, uint32_t update_interval)
: PollingComponent(update_interval),
pin_(pin),
temperature_sensor_(new sensor::Sensor(temperature_name)),
humidity_sensor_(new sensor::Sensor(humidity_name)) {}
void DHT::setup() { void DHT::setup() {
ESP_LOGCONFIG(TAG, "Setting up DHT..."); ESP_LOGCONFIG(TAG, "Setting up DHT...");
this->pin_->digital_write(true); this->pin_->digital_write(true);
@ -71,8 +65,6 @@ void DHT::set_dht_model(DHTModel model) {
this->model_ = model; this->model_ = model;
this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT; this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT;
} }
sensor::Sensor *DHT::get_temperature_sensor() const { return this->temperature_sensor_; }
sensor::Sensor *DHT::get_humidity_sensor() const { return this->humidity_sensor_; }
bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_errors) { bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_errors) {
*humidity = NAN; *humidity = NAN;
*temperature = NAN; *temperature = NAN;

View file

@ -18,13 +18,6 @@ enum DHTModel {
/// Component for reading temperature/humidity measurements from DHT11/DHT22 sensors. /// Component for reading temperature/humidity measurements from DHT11/DHT22 sensors.
class DHT : public PollingComponent { class DHT : public PollingComponent {
public: public:
/** Construct a DHTComponent.
*
* @param pin The pin which DHT sensor is connected to.
* @param update_interval The interval in ms the sensor should be checked.
*/
DHT(const std::string &temperature_name, const std::string &humidity_name, GPIOPin *pin, uint32_t update_interval);
/** Manually select the DHT model. /** Manually select the DHT model.
* *
* Valid values are: * Valid values are:
@ -40,10 +33,10 @@ class DHT : public PollingComponent {
*/ */
void set_dht_model(DHTModel model); void set_dht_model(DHTModel model);
// ========== INTERNAL METHODS ========== void set_pin(GPIOPin *pin) { pin_ = pin; }
// (In most use cases you won't need these) void set_model(DHTModel model) { model_ = model; }
sensor::Sensor *get_temperature_sensor() const; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
sensor::Sensor *get_humidity_sensor() const; void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
/// Set up the pins and check connection. /// Set up the pins and check connection.
void setup() override; void setup() override;
@ -59,8 +52,8 @@ class DHT : public PollingComponent {
GPIOPin *pin_; GPIOPin *pin_;
DHTModel model_{DHT_MODEL_AUTO_DETECT}; DHTModel model_{DHT_MODEL_AUTO_DETECT};
bool is_auto_detect_{false}; bool is_auto_detect_{false};
sensor::Sensor *temperature_sensor_; sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_; sensor::Sensor *humidity_sensor_{nullptr};
}; };
} // namespace dht } // namespace dht

View file

@ -1,11 +1,10 @@
from esphome.components import sensor
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_NAME, \ import esphome.config_validation as cv
CONF_PIN, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, CONF_ACCURACY_DECIMALS, CONF_ICON, \ from esphome import pins
ICON_THERMOMETER, CONF_UNIT_OF_MEASUREMENT, UNIT_CELSIUS, ICON_WATER_PERCENT, UNIT_PERCENT from esphome.components import sensor
from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_PIN, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL, ICON_THERMOMETER, UNIT_CELSIUS, ICON_WATER_PERCENT, UNIT_PERCENT
from esphome.cpp_helpers import gpio_pin_expression from esphome.cpp_helpers import gpio_pin_expression
from esphome.pins import gpio_input_pullup_pin_schema
dht_ns = cg.esphome_ns.namespace('dht') dht_ns = cg.esphome_ns.namespace('dht')
DHTModel = dht_ns.enum('DHTModel') DHTModel = dht_ns.enum('DHTModel')
@ -20,31 +19,27 @@ DHT_MODELS = {
DHT = dht_ns.class_('DHT', cg.PollingComponent) DHT = dht_ns.class_('DHT', cg.PollingComponent)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DHT), cv.GenerateID(): cv.declare_id(DHT),
cv.Required(CONF_PIN): gpio_input_pullup_pin_schema, cv.Required(CONF_PIN): pins.gpio_input_pin_schema,
cv.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA.extend({ cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1),
cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals, cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 0),
cv.Optional(CONF_ICON, default=ICON_THERMOMETER): sensor.icon, cv.Optional(CONF_MODEL, default='auto detect'): cv.enum(DHT_MODELS, upper=True, space='_'),
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_CELSIUS): sensor.unit_of_measurement,
})),
cv.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA.extend({
cv.Optional(CONF_ACCURACY_DECIMALS, default=0): sensor.accuracy_decimals,
cv.Optional(CONF_ICON, default=ICON_WATER_PERCENT): sensor.icon,
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_PERCENT): sensor.unit_of_measurement,
})),
cv.Optional(CONF_MODEL, default='auto detect'): cv.one_of(*DHT_MODELS, upper=True, space='_'),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA) }).extend(cv.polling_component_schema('60s'))
def to_code(config): def to_code(config):
pin = yield gpio_pin_expression(config[CONF_PIN]) var = cg.new_Pvariable(config[CONF_ID])
rhs = DHT.new(config[CONF_TEMPERATURE][CONF_NAME], yield cg.register_component(var, config)
config[CONF_HUMIDITY][CONF_NAME],
pin, config[CONF_UPDATE_INTERVAL])
dht = cg.Pvariable(config[CONF_ID], rhs)
yield cg.register_component(dht, config)
yield sensor.register_sensor(dht.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
yield sensor.register_sensor(dht.Pget_humidity_sensor(), config[CONF_HUMIDITY])
cg.add(dht.set_dht_model(DHT_MODELS[config[CONF_MODEL]])) pin = yield gpio_pin_expression(config[CONF_PIN])
cg.add(var.set_pin(pin))
if CONF_TEMPERATURE in config:
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
cg.add(var.set_temperature_sensor(sens))
if CONF_HUMIDITY in config:
sens = yield sensor.new_sensor(config[CONF_HUMIDITY])
cg.add(var.set_humidity_sensor(sens))
cg.add(var.set_dht_model(config[CONF_MODEL]))

View file

@ -9,8 +9,6 @@ namespace dht12 {
class DHT12Component : public PollingComponent, public i2c::I2CDevice { class DHT12Component : public PollingComponent, public i2c::I2CDevice {
public: public:
DHT12Component(uint32_t update_interval) : PollingComponent(update_interval) {}
void setup() override; void setup() override;
void dump_config() override; void dump_config() override;
float get_setup_priority() const override; float get_setup_priority() const override;

View file

@ -2,7 +2,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import i2c, sensor from esphome.components import i2c, sensor
from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, \ from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
@ -10,17 +10,14 @@ dht12_ns = cg.esphome_ns.namespace('dht12')
DHT12Component = dht12_ns.class_('DHT12Component', cg.PollingComponent, i2c.I2CDevice) DHT12Component = dht12_ns.class_('DHT12Component', cg.PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DHT12Component), cv.GenerateID(): cv.declare_id(DHT12Component),
cv.Optional(CONF_TEMPERATURE): cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1),
cv.nameable(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1)), cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1),
cv.Optional(CONF_HUMIDITY): }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5C))
cv.nameable(sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1)),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x5C))
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield i2c.register_i2c_device(var, config) yield i2c.register_i2c_device(var, config)

View file

@ -1,10 +1,10 @@
# coding=utf-8 # coding=utf-8
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome import core from esphome import core, automation
from esphome.automation import ACTION_REGISTRY, maybe_simple_id from esphome.automation import maybe_simple_id
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_ROTATION, CONF_UPDATE_INTERVAL from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_ROTATION, CONF_UPDATE_INTERVAL
from esphome.core import coroutine from esphome.core import coroutine, coroutine_with_priority
IS_PLATFORM_COMPONENT = True IS_PLATFORM_COMPONENT = True
@ -13,9 +13,9 @@ DisplayBuffer = display_ns.class_('DisplayBuffer')
DisplayPage = display_ns.class_('DisplayPage') DisplayPage = display_ns.class_('DisplayPage')
DisplayPagePtr = DisplayPage.operator('ptr') DisplayPagePtr = DisplayPage.operator('ptr')
DisplayBufferRef = DisplayBuffer.operator('ref') DisplayBufferRef = DisplayBuffer.operator('ref')
DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', cg.Action) DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', automation.Action)
DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', cg.Action) DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', automation.Action)
DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', cg.Action) DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', automation.Action)
DISPLAY_ROTATIONS = { DISPLAY_ROTATIONS = {
0: display_ns.DISPLAY_ROTATION_0_DEGREES, 0: display_ns.DISPLAY_ROTATION_0_DEGREES,
@ -29,11 +29,7 @@ def validate_rotation(value):
value = cv.string(value) value = cv.string(value)
if value.endswith(u"°"): if value.endswith(u"°"):
value = value[:-1] value = value[:-1]
try: return cv.enum(DISPLAY_ROTATIONS, int=True)(value)
value = int(value)
except ValueError:
raise cv.Invalid(u"Expected integer for rotation")
return cv.one_of(*DISPLAY_ROTATIONS)(value)
BASIC_DISPLAY_SCHEMA = cv.Schema({ BASIC_DISPLAY_SCHEMA = cv.Schema({
@ -44,7 +40,7 @@ BASIC_DISPLAY_SCHEMA = cv.Schema({
FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend({ FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend({
cv.Optional(CONF_ROTATION): validate_rotation, cv.Optional(CONF_ROTATION): validate_rotation,
cv.Optional(CONF_PAGES): cv.All(cv.ensure_list({ cv.Optional(CONF_PAGES): cv.All(cv.ensure_list({
cv.GenerateID(): cv.declare_variable_id(DisplayPage), cv.GenerateID(): cv.declare_id(DisplayPage),
cv.Required(CONF_LAMBDA): cv.lambda_, cv.Required(CONF_LAMBDA): cv.lambda_,
}), cv.Length(min=1)), }), cv.Length(min=1)),
}) })
@ -71,38 +67,37 @@ def register_display(var, config):
yield setup_display_core_(var, config) yield setup_display_core_(var, config)
@ACTION_REGISTRY.register('display.page.show', maybe_simple_id({ @automation.register_action('display.page.show', DisplayPageShowAction, maybe_simple_id({
cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayPage)), cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayPage)),
})) }))
def display_page_show_to_code(config, action_id, template_arg, args): def display_page_show_to_code(config, action_id, template_arg, args):
type = DisplayPageShowAction.template(template_arg) var = cg.new_Pvariable(action_id, template_arg)
action = cg.Pvariable(action_id, type.new(), type=type)
if isinstance(config[CONF_ID], core.Lambda): if isinstance(config[CONF_ID], core.Lambda):
template_ = yield cg.templatable(config[CONF_ID], args, DisplayPagePtr) template_ = yield cg.templatable(config[CONF_ID], args, DisplayPagePtr)
cg.add(action.set_page(template_)) cg.add(var.set_page(template_))
else: else:
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
cg.add(action.set_page(var)) cg.add(var.set_page(paren))
yield action yield var
@ACTION_REGISTRY.register('display.page.show_next', maybe_simple_id({ @automation.register_action('display.page.show_next', DisplayPageShowNextAction, maybe_simple_id({
cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)),
})) }))
def display_page_show_next_to_code(config, action_id, template_arg, args): def display_page_show_next_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = DisplayPageShowNextAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
yield cg.Pvariable(action_id, type.new(var), type=type)
@ACTION_REGISTRY.register('display.page.show_previous', maybe_simple_id({ @automation.register_action('display.page.show_previous', DisplayPageShowPrevAction,
cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), maybe_simple_id({
cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)),
})) }))
def display_page_show_previous_to_code(config, action_id, template_arg, args): def display_page_show_previous_to_code(config, action_id, template_arg, args):
var = yield cg.get_variable(config[CONF_ID]) paren = yield cg.get_variable(config[CONF_ID])
type = DisplayPageShowPrevAction.template(template_arg) yield cg.new_Pvariable(action_id, template_arg, paren)
yield cg.Pvariable(action_id, type.new(var), type=type)
@coroutine_with_priority(100.0)
def to_code(config): def to_code(config):
cg.add_global(display_ns.using) cg.add_global(display_ns.using)

View file

@ -396,17 +396,13 @@ template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
if (page != nullptr) { if (page != nullptr) {
page->show(); page->show();
} }
this->play_next(x...);
} }
}; };
template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> { template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> {
public: public:
DisplayPageShowNextAction(DisplayBuffer *buffer) : buffer_(buffer) {} DisplayPageShowNextAction(DisplayBuffer *buffer) : buffer_(buffer) {}
void play(Ts... x) override { void play(Ts... x) override { this->buffer_->show_next_page(); }
this->buffer_->show_next_page();
this->play_next(x...);
}
protected: protected:
DisplayBuffer *buffer_; DisplayBuffer *buffer_;
@ -415,10 +411,7 @@ template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...>
template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> { template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> {
public: public:
DisplayPageShowPrevAction(DisplayBuffer *buffer) : buffer_(buffer) {} DisplayPageShowPrevAction(DisplayBuffer *buffer) : buffer_(buffer) {}
void play(Ts... x) override { void play(Ts... x) override { this->buffer_->show_prev_page(); }
this->buffer_->show_prev_page();
this->play_next(x...);
}
protected: protected:
DisplayBuffer *buffer_; DisplayBuffer *buffer_;

View file

@ -17,10 +17,9 @@ struct DutyCycleSensorStore {
static void gpio_intr(DutyCycleSensorStore *arg); static void gpio_intr(DutyCycleSensorStore *arg);
}; };
class DutyCycleSensor : public sensor::PollingSensorComponent { class DutyCycleSensor : public sensor::Sensor, public PollingComponent {
public: public:
DutyCycleSensor(const std::string &name, uint32_t update_interval, GPIOPin *pin) void set_pin(GPIOPin *pin) { pin_ = pin; }
: PollingSensorComponent(name, update_interval), pin_(pin) {}
void setup() override; void setup() override;
float get_setup_priority() const override; float get_setup_priority() const override;

View file

@ -1,23 +1,23 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins from esphome import pins
from esphome.components import sensor from esphome.components import sensor
import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_PIN, UNIT_PERCENT, ICON_PERCENT
import esphome.codegen as cg
from esphome.const import CONF_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL, UNIT_PERCENT, \
ICON_PERCENT
duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle') duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle')
DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.PollingSensorComponent) DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.PollingSensorComponent)
CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({
cv.GenerateID(): cv.declare_variable_id(DutyCycleSensor), cv.GenerateID(): cv.declare_id(DutyCycleSensor),
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema, cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema,
pins.validate_has_interrupt), pins.validate_has_interrupt),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, }).extend(cv.polling_component_schema('60s'))
}).extend(cv.COMPONENT_SCHEMA))
def to_code(config): def to_code(config):
pin = yield cg.gpio_pin_expression(config[CONF_PIN]) var = cg.new_Pvariable(config[CONF_ID])
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL], pin)
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield sensor.register_sensor(var, config) yield sensor.register_sensor(var, config)
pin = yield cg.gpio_pin_expression(config[CONF_PIN])
cg.add(var.set_pin(pin))

View file

@ -1,32 +1,32 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation from esphome import automation
from esphome.components import binary_sensor, cover from esphome.components import binary_sensor, cover
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, \ from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, \
CONF_CLOSE_ENDSTOP, CONF_ID, CONF_NAME, CONF_OPEN_ACTION, CONF_OPEN_DURATION, \ CONF_CLOSE_ENDSTOP, CONF_ID, CONF_OPEN_ACTION, CONF_OPEN_DURATION, \
CONF_OPEN_ENDSTOP, CONF_STOP_ACTION, CONF_MAX_DURATION CONF_OPEN_ENDSTOP, CONF_STOP_ACTION, CONF_MAX_DURATION
endstop_ns = cg.esphome_ns.namespace('endstop') endstop_ns = cg.esphome_ns.namespace('endstop')
EndstopCover = endstop_ns.class_('EndstopCover', cover.Cover, cg.Component) EndstopCover = endstop_ns.class_('EndstopCover', cover.Cover, cg.Component)
CONFIG_SCHEMA = cv.nameable(cover.COVER_SCHEMA.extend({ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(EndstopCover), cv.GenerateID(): cv.declare_id(EndstopCover),
cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True),
cv.Required(CONF_OPEN_ENDSTOP): cv.use_variable_id(binary_sensor.BinarySensor), cv.Required(CONF_OPEN_ENDSTOP): cv.use_id(binary_sensor.BinarySensor),
cv.Required(CONF_OPEN_ACTION): automation.validate_automation(single=True), cv.Required(CONF_OPEN_ACTION): automation.validate_automation(single=True),
cv.Required(CONF_OPEN_DURATION): cv.positive_time_period_milliseconds, cv.Required(CONF_OPEN_DURATION): cv.positive_time_period_milliseconds,
cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True), cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
cv.Required(CONF_CLOSE_ENDSTOP): cv.use_variable_id(binary_sensor.BinarySensor), cv.Required(CONF_CLOSE_ENDSTOP): cv.use_id(binary_sensor.BinarySensor),
cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds, cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds,
cv.Optional(CONF_MAX_DURATION): cv.positive_time_period_milliseconds, cv.Optional(CONF_MAX_DURATION): cv.positive_time_period_milliseconds,
}).extend(cv.COMPONENT_SCHEMA)) }).extend(cv.COMPONENT_SCHEMA)
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME]) var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config) yield cg.register_component(var, config)
yield cover.register_cover(var, config) yield cover.register_cover(var, config)

View file

@ -10,8 +10,6 @@ namespace endstop {
class EndstopCover : public cover::Cover, public Component { class EndstopCover : public cover::Cover, public Component {
public: public:
EndstopCover(const std::string &name) : cover::Cover(name) {}
void setup() override; void setup() override;
void loop() override; void loop() override;
void dump_config() override; void dump_config() override;

View file

@ -12,7 +12,7 @@ CONF_MAJOR = 'major'
CONF_MINOR = 'minor' CONF_MINOR = 'minor'
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32BLEBeacon), cv.GenerateID(): cv.declare_id(ESP32BLEBeacon),
cv.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True), cv.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True),
cv.Required(CONF_UUID): cv.uuid, cv.Required(CONF_UUID): cv.uuid,
cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t,

View file

@ -11,12 +11,12 @@ ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component)
ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener') ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener')
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker), cv.GenerateID(): cv.declare_id(ESP32BLETracker),
cv.Optional(CONF_SCAN_INTERVAL, default='300s'): cv.positive_time_period_seconds, cv.Optional(CONF_SCAN_INTERVAL, default='300s'): cv.positive_time_period_seconds,
}).extend(cv.COMPONENT_SCHEMA) }).extend(cv.COMPONENT_SCHEMA)
ESP_BLE_DEVICE_SCHEMA = cv.Schema({ ESP_BLE_DEVICE_SCHEMA = cv.Schema({
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker), cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker),
}) })

View file

@ -58,7 +58,7 @@ CONF_TEST_PATTERN = 'test_pattern'
camera_range_param = cv.All(cv.int_, cv.Range(min=-2, max=2)) camera_range_param = cv.All(cv.int_, cv.Range(min=-2, max=2))
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32Camera), cv.GenerateID(): cv.declare_id(ESP32Camera),
cv.Required(CONF_NAME): cv.string, cv.Required(CONF_NAME): cv.string,
cv.Required(CONF_DATA_PINS): cv.All([pins.input_pin], cv.Length(min=8, max=8)), cv.Required(CONF_DATA_PINS): cv.All([pins.input_pin], cv.Length(min=8, max=8)),
cv.Required(CONF_VSYNC_PIN): pins.input_pin, cv.Required(CONF_VSYNC_PIN): pins.input_pin,
@ -80,7 +80,7 @@ CONFIG_SCHEMA = cv.Schema({
max=60)), max=60)),
cv.Optional(CONF_IDLE_FRAMERATE, default='0.1 fps'): cv.All(cv.framerate, cv.Optional(CONF_IDLE_FRAMERATE, default='0.1 fps'): cv.All(cv.framerate,
cv.Range(min=0, max=1)), cv.Range(min=0, max=1)),
cv.Optional(CONF_RESOLUTION, default='640X480'): cv.one_of(*FRAME_SIZES, upper=True), cv.Optional(CONF_RESOLUTION, default='640X480'): cv.enum(FRAME_SIZES, upper=True),
cv.Optional(CONF_JPEG_QUALITY, default=10): cv.All(cv.int_, cv.Range(min=10, max=63)), cv.Optional(CONF_JPEG_QUALITY, default=10): cv.All(cv.int_, cv.Range(min=10, max=63)),
cv.Optional(CONF_CONTRAST, default=0): camera_range_param, cv.Optional(CONF_CONTRAST, default=0): camera_range_param,
cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param, cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
@ -124,7 +124,7 @@ def to_code(config):
cg.add(var.set_idle_update_interval(0)) cg.add(var.set_idle_update_interval(0))
else: else:
cg.add(var.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE])) cg.add(var.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE]))
cg.add(var.set_frame_size(FRAME_SIZES[config[CONF_RESOLUTION]])) cg.add(var.set_frame_size(config[CONF_RESOLUTION]))
cg.add_define('USE_ESP32_CAMERA') cg.add_define('USE_ESP32_CAMERA')
cg.add_build_flag('-DBOARD_HAS_PSRAM') cg.add_build_flag('-DBOARD_HAS_PSRAM')

View file

@ -1,22 +1,18 @@
from esphome.components import sensor
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32, \ from esphome.const import CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32, \
CONF_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_ACCURACY_DECIMALS, UNIT_MICROTESLA, ICON_MAGNET UNIT_MICROTESLA, ICON_MAGNET
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall') esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall')
ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.PollingSensorComponent) ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.PollingSensorComponent)
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ CONFIG_SCHEMA = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1).extend({
cv.GenerateID(): cv.declare_variable_id(ESP32HallSensor), cv.GenerateID(): cv.declare_id(ESP32HallSensor),
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA)
cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_MICROTESLA): sensor.unit_of_measurement,
cv.Optional(CONF_ICON, default=ICON_MAGNET): sensor.icon,
cv.Optional(CONF_ACCURACY_DECIMALS, default=-1): sensor.accuracy_decimals,
}).extend(cv.COMPONENT_SCHEMA))
def to_code(config): def to_code(config):

View file

@ -44,7 +44,7 @@ VOLTAGE_ATTENUATION = {
} }
CONFIG_SCHEMA = cv.Schema({ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent), cv.GenerateID(): cv.declare_id(ESP32TouchComponent),
cv.Optional(CONF_SETUP_MODE, default=False): cv.boolean, cv.Optional(CONF_SETUP_MODE, default=False): cv.boolean,
cv.Optional(CONF_IIR_FILTER, default='0ms'): cv.positive_time_period_milliseconds, cv.Optional(CONF_IIR_FILTER, default='0ms'): cv.positive_time_period_milliseconds,
cv.Optional(CONF_SLEEP_DURATION, default='27306us'): cv.Optional(CONF_SLEEP_DURATION, default='27306us'):

Some files were not shown because too many files have changed in this diff Show more