1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-01 15:41:52 +00:00

Compare commits

...

74 Commits

Author SHA1 Message Date
Otto Winter
ac0b095941 Bump version to v1.12.2 2019-03-31 13:13:12 +02:00
Otto Winter
cda9bad233 Upgrade docker base image to 1.4.3 (#499) 2019-03-31 13:13:09 +02:00
Otto Winter
41db8a1264 Fix text sensor MQTT settings (#495)
Fixes https://github.com/esphome/issues/issues/170
2019-03-31 13:13:09 +02:00
Otto Winter
e7e785fd60 Fix dashboard wizard unicode (#494)
* Fix dashboard wizard unicode

Fixes https://github.com/esphome/issues/issues/169

* Fix password md5
2019-03-31 13:13:08 +02:00
Otto Winter
300d3a1f46 Upgrade ESPAsyncTCP to 1.2.0 (#497) 2019-03-31 13:13:08 +02:00
Otto Winter
356554c08d ESP8266 SDK 2.3.0 compat (#490) 2019-03-31 13:13:08 +02:00
Guillermo Ruffino
ced28ad006 Better symlink support under Windows (#487)
* Better symlink support under Windows

* Conditional loading of ctypes wintypes module

* Shortening comment line for pylint

* Adding plint bypass for Python 3
2019-03-31 13:13:08 +02:00
Otto Winter
6ccab2bef9 Bump version to v1.12.1 2019-03-20 13:11:55 +01:00
Otto Winter
475aa4879c Fix IPAddress in validate (#488)
Fixes https://github.com/esphome/issues/issues/141
2019-03-20 13:11:48 +01:00
Otto Winter
4452473735 Fix filter_out: nan filer (#486)
* Fix filter_out nan filter

Fixes https://github.com/esphome/issues/issues/138

* Add test
2019-03-20 13:11:48 +01:00
Otto Winter
948adfd28c Bump version to v1.12.0 2019-03-17 21:12:17 +01:00
Otto Winter
aebbd7673b Bump version to v1.12.0b4 2019-03-17 20:46:35 +01:00
Otto Winter
3baaf6b7c4 Update Hassio base image to 1.4.1 (#484)
* Update Hassio base image to 1.4.1

* Fix rotary encoder typo

Fixes https://github.com/esphome/issues/issues/136
2019-03-17 20:46:32 +01:00
Otto Winter
4a14221e2b Bump version to v1.12.0b3 2019-03-17 16:06:00 +01:00
Otto Winter
114ebf9fe1 More changes for 1.12 (#483)
* Print error when ESP32 BLE tracker used together with beacon

* Update

* Enable PSRAM

* Fix test
2019-03-17 16:05:55 +01:00
Otto Winter
92a4ee5652 Bump version to v1.12.0b2 2019-03-16 22:27:51 +01:00
Otto Winter
9fea094b4e Changes for 1.12 (#482)
* Update setup scripts

* Add delete action, remove Hass config command

* Update esphome.js

* Lint
2019-03-16 22:27:45 +01:00
Otto Winter
596c334fcb Bump version to v1.12.0b1 2019-03-13 18:58:54 +01:00
Otto Winter
ca4450858f Add auto-issue closer 2019-03-13 18:30:45 +01:00
Otto Winter
f3ec83fe31 Add ESP32 Camera (#475)
* Add ESP32 Camera

* Fixes

* Updates

* Fix substitutions not working for non-ASCII

* Update docker base image to 1.3.0
2019-03-13 16:40:09 +01:00
Florian Gareis
c4ada8c9f0 Add color to login error for better visability (#478) 2019-03-08 12:42:22 +01:00
puuu
23df5d8af7 Support SDS011 component. (#467)
* Support SDS011 component.

* improve if condition

* Check update interval is multiple of minute

* do not allow update intervals longer than 30 min

* fix sensor schema name

* remove query_mode

* Warn if rx_only mode used together with update interval

* Allow update intervals below 1min

Messed that up before, as the docs say update intervals below 1min are allowed

* Use update interval in minutes

* use set_update_interval_min() to set update interval
2019-03-06 12:39:52 +01:00
Otto Winter
289acade1e vol.Schema -> cv.Schema 2019-03-05 15:06:38 +01:00
Otto Winter
a99f99779a Use double quotes for wizard
Fixes https://github.com/esphome/issues/issues/81
2019-03-05 14:14:38 +01:00
Otto Winter
5c14ca030a Add Wifi info text sensor (#473)
* Add WiFi Info text sensor

* Lint

* Fix register

* Add newline at end of file
2019-03-05 14:05:51 +01:00
Otto Winter
0fc6a027a7 Add copy output platform (#472) 2019-03-05 13:54:33 +01:00
Otto Winter
3c0d97ef69 Add connected condition (#474)
* Add WiFi/MQTT/API connected condition

* Add tests

* Fix namespace

* Update api.py
2019-03-05 13:54:14 +01:00
Otto Winter
5b4f98d414 Revert "Remove piolibdeps cache"
This reverts commit e009f21a72.
2019-03-05 13:53:09 +01:00
Otto Winter
7ebfcd3807 Add for to binary sensor conditions (#471) 2019-03-05 13:51:53 +01:00
Otto Winter
3ef0634dd2 Upgrade ESP32 core to 1.0.1 (#470)
* Upgrade ESP32 core to 1.0.1

Ref https://github.com/espressif/arduino-esp32/issues/2540

* Undo remove

* Add i2c debugging

* Lint
2019-03-05 13:44:51 +01:00
Otto Winter
0928c9739f Fix build 2019-03-05 13:44:38 +01:00
Otto Winter
e009f21a72 Remove piolibdeps cache
We cannot cache esphome-core
2019-03-05 13:28:18 +01:00
Otto Winter
606c412616 Cache travis folders 2019-03-05 13:27:38 +01:00
Otto Winter
975b5127d6 Allow Arduino Core 2.5.0 for ESP8266 (#469) 2019-03-05 13:25:59 +01:00
Otto Winter
60c9ffef30 Fix build 2019-03-03 19:29:10 +01:00
Otto Winter
99861259d7 Add MCP23017 (#466)
* Add MCP23017

* Add test
2019-03-03 16:51:55 +01:00
Otto Winter
067ec30c56 Add relative_url, streamer_mode, status_use_ping dashboard options (#461)
* Add relative_url, streamer_mode, status_use_ping dashboard options

Additionally Hass.io now stores all build files in /data, so that snapshots no longer get huge.

* Lint

* Lint

* Replace tabs with spaces
2019-03-03 16:50:06 +01:00
Otto Winter
5a102c2ab7 Rewrite interrupt components (#464)
* Rewrite intterupt components

* Fix test
2019-03-03 16:47:10 +01:00
Otto Winter
4b017e2096 Add WiFi/MQTT/API connected condition (#465)
* Add WiFi/MQTT/API connected condition

* Add tests

* Fix namespace
2019-03-03 16:45:56 +01:00
Otto Winter
8495ce96a3 Lint
tornado got updated, broke pylint
2019-03-03 16:43:51 +01:00
Marco
55caf4f648 Update ads1115.py (#468)
GAIN setting is pointing to the wrong value
2019-03-01 16:43:51 +01:00
Otto Winter
c123f0091d Upgrade pylint on python 3 to fix travis 2019-02-28 10:33:22 +01:00
Otto Winter
7c65d44976 Add rotary encoder min/max value (#463) 2019-02-28 10:17:38 +01:00
Otto Winter
5b8d12a80c Enable i2c scanning by default (#462) 2019-02-28 10:16:19 +01:00
Otto Winter
3951a2b22a Fix os.symlink on Windows (#460) 2019-02-28 10:15:57 +01:00
Otto Winter
69a74a30e8 Lint 2019-02-28 10:14:28 +01:00
Otto Winter
f3ee5b55e9 Add warning if esphome-core dev used without esphome dev 2019-02-28 10:11:05 +01:00
Otto Winter
f6cc9f7caa Merge branch 'master' into dev 2019-02-26 23:12:06 +01:00
Otto Winter
a4edcc48ca Lint 2019-02-26 19:46:58 +01:00
Otto Winter
1778dd4df9 Add linear calibration sensor filter (#454)
* Add linear calibrate filter

* Remove filter_nan

* Add test
2019-02-26 19:38:39 +01:00
Otto Winter
311e837196 Add native API user-defined services (#453) 2019-02-26 19:38:28 +01:00
Otto Winter
3b00cfd6c4 Convert automation engine to use variadic templates (#452) 2019-02-26 19:28:11 +01:00
Otto Winter
1c7ca4bc6f Recommend similar keys for spelling errors (#458)
* Recommend similar keys for spelling errors

Fixes https://github.com/esphome/feature-requests/issues/68

* Fixes

* Fix
2019-02-26 19:22:33 +01:00
mtl010957
38e7b597d6 Add handling for min power output setting (#448)
* Add handling for min power output setting

* Fix line length error
2019-02-26 18:35:45 +01:00
Otto Winter
808ee19180 Fix mDNS library added only with OTA (#451) 2019-02-26 18:34:47 +01:00
Otto Winter
c2a0c22bd9 Automatically hide secrets in validation (#455)
* Hide secrets in validation

* Lint
2019-02-26 18:32:20 +01:00
Otto Winter
e785ad5401 Remove automatic update check (#457)
* Remove automatic update check

* Lint
2019-02-26 18:31:40 +01:00
Otto Winter
bacddc3673 Add restore state from flash option (#459) 2019-02-26 16:55:37 +01:00
Otto Winter
7dd0dabaf5 Allow non-pullup pins for dallas (#456) 2019-02-26 16:39:20 +01:00
Michiel van Turnhout
92f8b043ce Add MPR121 Capacitive Touch Sensor (#449)
* module mpr121

* added mpr121 sensor and binary sensor

* added tests

* removed CONF_CHANNELS, it is not supported in the esphome-code mpr121
code

* changed namespace for mpr121 to binary_sensor

* Update esphome/components/binary_sensor/mpr121.py

Co-Authored-By: mvturnho <qris.online@gmail.com>

* fixed class names

* fix lint errors
2019-02-24 21:48:28 +01:00
Otto Winter
2e5fd7e90d Merge branch 'master' into dev 2019-02-23 20:25:28 +01:00
Otto Winter
12ce448f2d Merge branch 'master' into dev 2019-02-22 22:06:36 +01:00
Otto Winter
e7ce8f7a13 Improve dashboard setup wizard (#450) 2019-02-22 21:18:56 +01:00
Otto Winter
3d1cce2a29 Add report_position test
Fixes https://github.com/esphome/issues/issues/46
2019-02-22 17:43:30 +01:00
Otto Winter
af0c213024 Allow use of arduino core v2.5.0 on ESP8266 (#446)
* Allow use of arduino core v2.5.0 on ESP8266

It's very unstable, but you can try if you want

* Fix
2019-02-21 18:16:00 +01:00
Otto Winter
88e036ddb2 Allow i2c on non-pullup pins (#447) 2019-02-21 18:15:45 +01:00
Otto Winter
8012de3ba4 Revert "Merge remote-tracking branch 'origin/master' into dev"
This reverts commit 52750d933b, reversing
changes made to 7e7a85abfd.
2019-02-20 13:21:49 +01:00
Otto Winter
f0c0131ed1 Fix MQTT log topic level (#445) 2019-02-20 12:38:09 +01:00
Otto Winter
52750d933b Merge remote-tracking branch 'origin/master' into dev 2019-02-20 12:22:43 +01:00
Florian Gareis
7e7a85abfd Remove unnecessary wrapper (#444) 2019-02-19 20:46:23 +01:00
Florian Gareis
c1b8107aaf Remove duplicate scrollbar & move scrollbar (#443)
* Remove duplicate scrollbar

* Move scrolling from modal-content to log-container

* Replace css autoscroll with stable js autoscroll
2019-02-19 20:30:12 +01:00
Otto Winter
0bdcce609f Re-remove aarch64
Tried it again and platformio doesn't work
2019-02-19 15:03:59 +01:00
Otto Winter
6b702f8014 Fix custom components not registered (#441) 2019-02-18 14:59:35 +01:00
Otto Winter
078ab26fd2 Bump dev version to 1.12.0-dev 2019-02-18 12:10:05 +01:00
186 changed files with 2229 additions and 1504 deletions

7
.github/issue-close-app.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
comment: >-
https://github.com/esphome/esphome/issues/430
issueConfigs:
- content:
- "OTHERWISE THE ISSUE WILL BE CLOSED AUTOMATICALLY"
caseInsensitive: false

View File

@@ -41,11 +41,11 @@ stages:
- |
if [[ "${IS_HASSIO}" == "YES" ]]; then
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.2.1
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
DOCKERFILE=docker/Dockerfile.hassio
else
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.2.1
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3
if [[ "${BUILD_ARCH}" == "amd64" ]]; then
BUILD_TO=esphome/esphome
else
@@ -126,7 +126,7 @@ test3:
- pip install -e .
- pip install twine
script:
- python setup.py sdist
- python setup.py sdist bdist_wheel
- twine upload dist/*
tags:
- docker
@@ -177,48 +177,48 @@ deploy-beta:pypi:
.dev-vars: &dev-vars
DEV: YES
aarch64-beta-docker:
<<: *beta
variables:
BETA: "YES"
BUILD_ARCH: aarch64
IS_HASSIO: "NO"
RELEASE: "YES"
aarch64-beta-hassio:
<<: *beta
variables:
BETA: "YES"
BUILD_ARCH: aarch64
IS_HASSIO: "YES"
RELEASE: "YES"
aarch64-dev-docker:
<<: *dev
variables:
BUILD_ARCH: aarch64
DEV: "YES"
IS_HASSIO: "NO"
aarch64-dev-hassio:
<<: *dev
variables:
BUILD_ARCH: aarch64
DEV: "YES"
IS_HASSIO: "YES"
aarch64-latest-docker:
<<: *latest
variables:
BETA: "YES"
BUILD_ARCH: aarch64
IS_HASSIO: "NO"
LATEST: "YES"
RELEASE: "YES"
aarch64-latest-hassio:
<<: *latest
variables:
BETA: "YES"
BUILD_ARCH: aarch64
IS_HASSIO: "YES"
LATEST: "YES"
RELEASE: "YES"
#aarch64-beta-docker:
# <<: *beta
# variables:
# BETA: "YES"
# BUILD_ARCH: aarch64
# IS_HASSIO: "NO"
# RELEASE: "YES"
#aarch64-beta-hassio:
# <<: *beta
# variables:
# BETA: "YES"
# BUILD_ARCH: aarch64
# IS_HASSIO: "YES"
# RELEASE: "YES"
#aarch64-dev-docker:
# <<: *dev
# variables:
# BUILD_ARCH: aarch64
# DEV: "YES"
# IS_HASSIO: "NO"
#aarch64-dev-hassio:
# <<: *dev
# variables:
# BUILD_ARCH: aarch64
# DEV: "YES"
# IS_HASSIO: "YES"
#aarch64-latest-docker:
# <<: *latest
# variables:
# BETA: "YES"
# BUILD_ARCH: aarch64
# IS_HASSIO: "NO"
# LATEST: "YES"
# RELEASE: "YES"
#aarch64-latest-hassio:
# <<: *latest
# variables:
# BETA: "YES"
# BUILD_ARCH: aarch64
# IS_HASSIO: "YES"
# LATEST: "YES"
# RELEASE: "YES"
amd64-beta-docker:
<<: *beta
variables:

View File

@@ -1,6 +1,13 @@
sudo: false
language: python
cache:
directories:
- "~/.platformio"
- "$TRAVIS_BUILD_DIR/tests/build/test1/.piolibdeps"
- "$TRAVIS_BUILD_DIR/tests/build/test2/.piolibdeps"
- "$TRAVIS_BUILD_DIR/tests/build/test3/.piolibdeps"
matrix:
fast_finish: true
include:
@@ -12,7 +19,7 @@ matrix:
- pylint esphome
- python: "3.5.3"
env: TARGET=Lint3.5
install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.2.2 pillow
install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.3.0 pillow
script:
- flake8 esphome
- pylint esphome
@@ -25,7 +32,7 @@ matrix:
- esphome tests/test3.yaml compile
#- python: "3.5.3"
# env: TARGET=Test3.5
# install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.2.2 pillow
# install: pip install -U https://github.com/platformio/platformio-core/archive/develop.zip && pip install -e . && pip install flake8==3.6.0 pylint==2.3.0 pillow
# script:
# - esphome tests/test1.yaml compile
# - esphome tests/test2.yaml compile

View File

@@ -1,17 +1,6 @@
include LICENSE
include README.md
include esphome/dashboard/templates/index.html
include esphome/dashboard/templates/login.html
include esphome/dashboard/static/ace.js
include esphome/dashboard/static/esphome.css
include esphome/dashboard/static/esphome.js
include esphome/dashboard/static/favicon.ico
include esphome/dashboard/static/jquery.min.js
include esphome/dashboard/static/jquery.validate.min.js
include esphome/dashboard/static/jquery-ui.min.js
include esphome/dashboard/static/materialize.min.css
include esphome/dashboard/static/materialize.min.js
include esphome/dashboard/static/materialize-stepper.min.css
include esphome/dashboard/static/materialize-stepper.min.js
include esphome/dashboard/static/mode-yaml.js
include esphome/dashboard/static/theme-dreamweaver.js
include esphome/dashboard/static/ext-searchbox.js
include esphome/dashboard/templates/*.html
include esphome/dashboard/static/*.js
include esphome/dashboard/static/*.css
include esphome/dashboard/static/*.ico

View File

@@ -1,4 +1,4 @@
ARG BUILD_FROM=esphome/esphome-base-amd64:1.2.1
ARG BUILD_FROM=esphome/esphome-base-amd64:1.4.3
FROM ${BUILD_FROM}
COPY . .

View File

@@ -1,4 +1,4 @@
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.2.1
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.4.3
FROM ${BUILD_FROM}
# Copy root filesystem

View File

@@ -16,11 +16,11 @@ echo "PWD: $PWD"
if [[ ${IS_HASSIO} = "YES" ]]; then
docker build \
--build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.2.1" \
--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.2.1" \
--build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3" \
-t "${IMAGE_NAME}" -f ../docker/Dockerfile ..
fi

View File

@@ -1,35 +1,41 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# This files check if all user configuration requirements are met
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
# Check SSL requirements, if enabled
if hass.config.true 'ssl'; then
if ! hass.config.has_value 'certfile'; then
hass.die 'SSL is enabled, but no certfile was specified.'
if bashio::config.true 'ssl'; then
if ! bashio::config.has_value 'certfile'; then
bashio::fatal 'SSL is enabled, but no certfile was specified.'
bashio::exit.nok
fi
if ! hass.config.has_value 'keyfile'; then
hass.die 'SSL is enabled, but no keyfile was specified'
if ! bashio::config.has_value 'keyfile'; then
bashio::fatal 'SSL is enabled, but no keyfile was specified'
bashio::exit.nok
fi
if ! hass.file_exists "/ssl/$(hass.config.get 'certfile')"; then
if ! hass.file_exists "/ssl/$(hass.config.get 'keyfile')"; then
certfile="/ssl/$(bashio::config 'certfile')"
keyfile="/ssl/$(bashio::config 'keyfile')"
if ! bashio::fs.file_exists "${certfile}"; then
if ! bashio::fs.file_exists "${keyfile}"; then
# Both files are missing, let's print a friendlier error message
text="You enabled encrypted connections using the \"ssl\": true option.
However, the SSL files \"$(hass.config.get 'certfile')\" and \"$(hass.config.get 'keyfile')\"
were not found. If you're using Hass.io on your local network and don't want
to encrypt connections to the ESPHome dashboard, you can manually disable
SSL by setting \"ssl\" to false."
hass.die "${text}"
bashio::log.fatal 'You enabled encrypted connections using the "ssl": true option.'
bashio::log.fatal "However, the SSL files '${certfile}' and '${keyfile}'"
bashio::log.fatal "were not found. If you're using Hass.io on your local network and don't want"
bashio::log.fatal 'to encrypt connections to the ESPHome dashboard, you can manually disable'
bashio::log.fatal 'SSL by setting "ssl" to false."'
bashio::exit.nok
fi
hass.die 'The configured certfile is not found'
bashio::log.fatal "The configured certfile '${certfile}' was not found."
bashio::exit.nok
fi
if ! hass.file_exists "/ssl/$(hass.config.get 'keyfile')"; then
hass.die 'The configured keyfile is not found'
if ! bashio::fs.file_exists "/ssl/$(bashio::config 'keyfile')"; then
bashio::log.fatal "The configured keyfile '${keyfile}' was not found."
bashio::exit.nok
fi
fi

View File

@@ -1,10 +1,8 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Configures NGINX for use with ESPHome
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
declare certfile
declare keyfile
@@ -13,16 +11,16 @@ declare port
mkdir -p /var/log/nginx
# Enable SSL
if hass.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=$(hass.config.get 'certfile')
keyfile=$(hass.config.get 'keyfile')
certfile=$(bashio::config 'certfile')
keyfile=$(bashio::config 'keyfile')
sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/nginx.conf
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/nginx.conf
fi
port=$(hass.config.get 'port')
port=$(bashio::config 'port')
sed -i "s/%%port%%/${port}/g" /etc/nginx/nginx.conf

View File

@@ -1,14 +1,15 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# This files installs the user ESPHome version if specified
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
declare esphome_version
if hass.config.has_value 'esphome_version'; then
esphome_version=$(hass.config.get 'esphome_version')
pip2 install --no-cache-dir --no-binary :all: "https://github.com/esphome/esphome/archive/${esphome_version}.zip"
if bashio::config.has_value 'esphome_version'; then
esphome_version=$(bashio::config 'esphome_version')
full_url="https://github.com/esphome/esphome/archive/${esphome_version}.zip"
bashio::log.info "Installing esphome version '${esphome_version}' (${full_url})..."
pip2 install --no-cache-dir --no-binary :all: "${full_url}" \
|| bashio::exit.nok "Failed installing esphome pinned version."
fi

View File

@@ -1,10 +1,8 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# This files migrates the esphome config directory from the old path
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
if [[ ! -d /config/esphome && -d /config/esphomeyaml ]]; then
echo "Moving config directory from /config/esphomeyaml to /config/esphome"

View File

@@ -1,14 +1,26 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Runs the ESPHome dashboard
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
if hass.config.true 'leave_front_door_open'; then
export ESPHOME_IS_HASSIO=true
if bashio::config.true 'leave_front_door_open'; then
export DISABLE_HA_AUTHENTICATION=true
fi
hass.log.info "Starting ESPHome dashboard..."
if bashio::config.true 'streamer_mode'; then
export ESPHOME_STREAMER_MODE=true
fi
if bashio::config.true 'status_use_ping'; then
export ESPHOME_DASHBOARD_USE_PING=true
fi
if bashio::config.has_value 'relative_url'; then
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
fi
bashio::log.info "Starting ESPHome dashboard..."
exec esphome /config/esphome dashboard --socket /var/run/esphome.sock --hassio

View File

@@ -1,10 +1,8 @@
#!/usr/bin/with-contenv bash
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Runs the NGINX proxy
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
hass.log.info "Starting NGINX..."
bashio::log.info "Starting NGINX..."
exec nginx -g "daemon off;"

View File

@@ -1,7 +1,6 @@
from __future__ import print_function
import argparse
from collections import OrderedDict
from datetime import datetime
import logging
import os
@@ -18,7 +17,8 @@ from esphome.cpp_generator import Expression, RawStatement, add, statement
from esphome.helpers import color, indent
from esphome.py_compat import IS_PY2, safe_input, text_type
from esphome.storage_json import StorageJSON, storage_path
from esphome.util import run_external_command, run_external_process, safe_print
from esphome.util import run_external_command, run_external_process, safe_print, \
is_dev_esphome_version
_LOGGER = logging.getLogger(__name__)
@@ -157,11 +157,20 @@ def write_cpp(config):
def compile_program(args, config):
_LOGGER.info("Compiling app...")
rc = platformio_api.run_compile(config, args.verbose)
if rc != 0 and CORE.is_dev_esphome_core_version and not is_dev_esphome_version():
_LOGGER.warning("You're using 'esphome_core_version: dev' but not using the "
"dev version of the ESPHome tool.")
_LOGGER.warning("Expect compile errors if these versions are out of sync.")
_LOGGER.warning("Please install the dev version of ESPHome too when using "
"'esphome_core_version: dev'.")
_LOGGER.warning(" - Hass.io: Install 'ESPHome (dev)' addon")
_LOGGER.warning(" - Docker: docker run [...] esphome/esphome:dev [...]")
_LOGGER.warning(" - PIP: pip install -U https://github.com/esphome/esphome/archive/dev.zip")
return rc
def upload_using_esptool(config, port):
path = os.path.join(CORE.build_path, '.pioenvs', CORE.name, 'firmware.bin')
path = CORE.firmware_bin
cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path]
@@ -338,28 +347,6 @@ def command_clean(args, config):
return 0
def command_hass_config(args, config):
from esphome.components import mqtt as mqtt_component
_LOGGER.info("This is what you should put in your Home Assistant YAML configuration.")
_LOGGER.info("Please note this is only necessary if you're not using MQTT discovery.")
data = mqtt_component.GenerateHassConfigData(config)
hass_config = OrderedDict()
for domain, component, conf in iter_components(config):
if not hasattr(component, 'to_hass_config'):
continue
func = getattr(component, 'to_hass_config')
ret = func(data, conf)
if not isinstance(ret, (list, tuple)):
ret = [ret]
ret = [x for x in ret if x is not None]
domain_conf = hass_config.setdefault(domain.split('.')[0], [])
domain_conf += ret
safe_print(yaml_util.dump(hass_config))
return 0
def command_dashboard(args):
from esphome.dashboard import dashboard
@@ -381,7 +368,6 @@ POST_CONFIG_ACTIONS = {
'clean-mqtt': command_clean_mqtt,
'mqtt-fingerprint': command_mqtt_fingerprint,
'clean': command_clean,
'hass-config': command_hass_config,
}
@@ -461,10 +447,6 @@ def parse_args(argv):
dashboard.add_argument("--socket",
help="Make the dashboard serve under a unix socket", type=str)
subparsers.add_parser('hass-config',
help="Dump the configuration entries that should be added "
"to Home Assistant when not using MQTT discovery.")
return parser.parse_args(argv[1:])

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: api.proto

View File

@@ -3,9 +3,9 @@ import copy
import voluptuous as vol
import esphome.config_validation as cv
from esphome.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \
CONF_BELOW, CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, CONF_ELSE, CONF_ID, CONF_IF, \
CONF_LAMBDA, CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID, CONF_WHILE, CONF_WAIT_UNTIL
from esphome.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, CONF_BELOW, \
CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, CONF_ELSE, CONF_ID, CONF_IF, CONF_LAMBDA, \
CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID, CONF_WAIT_UNTIL, CONF_WHILE
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, TemplateArguments, add, get_variable, \
process_lambda, templatable
@@ -48,7 +48,7 @@ def validate_recursive_condition(value):
u"".format(key, key2), path)
validator = CONDITION_REGISTRY[key][0]
try:
condition = validator(item[key])
condition = validator(item[key] or {})
except vol.Invalid as err:
err.prepend(path)
raise err
@@ -83,7 +83,7 @@ def validate_recursive_action(value):
u"".format(key, key2), path)
validator = ACTION_REGISTRY[key][0]
try:
action = validator(item[key])
action = validator(item[key] or {})
except vol.Invalid as err:
err.prepend(path)
raise err
@@ -131,7 +131,7 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
# Next try as a sequence of automations
try:
return vol.Schema([schema])(value)
return cv.Schema([schema])(value)
except vol.Invalid as err2:
if 'Unable to find action' in str(err):
raise err2
@@ -146,7 +146,7 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
def validator(value):
value = validator_(value)
if extra_validators is not None:
value = vol.Schema([extra_validators])(value)
value = cv.Schema([extra_validators])(value)
if single:
if len(value) != 1:
raise vol.Invalid("Cannot have more than 1 automation for templates")
@@ -156,10 +156,9 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
return validator
AUTOMATION_SCHEMA = vol.Schema({
AUTOMATION_SCHEMA = cv.Schema({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger),
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation),
vol.Optional(CONF_IF): validate_recursive_condition,
vol.Required(CONF_THEN): validate_recursive_action,
})
@@ -167,8 +166,8 @@ AND_CONDITION_SCHEMA = validate_recursive_condition
@CONDITION_REGISTRY.register(CONF_AND, AND_CONDITION_SCHEMA)
def and_condition_to_code(config, condition_id, arg_type, template_arg):
for conditions in build_conditions(config, arg_type):
def and_condition_to_code(config, condition_id, template_arg, args):
for conditions in build_conditions(config, template_arg, args):
yield
rhs = AndCondition.new(template_arg, conditions)
type = AndCondition.template(template_arg)
@@ -179,33 +178,33 @@ OR_CONDITION_SCHEMA = validate_recursive_condition
@CONDITION_REGISTRY.register(CONF_OR, OR_CONDITION_SCHEMA)
def or_condition_to_code(config, condition_id, arg_type, template_arg):
for conditions in build_conditions(config, arg_type):
def or_condition_to_code(config, condition_id, template_arg, args):
for conditions in build_conditions(config, template_arg, args):
yield
rhs = OrCondition.new(template_arg, conditions)
type = OrCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
RANGE_CONDITION_SCHEMA = vol.All(vol.Schema({
RANGE_CONDITION_SCHEMA = vol.All(cv.Schema({
vol.Optional(CONF_ABOVE): cv.templatable(cv.float_),
vol.Optional(CONF_BELOW): cv.templatable(cv.float_),
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))
@CONDITION_REGISTRY.register(CONF_RANGE, RANGE_CONDITION_SCHEMA)
def range_condition_to_code(config, condition_id, arg_type, template_arg):
for conditions in build_conditions(config, arg_type):
def range_condition_to_code(config, condition_id, template_arg, args):
for conditions in build_conditions(config, template_arg, args):
yield
rhs = RangeCondition.new(template_arg, conditions)
type = RangeCondition.template(template_arg)
condition = Pvariable(condition_id, rhs, type=type)
if CONF_ABOVE in config:
for template_ in templatable(config[CONF_ABOVE], arg_type, float_):
for template_ in templatable(config[CONF_ABOVE], args, float_):
yield
condition.set_min(template_)
if CONF_BELOW in config:
for template_ in templatable(config[CONF_BELOW], arg_type, float_):
for template_ in templatable(config[CONF_BELOW], args, float_):
yield
condition.set_max(template_)
yield condition
@@ -215,11 +214,11 @@ DELAY_ACTION_SCHEMA = cv.templatable(cv.positive_time_period_milliseconds)
@ACTION_REGISTRY.register(CONF_DELAY, DELAY_ACTION_SCHEMA)
def delay_action_to_code(config, action_id, arg_type, template_arg):
def delay_action_to_code(config, action_id, template_arg, args):
rhs = App.register_component(DelayAction.new(template_arg))
type = DelayAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for template_ in templatable(config, arg_type, uint32):
for template_ in templatable(config, args, uint32):
yield
add(action.set_delay(template_))
yield action
@@ -233,44 +232,44 @@ IF_ACTION_SCHEMA = vol.All({
@ACTION_REGISTRY.register(CONF_IF, IF_ACTION_SCHEMA)
def if_action_to_code(config, action_id, arg_type, template_arg):
for conditions in build_conditions(config[CONF_CONDITION], arg_type):
def if_action_to_code(config, action_id, template_arg, args):
for conditions in build_conditions(config[CONF_CONDITION], template_arg, args):
yield None
rhs = IfAction.new(template_arg, conditions)
type = IfAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_THEN in config:
for actions in build_actions(config[CONF_THEN], arg_type):
for actions in build_actions(config[CONF_THEN], template_arg, args):
yield None
add(action.add_then(actions))
if CONF_ELSE in config:
for actions in build_actions(config[CONF_ELSE], arg_type):
for actions in build_actions(config[CONF_ELSE], template_arg, args):
yield None
add(action.add_else(actions))
yield action
WHILE_ACTION_SCHEMA = vol.Schema({
WHILE_ACTION_SCHEMA = cv.Schema({
vol.Required(CONF_CONDITION): validate_recursive_condition,
vol.Required(CONF_THEN): validate_recursive_action,
})
@ACTION_REGISTRY.register(CONF_WHILE, WHILE_ACTION_SCHEMA)
def while_action_to_code(config, action_id, arg_type, template_arg):
for conditions in build_conditions(config[CONF_CONDITION], arg_type):
def while_action_to_code(config, action_id, template_arg, args):
for conditions in build_conditions(config[CONF_CONDITION], template_arg, args):
yield None
rhs = WhileAction.new(template_arg, conditions)
type = WhileAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for actions in build_actions(config[CONF_THEN], arg_type):
for actions in build_actions(config[CONF_THEN], template_arg, args):
yield None
add(action.add_then(actions))
yield action
def validate_wait_until(value):
schema = vol.Schema({
schema = cv.Schema({
vol.Required(CONF_CONDITION): validate_recursive_condition
})
if isinstance(value, dict) and CONF_CONDITION in value:
@@ -282,8 +281,8 @@ WAIT_UNTIL_ACTION_SCHEMA = validate_wait_until
@ACTION_REGISTRY.register(CONF_WAIT_UNTIL, WAIT_UNTIL_ACTION_SCHEMA)
def wait_until_action_to_code(config, action_id, arg_type, template_arg):
for conditions in build_conditions(config[CONF_CONDITION], arg_type):
def wait_until_action_to_code(config, action_id, template_arg, args):
for conditions in build_conditions(config[CONF_CONDITION], template_arg, args):
yield None
rhs = WaitUntilAction.new(template_arg, conditions)
type = WaitUntilAction.template(template_arg)
@@ -296,8 +295,8 @@ LAMBDA_ACTION_SCHEMA = cv.lambda_
@ACTION_REGISTRY.register(CONF_LAMBDA, LAMBDA_ACTION_SCHEMA)
def lambda_action_to_code(config, action_id, arg_type, template_arg):
for lambda_ in process_lambda(config, [(arg_type, 'x')], return_type=void):
def lambda_action_to_code(config, action_id, template_arg, args):
for lambda_ in process_lambda(config, args, return_type=void):
yield None
rhs = LambdaAction.new(template_arg, lambda_)
type = LambdaAction.template(template_arg)
@@ -308,8 +307,8 @@ LAMBDA_CONDITION_SCHEMA = cv.lambda_
@CONDITION_REGISTRY.register(CONF_LAMBDA, LAMBDA_CONDITION_SCHEMA)
def lambda_condition_to_code(config, condition_id, arg_type, template_arg):
for lambda_ in process_lambda(config, [(arg_type, 'x')], return_type=bool_):
def lambda_condition_to_code(config, condition_id, template_arg, args):
for lambda_ in process_lambda(config, args, return_type=bool_):
yield
rhs = LambdaCondition.new(template_arg, lambda_)
type = LambdaCondition.template(template_arg)
@@ -323,7 +322,7 @@ COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COMPONENT_UPDATE, COMPONENT_UPDATE_ACTION_SCHEMA)
def component_update_action_to_code(config, action_id, arg_type, template_arg):
def component_update_action_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = UpdateComponentAction.new(template_arg, var)
@@ -331,61 +330,55 @@ def component_update_action_to_code(config, action_id, arg_type, template_arg):
yield Pvariable(action_id, rhs, type=type)
def build_action(full_config, arg_type):
def build_action(full_config, template_arg, args):
action_id = full_config[CONF_ACTION_ID]
key, config = next((k, v) for k, v in full_config.items() if k in ACTION_REGISTRY)
builder = ACTION_REGISTRY[key][1]
template_arg = TemplateArguments(arg_type)
for result in builder(config, action_id, arg_type, template_arg):
for result in builder(config, action_id, template_arg, args):
yield None
yield result
def build_actions(config, arg_type):
def build_actions(config, templ, arg_type):
actions = []
for conf in config:
for action in build_action(conf, arg_type):
for action in build_action(conf, templ, arg_type):
yield None
actions.append(action)
yield actions
def build_condition(full_config, arg_type):
def build_condition(full_config, template_arg, args):
action_id = full_config[CONF_CONDITION_ID]
key, config = next((k, v) for k, v in full_config.items() if k in CONDITION_REGISTRY)
builder = CONDITION_REGISTRY[key][1]
template_arg = TemplateArguments(arg_type)
for result in builder(config, action_id, arg_type, template_arg):
for result in builder(config, action_id, template_arg, args):
yield None
yield result
def build_conditions(config, arg_type):
def build_conditions(config, templ, args):
conditions = []
for conf in config:
for condition in build_condition(conf, arg_type):
for condition in build_condition(conf, templ, args):
yield None
conditions.append(condition)
yield conditions
def build_automation_(trigger, arg_type, config):
rhs = App.make_automation(TemplateArguments(arg_type), trigger)
type = Automation.template(arg_type)
def build_automation_(trigger, args, config):
arg_types = [arg[0] for arg in args]
templ = TemplateArguments(*arg_types)
rhs = App.make_automation(templ, trigger)
type = Automation.template(templ)
obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type)
if CONF_IF in config:
conditions = None
for conditions in build_conditions(config[CONF_IF], arg_type):
yield None
add(obj.add_conditions(conditions))
actions = None
for actions in build_actions(config[CONF_THEN], arg_type):
for actions in build_actions(config[CONF_THEN], templ, args):
yield None
add(obj.add_actions(actions))
yield obj
def build_automation(trigger, arg_type, config):
CORE.add_job(build_automation_, trigger, arg_type, config)
def build_automations(trigger, args, config):
CORE.add_job(build_automation_, trigger, args, config)

View File

@@ -12,7 +12,7 @@ MULTI_CONF = True
ADS1115Component = sensor.sensor_ns.class_('ADS1115Component', Component, i2c.I2CDevice)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
vol.Required(CONF_ADDRESS): cv.i2c_address,
}).extend(cv.COMPONENT_SCHEMA.schema)

View File

@@ -13,7 +13,7 @@ MULTI_CONF = True
CONF_APDS9960_ID = 'apds9960_id'
APDS9960 = sensor.sensor_ns.class_('APDS9960', PollingComponent, i2c.I2CDevice)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(APDS9960),
vol.Optional(CONF_ADDRESS): cv.i2c_address,
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,

View File

@@ -1,25 +1,52 @@
import voluptuous as vol
from esphome.automation import ACTION_REGISTRY
from esphome import automation
from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY, Condition
import esphome.config_validation as cv
from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \
CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES
CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, add, get_variable, process_lambda
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import Action, App, Component, StoringController, esphome_ns
from esphome.cpp_types import Action, App, Component, StoringController, esphome_ns, Trigger, \
bool_, int32, float_, std_string
api_ns = esphome_ns.namespace('api')
APIServer = api_ns.class_('APIServer', Component, StoringController)
HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', Action)
KeyValuePair = api_ns.class_('KeyValuePair')
TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair')
APIConnectedCondition = api_ns.class_('APIConnectedCondition', Condition)
CONFIG_SCHEMA = vol.Schema({
UserService = api_ns.class_('UserService', Trigger)
ServiceTypeArgument = api_ns.class_('ServiceTypeArgument')
ServiceArgType = api_ns.enum('ServiceArgType')
SERVICE_ARG_TYPES = {
'bool': ServiceArgType.SERVICE_ARG_TYPE_BOOL,
'int': ServiceArgType.SERVICE_ARG_TYPE_INT,
'float': ServiceArgType.SERVICE_ARG_TYPE_FLOAT,
'string': ServiceArgType.SERVICE_ARG_TYPE_STRING,
}
SERVICE_ARG_NATIVE_TYPES = {
'bool': bool_,
'int': int32,
'float': float_,
'string': std_string,
}
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(APIServer),
vol.Optional(CONF_PORT, default=6053): cv.port,
vol.Optional(CONF_PASSWORD, default=''): cv.string_strict,
vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds,
vol.Optional(CONF_SERVICES): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(UserService),
vol.Required(CONF_SERVICE): cv.valid_name,
vol.Optional(CONF_VARIABLES, default={}): cv.Schema({
cv.validate_id_name: cv.one_of(*SERVICE_ARG_TYPES, lower=True),
}),
}),
}).extend(cv.COMPONENT_SCHEMA.schema)
@@ -34,6 +61,21 @@ def to_code(config):
if CONF_REBOOT_TIMEOUT in config:
add(api.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
for conf in config.get(CONF_SERVICES, []):
template_args = []
func_args = []
service_type_args = []
for name, var_ in conf[CONF_VARIABLES].items():
native = SERVICE_ARG_NATIVE_TYPES[var_]
template_args.append(native)
func_args.append((native, name))
service_type_args.append(ServiceTypeArgument(name, SERVICE_ARG_TYPES[var_]))
func = api.make_user_service_trigger.template(*template_args)
rhs = func(conf[CONF_SERVICE], service_type_args)
type_ = UserService.template(*template_args)
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs, type=type_)
automation.build_automations(trigger, func_args, conf)
setup_component(api, config)
@@ -42,34 +84,34 @@ BUILD_FLAGS = '-DUSE_API'
def lib_deps(config):
if CORE.is_esp32:
return 'AsyncTCP@1.0.1'
return 'AsyncTCP@1.0.3'
if CORE.is_esp8266:
return 'ESPAsyncTCP@1.1.3'
return 'ESPAsyncTCP@1.2.0'
raise NotImplementedError
CONF_HOMEASSISTANT_SERVICE = 'homeassistant.service'
HOMEASSISTANT_SERVIC_ACTION_SCHEMA = vol.Schema({
HOMEASSISTANT_SERVIC_ACTION_SCHEMA = cv.Schema({
cv.GenerateID(): cv.use_variable_id(APIServer),
vol.Required(CONF_SERVICE): cv.string,
vol.Optional(CONF_DATA): vol.Schema({
vol.Optional(CONF_DATA): cv.Schema({
cv.string: cv.string,
}),
vol.Optional(CONF_DATA_TEMPLATE): vol.Schema({
vol.Optional(CONF_DATA_TEMPLATE): cv.Schema({
cv.string: cv.string,
}),
vol.Optional(CONF_VARIABLES): vol.Schema({
vol.Optional(CONF_VARIABLES): cv.Schema({
cv.string: cv.lambda_,
}),
})
@ACTION_REGISTRY.register(CONF_HOMEASSISTANT_SERVICE, HOMEASSISTANT_SERVIC_ACTION_SCHEMA)
def homeassistant_service_to_code(config, action_id, arg_type, template_arg):
def homeassistant_service_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_home_assistant_service_call_action(template_arg)
type = HomeAssistantServiceCallAction.template(arg_type)
type = HomeAssistantServiceCallAction.template(template_arg)
act = Pvariable(action_id, rhs, type=type)
add(act.set_service(config[CONF_SERVICE]))
if CONF_DATA in config:
@@ -86,3 +128,14 @@ def homeassistant_service_to_code(config, action_id, arg_type, template_arg):
datas.append(TemplatableKeyValuePair(key, value_))
add(act.set_variables(datas))
yield act
CONF_API_CONNECTED = 'api.connected'
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):
rhs = APIConnectedCondition.new(template_arg)
type = APIConnectedCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)

View File

@@ -9,10 +9,10 @@ from esphome.const import CONF_DELAYED_OFF, CONF_DELAYED_ON, CONF_DEVICE_CLASS,
CONF_HEARTBEAT, CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERT, CONF_INVERTED, \
CONF_LAMBDA, CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, \
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_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, StructInitializer, add, get_variable, process_lambda
from esphome.cpp_types import App, Component, Nameable, NoArg, Trigger, bool_, esphome_ns, optional
from esphome.cpp_types import App, Component, Nameable, Trigger, bool_, esphome_ns, optional
from esphome.py_compat import string_types
DEVICE_CLASSES = [
@@ -32,11 +32,11 @@ BinarySensorPtr = BinarySensor.operator('ptr')
MQTTBinarySensorComponent = binary_sensor_ns.class_('MQTTBinarySensorComponent', mqtt.MQTTComponent)
# Triggers
PressTrigger = binary_sensor_ns.class_('PressTrigger', Trigger.template(NoArg))
ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', Trigger.template(NoArg))
ClickTrigger = binary_sensor_ns.class_('ClickTrigger', Trigger.template(NoArg))
DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', Trigger.template(NoArg))
MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', Trigger.template(NoArg), Component)
PressTrigger = binary_sensor_ns.class_('PressTrigger', Trigger.template())
ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', Trigger.template())
ClickTrigger = binary_sensor_ns.class_('ClickTrigger', Trigger.template())
DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', Trigger.template())
MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', Trigger.template(), Component)
MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent')
StateTrigger = binary_sensor_ns.class_('StateTrigger', Trigger.template(bool_))
@@ -62,7 +62,7 @@ FILTERS_SCHEMA = cv.ensure_list({
vol.Optional(CONF_HEARTBEAT): cv.invalid("The heartbeat filter has been removed in 1.11.0"),
}, cv.has_exactly_one_key(*FILTER_KEYS))
MULTI_CLICK_TIMING_SCHEMA = vol.Schema({
MULTI_CLICK_TIMING_SCHEMA = cv.Schema({
vol.Optional(CONF_STATE): cv.boolean,
vol.Optional(CONF_MIN_LENGTH): cv.positive_time_period_milliseconds,
vol.Optional(CONF_MAX_LENGTH): cv.positive_time_period_milliseconds,
@@ -234,23 +234,23 @@ def setup_binary_sensor_core_(binary_sensor_var, config):
for conf in config.get(CONF_ON_PRESS, []):
rhs = binary_sensor_var.make_press_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
for conf in config.get(CONF_ON_RELEASE, []):
rhs = binary_sensor_var.make_release_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
for conf in config.get(CONF_ON_CLICK, []):
rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH])
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
for conf in config.get(CONF_ON_DOUBLE_CLICK, []):
rhs = binary_sensor_var.make_double_click_trigger(conf[CONF_MIN_LENGTH],
conf[CONF_MAX_LENGTH])
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
for conf in config.get(CONF_ON_MULTI_CLICK, []):
timings = []
@@ -265,12 +265,12 @@ def setup_binary_sensor_core_(binary_sensor_var, config):
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
if CONF_INVALID_COOLDOWN in conf:
add(trigger.set_invalid_cooldown(conf[CONF_INVALID_COOLDOWN]))
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
for conf in config.get(CONF_ON_STATE, []):
rhs = binary_sensor_var.make_state_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, bool_, conf)
automation.build_automations(trigger, [(bool_, 'x')], conf)
setup_mqtt_component(binary_sensor_var.Pget_mqtt(), config)
@@ -287,43 +287,35 @@ def register_binary_sensor(var, config):
CORE.add_job(setup_binary_sensor_core_, binary_sensor_var, config)
def core_to_hass_config(data, config):
ret = mqtt.build_hass_config(data, 'binary_sensor', config,
include_state=True, include_command=False)
if ret is None:
return None
if CONF_DEVICE_CLASS in config:
ret['device_class'] = config[CONF_DEVICE_CLASS]
return ret
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
CONF_BINARY_SENSOR_IS_ON = 'binary_sensor.is_on'
BINARY_SENSOR_IS_ON_CONDITION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinarySensor),
vol.Optional(CONF_FOR): cv.positive_time_period_milliseconds,
})
@CONDITION_REGISTRY.register(CONF_BINARY_SENSOR_IS_ON, BINARY_SENSOR_IS_ON_CONDITION_SCHEMA)
def binary_sensor_is_on_to_code(config, condition_id, arg_type, template_arg):
def binary_sensor_is_on_to_code(config, condition_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_binary_sensor_is_on_condition(template_arg)
type = BinarySensorCondition.template(arg_type)
rhs = var.make_binary_sensor_is_on_condition(template_arg, config.get(CONF_FOR))
type = BinarySensorCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
CONF_BINARY_SENSOR_IS_OFF = 'binary_sensor.is_off'
BINARY_SENSOR_IS_OFF_CONDITION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinarySensor),
vol.Optional(CONF_FOR): cv.positive_time_period_milliseconds,
})
@CONDITION_REGISTRY.register(CONF_BINARY_SENSOR_IS_OFF, BINARY_SENSOR_IS_OFF_CONDITION_SCHEMA)
def binary_sensor_is_off_to_code(config, condition_id, arg_type, template_arg):
def binary_sensor_is_off_to_code(config, condition_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_binary_sensor_is_off_condition(template_arg)
type = BinarySensorCondition.template(arg_type)
rhs = var.make_binary_sensor_is_off_condition(template_arg, config.get(CONF_FOR))
type = BinarySensorCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)

View File

@@ -30,7 +30,3 @@ def to_code(config):
func = getattr(hub, DIRECTIONS[config[CONF_DIRECTION]])
rhs = func(config[CONF_NAME])
binary_sensor.register_binary_sensor(rhs, config)
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -33,7 +33,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_CUSTOM_BINARY_SENSOR'
def to_hass_config(data, config):
return [binary_sensor.core_to_hass_config(data, sens) for sens in config[CONF_BINARY_SENSORS]]

View File

@@ -23,7 +23,3 @@ def to_code(config):
yield
rhs = hub.make_presence_sensor(config[CONF_NAME], make_address_array(config[CONF_MAC_ADDRESS]))
binary_sensor.register_binary_sensor(rhs, config)
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -56,7 +56,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_ESP32_TOUCH_BINARY_SENSOR'
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -29,7 +29,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_GPIO_BINARY_SENSOR'
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -24,7 +24,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_HOMEASSISTANT_BINARY_SENSOR'
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -0,0 +1,24 @@
import voluptuous as vol
from esphome.components import binary_sensor
from esphome.components.mpr121 import MPR121Component, CONF_MPR121_ID
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_NAME
from esphome.cpp_generator import get_variable
DEPENDENCIES = ['mpr121']
MPR121Channel = binary_sensor.binary_sensor_ns.class_(
'MPR121Channel', binary_sensor.BinarySensor)
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(MPR121Channel),
cv.GenerateID(CONF_MPR121_ID): cv.use_variable_id(MPR121Component),
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=11))
}))
def to_code(config):
for hub in get_variable(config[CONF_MPR121_ID]):
yield
rhs = MPR121Channel.new(config[CONF_NAME], config[CONF_CHANNEL])
binary_sensor.register_binary_sensor(hub.add_channel(rhs), config)

View File

@@ -27,7 +27,3 @@ def to_code(config):
rhs = hub.make_touch_component(config[CONF_NAME], config[CONF_PAGE_ID],
config[CONF_COMPONENT_ID])
binary_sensor.register_binary_sensor(rhs, config)
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -43,7 +43,3 @@ def to_code(config):
addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')]
rhs = hub.make_tag(config[CONF_NAME], addr)
binary_sensor.register_binary_sensor(rhs, config)
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -24,7 +24,3 @@ def to_code(config):
yield
rhs = hub.make_card(config[CONF_NAME], config[CONF_UID])
binary_sensor.register_binary_sensor(rhs, config)
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -41,7 +41,7 @@ RCSwitchTypeDReceiver = remote_ns.class_('RCSwitchTypeDReceiver', RCSwitchRawRec
def validate_raw(value):
if isinstance(value, dict):
return vol.Schema({
return cv.Schema({
cv.GenerateID(): cv.declare_variable_id(int32),
vol.Required(CONF_DATA): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)],
})(value)
@@ -52,29 +52,29 @@ def validate_raw(value):
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(RemoteReceiver),
vol.Optional(CONF_JVC): vol.Schema({
vol.Optional(CONF_JVC): cv.Schema({
vol.Required(CONF_DATA): cv.hex_uint32_t,
}),
vol.Optional(CONF_LG): vol.Schema({
vol.Optional(CONF_LG): cv.Schema({
vol.Required(CONF_DATA): cv.hex_uint32_t,
vol.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True),
}),
vol.Optional(CONF_NEC): vol.Schema({
vol.Optional(CONF_NEC): cv.Schema({
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
}),
vol.Optional(CONF_SAMSUNG): vol.Schema({
vol.Optional(CONF_SAMSUNG): cv.Schema({
vol.Required(CONF_DATA): cv.hex_uint32_t,
}),
vol.Optional(CONF_SONY): vol.Schema({
vol.Optional(CONF_SONY): cv.Schema({
vol.Required(CONF_DATA): cv.hex_uint32_t,
vol.Optional(CONF_NBITS, default=12): cv.one_of(12, 15, 20, int=True),
}),
vol.Optional(CONF_PANASONIC): vol.Schema({
vol.Optional(CONF_PANASONIC): cv.Schema({
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
vol.Required(CONF_COMMAND): cv.hex_uint32_t,
}),
vol.Optional(CONF_RC5): vol.Schema({
vol.Optional(CONF_RC5): cv.Schema({
vol.Required(CONF_ADDRESS): vol.All(cv.hex_int, vol.Range(min=0, max=0x1F)),
vol.Required(CONF_COMMAND): vol.All(cv.hex_int, vol.Range(min=0, max=0x3F)),
}),
@@ -145,7 +145,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER'
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -22,7 +22,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_STATUS_BINARY_SENSOR'
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -36,7 +36,7 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_TEMPLATE_BINARY_SENSOR'
CONF_BINARY_SENSOR_TEMPLATE_PUBLISH = 'binary_sensor.template.publish'
BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.use_variable_id(binary_sensor.BinarySensor),
vol.Required(CONF_STATE): cv.templatable(cv.boolean),
})
@@ -44,17 +44,13 @@ BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_BINARY_SENSOR_TEMPLATE_PUBLISH,
BINARY_SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA)
def binary_sensor_template_publish_to_code(config, action_id, arg_type, template_arg):
def binary_sensor_template_publish_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_binary_sensor_publish_action(template_arg)
type = BinarySensorPublishAction.template(arg_type)
type = BinarySensorPublishAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for template_ in templatable(config[CONF_STATE], arg_type, bool_):
for template_ in templatable(config[CONF_STATE], args, bool_):
yield None
add(action.set_state(template_))
yield action
def to_hass_config(data, config):
return binary_sensor.core_to_hass_config(data, config)

View File

@@ -60,11 +60,11 @@ COVER_OPEN_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_OPEN, COVER_OPEN_ACTION_SCHEMA)
def cover_open_to_code(config, action_id, arg_type, template_arg):
def cover_open_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_open_action(template_arg)
type = OpenAction.template(arg_type)
type = OpenAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -75,11 +75,11 @@ COVER_CLOSE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_CLOSE, COVER_CLOSE_ACTION_SCHEMA)
def cover_close_to_code(config, action_id, arg_type, template_arg):
def cover_close_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_close_action(template_arg)
type = CloseAction.template(arg_type)
type = CloseAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -90,16 +90,9 @@ COVER_STOP_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_STOP, COVER_STOP_ACTION_SCHEMA)
def cover_stop_to_code(config, action_id, arg_type, template_arg):
def cover_stop_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_stop_action(template_arg)
type = StopAction.template(arg_type)
type = StopAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
def core_to_hass_config(data, config):
ret = mqtt.build_hass_config(data, 'cover', config, include_state=True, include_command=True)
if ret is None:
return None
return ret

View File

@@ -8,7 +8,7 @@ from esphome.const import CONF_ASSUMED_STATE, CONF_CLOSE_ACTION, CONF_ID, CONF_L
CONF_OPEN_ACTION, CONF_OPTIMISTIC, CONF_STATE, CONF_STOP_ACTION
from esphome.cpp_generator import Pvariable, add, get_variable, process_lambda, templatable
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import Action, App, NoArg, optional
from esphome.cpp_types import Action, App, optional
from esphome.py_compat import string_types
TemplateCover = cover.cover_ns.class_('TemplateCover', cover.Cover)
@@ -38,14 +38,14 @@ def to_code(config):
yield
add(var.set_state_lambda(template_))
if CONF_OPEN_ACTION in config:
automation.build_automation(var.get_open_trigger(), NoArg,
config[CONF_OPEN_ACTION])
automation.build_automations(var.get_open_trigger(), [],
config[CONF_OPEN_ACTION])
if CONF_CLOSE_ACTION in config:
automation.build_automation(var.get_close_trigger(), NoArg,
config[CONF_CLOSE_ACTION])
automation.build_automations(var.get_close_trigger(), [],
config[CONF_CLOSE_ACTION])
if CONF_STOP_ACTION in config:
automation.build_automation(var.get_stop_trigger(), NoArg,
config[CONF_STOP_ACTION])
automation.build_automations(var.get_stop_trigger(), [],
config[CONF_STOP_ACTION])
if CONF_OPTIMISTIC in config:
add(var.set_optimistic(config[CONF_OPTIMISTIC]))
if CONF_ASSUMED_STATE in config:
@@ -55,7 +55,7 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_TEMPLATE_COVER'
CONF_COVER_TEMPLATE_PUBLISH = 'cover.template.publish'
COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.use_variable_id(cover.Cover),
vol.Required(CONF_STATE): cv.templatable(cover.validate_cover_state),
})
@@ -63,26 +63,17 @@ COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_COVER_TEMPLATE_PUBLISH,
COVER_TEMPLATE_PUBLISH_ACTION_SCHEMA)
def cover_template_publish_to_code(config, action_id, arg_type, template_arg):
def cover_template_publish_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_cover_publish_action(template_arg)
type = CoverPublishAction.template(arg_type)
type = CoverPublishAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
state = config[CONF_STATE]
if isinstance(state, string_types):
template_ = cover.COVER_STATES[state]
else:
for template_ in templatable(state, arg_type, cover.CoverState):
for template_ in templatable(state, args, cover.CoverState):
yield None
add(action.set_state(template_))
yield action
def to_hass_config(data, config):
ret = cover.core_to_hass_config(data, config)
if ret is None:
return None
if CONF_OPTIMISTIC in config:
ret['optimistic'] = config[CONF_OPTIMISTIC]
return ret

View File

@@ -9,10 +9,10 @@ from esphome.cpp_types import Component, ComponentPtr, esphome_ns, std_vector
CustomComponentConstructor = esphome_ns.class_('CustomComponentConstructor')
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_COMPONENTS): cv.ensure_list(vol.Schema({
vol.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(Component)
}).extend(cv.COMPONENT_SCHEMA.schema)),
})

View File

@@ -11,7 +11,7 @@ from esphome.cpp_types import App, PollingComponent
DallasComponent = sensor.sensor_ns.class_('DallasComponent', PollingComponent)
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DallasComponent),
vol.Required(CONF_PIN): pins.input_pin,
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,

View File

@@ -1,11 +1,10 @@
import voluptuous as vol
import esphome.config_validation as cv
from esphome.cpp_generator import add
from esphome.cpp_types import App
DEPENDENCIES = ['logger']
CONFIG_SCHEMA = vol.Schema({})
CONFIG_SCHEMA = cv.Schema({})
def to_code(config):

View File

@@ -38,14 +38,14 @@ EXT1_WAKEUP_MODES = {
CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup'
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent),
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
validate_pin_number),
vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32,
cv.one_of(*WAKEUP_PIN_MODES), upper=True),
vol.Optional(CONF_ESP32_EXT1_WAKEUP): vol.All(cv.only_on_esp32, vol.Schema({
vol.Optional(CONF_ESP32_EXT1_WAKEUP): vol.All(cv.only_on_esp32, cv.Schema({
vol.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number),
vol.Required(CONF_MODE): cv.one_of(*EXT1_WAKEUP_MODES, upper=True),
})),
@@ -95,11 +95,11 @@ DEEP_SLEEP_ENTER_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DEEP_SLEEP_ENTER, DEEP_SLEEP_ENTER_ACTION_SCHEMA)
def deep_sleep_enter_to_code(config, action_id, arg_type, template_arg):
def deep_sleep_enter_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_enter_deep_sleep_action(template_arg)
type = EnterDeepSleepAction.template(arg_type)
type = EnterDeepSleepAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -110,9 +110,9 @@ DEEP_SLEEP_PREVENT_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DEEP_SLEEP_PREVENT, DEEP_SLEEP_PREVENT_ACTION_SCHEMA)
def deep_sleep_prevent_to_code(config, action_id, arg_type, template_arg):
def deep_sleep_prevent_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_prevent_deep_sleep_action(template_arg)
type = PreventDeepSleepAction.template(arg_type)
type = PreventDeepSleepAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)

View File

@@ -78,11 +78,11 @@ DISPLAY_PAGE_SHOW_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW, DISPLAY_PAGE_SHOW_ACTION_SCHEMA)
def display_page_show_to_code(config, action_id, arg_type, template_arg):
type = DisplayPageShowAction.template(arg_type)
def display_page_show_to_code(config, action_id, template_arg, args):
type = DisplayPageShowAction.template(template_arg)
action = Pvariable(action_id, type.new(), type=type)
if isinstance(config[CONF_ID], core.Lambda):
for template_ in templatable(config[CONF_ID], arg_type, DisplayPagePtr):
for template_ in templatable(config[CONF_ID], args, DisplayPagePtr):
yield None
add(action.set_page(template_))
else:
@@ -99,10 +99,10 @@ DISPLAY_PAGE_SHOW_NEXT_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW_NEXT, DISPLAY_PAGE_SHOW_NEXT_ACTION_SCHEMA)
def display_page_show_next_to_code(config, action_id, arg_type, template_arg):
def display_page_show_next_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
type = DisplayPageShowNextAction.template(arg_type)
type = DisplayPageShowNextAction.template(template_arg)
yield Pvariable(action_id, type.new(var), type=type)
@@ -113,10 +113,10 @@ DISPLAY_PAGE_SHOW_PREVIOUS_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DISPLAY_PAGE_SHOW_PREVIOUS, DISPLAY_PAGE_SHOW_PREVIOUS_ACTION_SCHEMA)
def display_page_show_previous_to_code(config, action_id, arg_type, template_arg):
def display_page_show_previous_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
type = DisplayPageShowPrevAction.template(arg_type)
type = DisplayPageShowPrevAction.template(template_arg)
yield Pvariable(action_id, type.new(var), type=type)

View File

@@ -7,13 +7,14 @@ from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, Component, esphome_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
CONFLICTS_WITH = ['esp32_ble_tracker']
ESP32BLEBeacon = esphome_ns.class_('ESP32BLEBeacon', Component)
CONF_MAJOR = 'major'
CONF_MINOR = 'minor'
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32BLEBeacon),
vol.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True),
vol.Required(CONF_UUID): cv.uuid,

View File

@@ -18,7 +18,7 @@ XIAOMI_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(XiaomiSensor)
})
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker),
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_seconds,
}).extend(cv.COMPONENT_SCHEMA.schema)

View File

@@ -0,0 +1,130 @@
import voluptuous as vol
from esphome import config_validation as cv, pins
from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NAME, CONF_PIN, CONF_SCL, CONF_SDA, \
ESP_PLATFORM_ESP32
from esphome.cpp_generator import Pvariable, add
from esphome.cpp_types import App, Nameable, PollingComponent, esphome_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
ESP32Camera = esphome_ns.class_('ESP32Camera', PollingComponent, Nameable)
ESP32CameraFrameSize = esphome_ns.enum('ESP32CameraFrameSize')
FRAME_SIZES = {
'160X120': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120,
'QQVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120,
'128x160': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160,
'QQVGA2': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160,
'176X144': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144,
'QCIF': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144,
'240X176': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176,
'HQVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176,
'320X240': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240,
'QVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240,
'400X296': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296,
'CIF': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296,
'640X480': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480,
'VGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480,
'800X600': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600,
'SVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600,
'1024X768': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768,
'XGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768,
'1280x1024': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024,
'SXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024,
'1600X1200': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200,
'UXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200,
}
CONF_DATA_PINS = 'data_pins'
CONF_VSYNC_PIN = 'vsync_pin'
CONF_HREF_PIN = 'href_pin'
CONF_PIXEL_CLOCK_PIN = 'pixel_clock_pin'
CONF_EXTERNAL_CLOCK = 'external_clock'
CONF_I2C_PINS = 'i2c_pins'
CONF_RESET_PIN = 'reset_pin'
CONF_POWER_DOWN_PIN = 'power_down_pin'
CONF_MAX_FRAMERATE = 'max_framerate'
CONF_IDLE_FRAMERATE = 'idle_framerate'
CONF_RESOLUTION = 'resolution'
CONF_JPEG_QUALITY = 'jpeg_quality'
CONF_VERTICAL_FLIP = 'vertical_flip'
CONF_HORIZONTAL_MIRROR = 'horizontal_mirror'
CONF_CONTRAST = 'contrast'
CONF_BRIGHTNESS = 'brightness'
CONF_SATURATION = 'saturation'
CONF_TEST_PATTERN = 'test_pattern'
camera_range_param = vol.All(cv.int_, vol.Range(min=-2, max=2))
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32Camera),
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_DATA_PINS): vol.All([pins.input_pin], vol.Length(min=8, max=8)),
vol.Required(CONF_VSYNC_PIN): pins.input_pin,
vol.Required(CONF_HREF_PIN): pins.input_pin,
vol.Required(CONF_PIXEL_CLOCK_PIN): pins.input_pin,
vol.Required(CONF_EXTERNAL_CLOCK): cv.Schema({
vol.Required(CONF_PIN): pins.output_pin,
vol.Optional(CONF_FREQUENCY, default='20MHz'): vol.All(cv.frequency, vol.In([20e6, 10e6])),
}),
vol.Required(CONF_I2C_PINS): cv.Schema({
vol.Required(CONF_SDA): pins.output_pin,
vol.Required(CONF_SCL): pins.output_pin,
}),
vol.Optional(CONF_RESET_PIN): pins.output_pin,
vol.Optional(CONF_POWER_DOWN_PIN): pins.output_pin,
vol.Optional(CONF_MAX_FRAMERATE, default='10 fps'): vol.All(cv.framerate,
vol.Range(min=0, min_included=False,
max=60)),
vol.Optional(CONF_IDLE_FRAMERATE, default='0.1 fps'): vol.All(cv.framerate,
vol.Range(min=0, max=1)),
vol.Optional(CONF_RESOLUTION, default='640X480'): cv.one_of(*FRAME_SIZES, upper=True),
vol.Optional(CONF_JPEG_QUALITY, default=10): vol.All(cv.int_, vol.Range(min=10, max=63)),
vol.Optional(CONF_CONTRAST, default=0): camera_range_param,
vol.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
vol.Optional(CONF_SATURATION, default=0): camera_range_param,
vol.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean,
vol.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean,
vol.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
}).extend(cv.COMPONENT_SCHEMA.schema)
SETTERS = {
CONF_DATA_PINS: 'set_data_pins',
CONF_VSYNC_PIN: 'set_vsync_pin',
CONF_HREF_PIN: 'set_href_pin',
CONF_PIXEL_CLOCK_PIN: 'set_pixel_clock_pin',
CONF_RESET_PIN: 'set_reset_pin',
CONF_POWER_DOWN_PIN: 'set_power_down_pin',
CONF_JPEG_QUALITY: 'set_jpeg_quality',
CONF_VERTICAL_FLIP: 'set_vertical_flip',
CONF_HORIZONTAL_MIRROR: 'set_horizontal_mirror',
CONF_CONTRAST: 'set_contrast',
CONF_BRIGHTNESS: 'set_brightness',
CONF_SATURATION: 'set_saturation',
CONF_TEST_PATTERN: 'set_test_pattern',
}
def to_code(config):
rhs = App.register_component(ESP32Camera.new(config[CONF_NAME]))
cam = Pvariable(config[CONF_ID], rhs)
for key, setter in SETTERS.items():
if key in config:
add(getattr(cam, setter)(config[key]))
extclk = config[CONF_EXTERNAL_CLOCK]
add(cam.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
i2c_pins = config[CONF_I2C_PINS]
add(cam.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
add(cam.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
if config[CONF_IDLE_FRAMERATE] == 0:
add(cam.set_idle_update_interval(0))
else:
add(cam.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE]))
add(cam.set_frame_size(FRAME_SIZES[config[CONF_RESOLUTION]]))
BUILD_FLAGS = ['-DUSE_ESP32_CAMERA', '-DBOARD_HAS_PSRAM']

View File

@@ -46,7 +46,7 @@ VOLTAGE_ATTENUATION = {
ESP32TouchComponent = binary_sensor.binary_sensor_ns.class_('ESP32TouchComponent', Component)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent),
vol.Optional(CONF_SETUP_MODE): cv.boolean,
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,

View File

@@ -46,7 +46,7 @@ def validate(config):
return config
CONFIG_SCHEMA = vol.All(vol.Schema({
CONFIG_SCHEMA = vol.All(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(EthernetComponent),
vol.Required(CONF_TYPE): cv.one_of(*ETHERNET_TYPES, upper=True),
vol.Required(CONF_MDC_PIN): pins.output_pin,

View File

@@ -4,9 +4,9 @@ from esphome.automation import ACTION_REGISTRY, maybe_simple_id
from esphome.components import mqtt
from esphome.components.mqtt import setup_mqtt_component
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_NAME, CONF_OSCILLATING, \
CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_OUTPUT, CONF_OSCILLATION_STATE_TOPIC, \
CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_OSCILLATING, \
CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED, \
CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, add, get_variable, templatable
from esphome.cpp_types import Action, Application, Component, Nameable, bool_, esphome_ns
@@ -81,11 +81,11 @@ FAN_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TOGGLE, FAN_TOGGLE_ACTION_SCHEMA)
def fan_toggle_to_code(config, action_id, arg_type, template_arg):
def fan_toggle_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_toggle_action(template_arg)
type = ToggleAction.template(arg_type)
type = ToggleAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -96,11 +96,11 @@ FAN_TURN_OFF_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TURN_OFF, FAN_TURN_OFF_ACTION_SCHEMA)
def fan_turn_off_to_code(config, action_id, arg_type, template_arg):
def fan_turn_off_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
type = TurnOffAction.template(arg_type)
type = TurnOffAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -113,32 +113,20 @@ FAN_TURN_ON_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TURN_ON, FAN_TURN_ON_ACTION_SCHEMA)
def fan_turn_on_to_code(config, action_id, arg_type, template_arg):
def fan_turn_on_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
type = TurnOnAction.template(arg_type)
type = TurnOnAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_OSCILLATING in config:
for template_ in templatable(config[CONF_OSCILLATING], arg_type, bool_):
for template_ in templatable(config[CONF_OSCILLATING], args, bool_):
yield None
add(action.set_oscillating(template_))
if CONF_SPEED in config:
for template_ in templatable(config[CONF_SPEED], arg_type, FanSpeed):
for template_ in templatable(config[CONF_SPEED], args, FanSpeed):
yield None
if isinstance(template_, string_types):
template_ = FAN_SPEEDS[template_]
add(action.set_speed(template_))
yield action
def core_to_hass_config(data, config):
ret = mqtt.build_hass_config(data, 'fan', config, include_state=True, include_command=True)
if ret is None:
return None
if CONF_OSCILLATION_OUTPUT in config:
default = mqtt.get_default_topic_for(data, 'fan', config[CONF_NAME], 'oscillation/state')
ret['oscillation_state_topic'] = config.get(CONF_OSCILLATION_STATE_TOPIC, default)
default = mqtt.get_default_topic_for(data, 'fan', config[CONF_NAME], 'oscillation/command')
ret['oscillation_command__topic'] = config.get(CONF_OSCILLATION_COMMAND_TOPIC, default)
return ret

View File

@@ -28,7 +28,3 @@ def to_code(config):
fan.setup_fan(fan_struct.Pstate, config)
setup_component(fan_struct.Poutput, config)
def to_hass_config(data, config):
return fan.core_to_hass_config(data, config)

View File

@@ -1,6 +1,6 @@
import voluptuous as vol
from esphome.components import fan, mqtt, output
from esphome.components import fan, output
import esphome.config_validation as cv
from esphome.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CONF_NAME, \
CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, \
@@ -14,7 +14,7 @@ PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput),
vol.Optional(CONF_SPEED): vol.Schema({
vol.Optional(CONF_SPEED): cv.Schema({
vol.Required(CONF_LOW): cv.percentage,
vol.Required(CONF_MEDIUM): cv.percentage,
vol.Required(CONF_HIGH): cv.percentage,
@@ -42,14 +42,3 @@ def to_code(config):
add(fan_struct.Poutput.set_oscillation(oscillation_output))
fan.setup_fan(fan_struct.Pstate, config)
def to_hass_config(data, config):
ret = fan.core_to_hass_config(data, config)
if ret is None:
return None
default = mqtt.get_default_topic_for(data, 'fan', config[CONF_NAME], 'speed/state')
ret['speed_state_topic'] = config.get(CONF_SPEED_STATE_TOPIC, default)
default = mqtt.get_default_topic_for(data, 'fan', config[CONF_NAME], 'speed/command')
ret['speed_command__topic'] = config.get(CONF_SPEED_COMMAND_TOPIC, default)
return ret

View File

@@ -19,8 +19,8 @@ Glyph = display.display_ns.class_('Glyph')
def validate_glyphs(value):
if isinstance(value, list):
value = vol.Schema([cv.string])(value)
value = vol.Schema([cv.string])(list(value))
value = cv.Schema([cv.string])(value)
value = cv.Schema([cv.string])(list(value))
def comparator(x, y):
x_ = x.encode('utf-8')
@@ -69,7 +69,7 @@ def validate_truetype_file(value):
DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
CONF_RAW_DATA_ID = 'raw_data_id'
FONT_SCHEMA = vol.Schema({
FONT_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(Font),
vol.Required(CONF_FILE): validate_truetype_file,
vol.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs,

View File

@@ -10,7 +10,7 @@ GlobalVariableComponent = esphome_ns.class_('GlobalVariableComponent', Component
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(GlobalVariableComponent),
vol.Required(CONF_TYPE): cv.string_strict,
vol.Optional(CONF_INITIAL_VALUE): cv.string_strict,

View File

@@ -11,12 +11,12 @@ from esphome.cpp_types import App, Component, esphome_ns
I2CComponent = esphome_ns.class_('I2CComponent', Component)
I2CDevice = pins.I2CDevice
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(I2CComponent),
vol.Optional(CONF_SDA, default='SDA'): pins.input_pin,
vol.Optional(CONF_SCL, default='SCL'): pins.input_pin,
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)),
vol.Optional(CONF_SCAN): cv.boolean,
vol.Optional(CONF_SCAN, default=True): cv.boolean,
vol.Optional(CONF_RECEIVE_TIMEOUT): cv.invalid("The receive_timeout option has been removed "
"because timeouts are already handled by the "

View File

@@ -20,7 +20,7 @@ Image_ = display.display_ns.class_('Image')
CONF_RAW_DATA_ID = 'raw_data_id'
IMAGE_SCHEMA = vol.Schema({
IMAGE_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(Image_),
vol.Required(CONF_FILE): cv.file_,
vol.Optional(CONF_RESIZE): cv.dimensions,

View File

@@ -5,11 +5,11 @@ import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INTERVAL
from esphome.cpp_generator import Pvariable
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, NoArg, PollingComponent, Trigger, esphome_ns
from esphome.cpp_types import App, PollingComponent, Trigger, esphome_ns
IntervalTrigger = esphome_ns.class_('IntervalTrigger', Trigger.template(NoArg), PollingComponent)
IntervalTrigger = esphome_ns.class_('IntervalTrigger', Trigger.template(), PollingComponent)
CONFIG_SCHEMA = automation.validate_automation(vol.Schema({
CONFIG_SCHEMA = automation.validate_automation(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(IntervalTrigger),
vol.Required(CONF_INTERVAL): cv.positive_time_period_milliseconds,
}).extend(cv.COMPONENT_SCHEMA.schema))
@@ -21,4 +21,4 @@ def to_code(config):
trigger = Pvariable(conf[CONF_ID], rhs)
setup_component(trigger, conf)
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)

View File

@@ -88,22 +88,22 @@ ADDRESSABLE_EFFECTS = RGB_EFFECTS + [CONF_ADDRESSABLE_LAMBDA, CONF_ADDRESSABLE_R
CONF_ADDRESSABLE_TWINKLE, CONF_ADDRESSABLE_RANDOM_TWINKLE,
CONF_ADDRESSABLE_FIREWORKS, CONF_ADDRESSABLE_FLICKER]
EFFECTS_SCHEMA = vol.Schema({
vol.Optional(CONF_LAMBDA): vol.Schema({
EFFECTS_SCHEMA = cv.Schema({
vol.Optional(CONF_LAMBDA): cv.Schema({
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_RANDOM): vol.Schema({
vol.Optional(CONF_RANDOM): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(RandomLightEffect),
vol.Optional(CONF_NAME, default="Random"): cv.string,
vol.Optional(CONF_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_STROBE): vol.Schema({
vol.Optional(CONF_STROBE): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(StrobeLightEffect),
vol.Optional(CONF_NAME, default="Strobe"): cv.string,
vol.Optional(CONF_COLORS): vol.All(cv.ensure_list(vol.Schema({
vol.Optional(CONF_COLORS): vol.All(cv.ensure_list(cv.Schema({
vol.Optional(CONF_STATE, default=True): cv.boolean,
vol.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage,
vol.Optional(CONF_RED, default=1.0): cv.percentage,
@@ -114,24 +114,24 @@ EFFECTS_SCHEMA = vol.Schema({
}), cv.has_at_least_one_key(CONF_STATE, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE,
CONF_WHITE)), vol.Length(min=2)),
}),
vol.Optional(CONF_FLICKER): vol.Schema({
vol.Optional(CONF_FLICKER): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FlickerLightEffect),
vol.Optional(CONF_NAME, default="Flicker"): cv.string,
vol.Optional(CONF_ALPHA): cv.percentage,
vol.Optional(CONF_INTENSITY): cv.percentage,
}),
vol.Optional(CONF_ADDRESSABLE_LAMBDA): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_LAMBDA): cv.Schema({
vol.Required(CONF_NAME): cv.string,
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_ADDRESSABLE_RAINBOW): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_RAINBOW): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableRainbowLightEffect),
vol.Optional(CONF_NAME, default="Rainbow"): cv.string,
vol.Optional(CONF_SPEED): cv.uint32_t,
vol.Optional(CONF_WIDTH): cv.uint32_t,
}),
vol.Optional(CONF_ADDRESSABLE_COLOR_WIPE): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_COLOR_WIPE): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableColorWipeEffect),
vol.Optional(CONF_NAME, default="Color Wipe"): cv.string,
vol.Optional(CONF_COLORS): cv.ensure_list({
@@ -145,24 +145,24 @@ EFFECTS_SCHEMA = vol.Schema({
vol.Optional(CONF_ADD_LED_INTERVAL): cv.positive_time_period_milliseconds,
vol.Optional(CONF_REVERSE): cv.boolean,
}),
vol.Optional(CONF_ADDRESSABLE_SCAN): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_SCAN): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableScanEffect),
vol.Optional(CONF_NAME, default="Scan"): cv.string,
vol.Optional(CONF_MOVE_INTERVAL): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_ADDRESSABLE_TWINKLE): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_TWINKLE): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableTwinkleEffect),
vol.Optional(CONF_NAME, default="Twinkle"): cv.string,
vol.Optional(CONF_TWINKLE_PROBABILITY): cv.percentage,
vol.Optional(CONF_PROGRESS_INTERVAL): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_ADDRESSABLE_RANDOM_TWINKLE): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_RANDOM_TWINKLE): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableRandomTwinkleEffect),
vol.Optional(CONF_NAME, default="Random Twinkle"): cv.string,
vol.Optional(CONF_TWINKLE_PROBABILITY): cv.percentage,
vol.Optional(CONF_PROGRESS_INTERVAL): cv.positive_time_period_milliseconds,
}),
vol.Optional(CONF_ADDRESSABLE_FIREWORKS): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_FIREWORKS): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableFireworksEffect),
vol.Optional(CONF_NAME, default="Fireworks"): cv.string,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
@@ -170,7 +170,7 @@ EFFECTS_SCHEMA = vol.Schema({
vol.Optional(CONF_USE_RANDOM_COLOR): cv.boolean,
vol.Optional(CONF_FADE_OUT_RATE): cv.uint8_t,
}),
vol.Optional(CONF_ADDRESSABLE_FLICKER): vol.Schema({
vol.Optional(CONF_ADDRESSABLE_FLICKER): cv.Schema({
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(AddressableFlickerEffect),
vol.Optional(CONF_NAME, default="Addressable Flicker"): cv.string,
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
@@ -404,14 +404,14 @@ LIGHT_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TOGGLE, LIGHT_TOGGLE_ACTION_SCHEMA)
def light_toggle_to_code(config, action_id, arg_type, template_arg):
def light_toggle_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_toggle_action(template_arg)
type = ToggleAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_TRANSITION_LENGTH in config:
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
for template_ in templatable(config[CONF_TRANSITION_LENGTH], args, uint32):
yield None
add(action.set_transition_length(template_))
yield action
@@ -425,14 +425,14 @@ LIGHT_TURN_OFF_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TURN_OFF, LIGHT_TURN_OFF_ACTION_SCHEMA)
def light_turn_off_to_code(config, action_id, arg_type, template_arg):
def light_turn_off_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
type = TurnOffAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_TRANSITION_LENGTH in config:
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
for template_ in templatable(config[CONF_TRANSITION_LENGTH], args, uint32):
yield None
add(action.set_transition_length(template_))
yield action
@@ -456,67 +456,46 @@ LIGHT_TURN_ON_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TURN_ON, LIGHT_TURN_ON_ACTION_SCHEMA)
def light_turn_on_to_code(config, action_id, arg_type, template_arg):
def light_turn_on_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
type = TurnOnAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
if CONF_TRANSITION_LENGTH in config:
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
for template_ in templatable(config[CONF_TRANSITION_LENGTH], args, uint32):
yield None
add(action.set_transition_length(template_))
if CONF_FLASH_LENGTH in config:
for template_ in templatable(config[CONF_FLASH_LENGTH], arg_type, uint32):
for template_ in templatable(config[CONF_FLASH_LENGTH], args, uint32):
yield None
add(action.set_flash_length(template_))
if CONF_BRIGHTNESS in config:
for template_ in templatable(config[CONF_BRIGHTNESS], arg_type, float_):
for template_ in templatable(config[CONF_BRIGHTNESS], args, float_):
yield None
add(action.set_brightness(template_))
if CONF_RED in config:
for template_ in templatable(config[CONF_RED], arg_type, float_):
for template_ in templatable(config[CONF_RED], args, float_):
yield None
add(action.set_red(template_))
if CONF_GREEN in config:
for template_ in templatable(config[CONF_GREEN], arg_type, float_):
for template_ in templatable(config[CONF_GREEN], args, float_):
yield None
add(action.set_green(template_))
if CONF_BLUE in config:
for template_ in templatable(config[CONF_BLUE], arg_type, float_):
for template_ in templatable(config[CONF_BLUE], args, float_):
yield None
add(action.set_blue(template_))
if CONF_WHITE in config:
for template_ in templatable(config[CONF_WHITE], arg_type, float_):
for template_ in templatable(config[CONF_WHITE], args, float_):
yield None
add(action.set_white(template_))
if CONF_COLOR_TEMPERATURE in config:
for template_ in templatable(config[CONF_COLOR_TEMPERATURE], arg_type, float_):
for template_ in templatable(config[CONF_COLOR_TEMPERATURE], args, float_):
yield None
add(action.set_color_temperature(template_))
if CONF_EFFECT in config:
for template_ in templatable(config[CONF_EFFECT], arg_type, std_string):
for template_ in templatable(config[CONF_EFFECT], args, std_string):
yield None
add(action.set_effect(template_))
yield action
def core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=True,
white_value=True):
ret = mqtt.build_hass_config(data, 'light', config, include_state=True, include_command=True)
if ret is None:
return None
ret['schema'] = 'json'
if brightness:
ret['brightness'] = True
if rgb:
ret['rgb'] = True
if color_temp:
ret['color_temp'] = True
if white_value:
ret['white_value'] = True
for effect in config.get(CONF_EFFECTS, []):
ret["effect"] = True
effects = ret.setdefault("effect_list", [])
effects.append(next(x for x in effect.values())[CONF_NAME])
return ret

View File

@@ -21,8 +21,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=False, rgb=False, color_temp=False,
white_value=False)

View File

@@ -35,8 +35,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=False, color_temp=True,
white_value=False)

View File

@@ -106,8 +106,3 @@ def to_code(config):
REQUIRED_BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
LIB_DEPS = 'FastLED@3.2.0'
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,
white_value=False)

View File

@@ -86,8 +86,3 @@ def to_code(config):
REQUIRED_BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
LIB_DEPS = 'FastLED@3.2.0'
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,
white_value=False)

View File

@@ -24,8 +24,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=False, color_temp=False,
white_value=False)

View File

@@ -188,8 +188,3 @@ def to_code(config):
REQUIRED_BUILD_FLAGS = '-DUSE_NEO_PIXEL_BUS_LIGHT'
LIB_DEPS = 'NeoPixelBus@2.4.1'
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,
white_value='W' in config[CONF_TYPE])

View File

@@ -46,7 +46,3 @@ def to_code(config):
rhs = App.make_partition_light(config[CONF_NAME], segments)
make = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(make.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False)

View File

@@ -30,8 +30,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,
white_value=False)

View File

@@ -33,8 +33,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,
white_value=True)

View File

@@ -63,8 +63,3 @@ def to_code(config):
light_struct = variable(config[CONF_MAKE_ID], rhs)
light.setup_light(light_struct.Pstate, config)
setup_component(light_struct.Pstate, config)
def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=True,
white_value=True)

View File

@@ -73,13 +73,13 @@ def validate_local_no_higher_than_global(value):
LogComponent = esphome_ns.class_('LogComponent', Component)
CONFIG_SCHEMA = vol.All(vol.Schema({
CONFIG_SCHEMA = vol.All(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(LogComponent),
vol.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
vol.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes,
vol.Optional(CONF_HARDWARE_UART, default='UART0'): uart_selection,
vol.Optional(CONF_LEVEL): is_log_level,
vol.Optional(CONF_LOGS): vol.Schema({
vol.Optional(CONF_LOGS): cv.Schema({
cv.string: is_log_level,
})
}), validate_local_no_higher_than_global)
@@ -102,7 +102,9 @@ def required_build_flags(config):
flags.append(u'-DESPHOME_LOG_LEVEL={}'.format(str(LOG_LEVELS[config[CONF_LEVEL]])))
this_severity = LOG_LEVEL_SEVERITY.index(config[CONF_LEVEL])
verbose_severity = LOG_LEVEL_SEVERITY.index('VERBOSE')
very_verbose_severity = LOG_LEVEL_SEVERITY.index('VERY_VERBOSE')
is_at_least_verbose = this_severity >= verbose_severity
is_at_least_very_verbose = this_severity >= very_verbose_severity
has_serial_logging = config.get(CONF_BAUD_RATE) != 0
if CORE.is_esp8266 and has_serial_logging and is_at_least_verbose:
debug_serial_port = HARDWARE_UART_TO_SERIAL[config.get(CONF_HARDWARE_UART)]
@@ -122,6 +124,8 @@ def required_build_flags(config):
flags.append(u"-DDEBUG_ESP_{}".format(comp))
if CORE.is_esp32 and is_at_least_verbose:
flags.append('-DCORE_DEBUG_LEVEL=5')
if CORE.is_esp32 and is_at_least_very_verbose:
flags.append('-DENABLE_I2C_DEBUG_BUFFER')
return flags
@@ -129,8 +133,8 @@ def required_build_flags(config):
def maybe_simple_message(schema):
def validator(value):
if isinstance(value, dict):
return vol.Schema(schema)(value)
return vol.Schema(schema)({CONF_FORMAT: value})
return cv.Schema(schema)(value)
return cv.Schema(schema)({CONF_FORMAT: value})
return validator
@@ -167,13 +171,13 @@ LOGGER_LOG_ACTION_SCHEMA = vol.All(maybe_simple_message({
@ACTION_REGISTRY.register(CONF_LOGGER_LOG, LOGGER_LOG_ACTION_SCHEMA)
def logger_log_action_to_code(config, action_id, arg_type, template_arg):
def logger_log_action_to_code(config, action_id, template_arg, args):
esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]]
args = [RawExpression(text_type(x)) for x in config[CONF_ARGS]]
args_ = [RawExpression(text_type(x)) for x in config[CONF_ARGS]]
text = text_type(statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args)))
text = text_type(statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_)))
for lambda_ in process_lambda(Lambda(text), [(arg_type, 'x')], return_type=void):
for lambda_ in process_lambda(Lambda(text), args, return_type=void):
yield None
rhs = LambdaAction.new(template_arg, lambda_)
type = LambdaAction.template(template_arg)

View File

@@ -0,0 +1,35 @@
import voluptuous as vol
from esphome import pins
import esphome.config_validation as cv
from esphome.const import CONF_ADDRESS, CONF_ID
from esphome.cpp_generator import Pvariable
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, GPIOInputPin, GPIOOutputPin, io_ns, esphome_ns
DEPENDENCIES = ['i2c']
MULTI_CONF = True
MCP23017GPIOMode = esphome_ns.enum('MCP23017GPIOMode')
MCP23017_GPIO_MODES = {
'INPUT': MCP23017GPIOMode.MCP23017_INPUT,
'INPUT_PULLUP': MCP23017GPIOMode.MCP23017_INPUT_PULLUP,
'OUTPUT': MCP23017GPIOMode.MCP23017_OUTPUT,
}
MCP23017GPIOInputPin = io_ns.class_('MCP23017GPIOInputPin', GPIOInputPin)
MCP23017GPIOOutputPin = io_ns.class_('MCP23017GPIOOutputPin', GPIOOutputPin)
CONFIG_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(pins.MCP23017),
vol.Optional(CONF_ADDRESS, default=0x20): cv.i2c_address,
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
rhs = App.make_mcp23017_component(config[CONF_ADDRESS])
var = Pvariable(config[CONF_ID], rhs)
setup_component(var, config)
BUILD_FLAGS = '-DUSE_MCP23017'

View File

@@ -0,0 +1,29 @@
import voluptuous as vol
from esphome.components import i2c, binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_ADDRESS, CONF_ID
from esphome.cpp_generator import Pvariable
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, Component
DEPENDENCIES = ['i2c']
MULTI_CONF = True
CONF_MPR121_ID = 'mpr121_id'
MPR121Component = binary_sensor.binary_sensor_ns.class_('MPR121Component', Component, i2c.I2CDevice)
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(MPR121Component),
vol.Optional(CONF_ADDRESS): cv.i2c_address
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
rhs = App.make_mpr121(config.get(CONF_ADDRESS))
var = Pvariable(config[CONF_ID], rhs)
setup_component(var, config)
BUILD_FLAGS = '-DUSE_MPR121'

View File

@@ -1,20 +1,18 @@
from collections import OrderedDict
import re
import voluptuous as vol
from esphome import automation
from esphome.automation import ACTION_REGISTRY
from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY, Condition
from esphome.components import logger
import esphome.config_validation as cv
from esphome.const import CONF_AVAILABILITY, CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, \
CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, \
CONF_ESPHOME, CONF_ID, CONF_INTERNAL, CONF_KEEPALIVE, CONF_LEVEL, CONF_LOG_TOPIC, \
CONF_MQTT, CONF_NAME, CONF_ON_JSON_MESSAGE, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, \
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, CONF_QOS, CONF_REBOOT_TIMEOUT, \
CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, CONF_STATE_TOPIC, CONF_TOPIC, \
CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, CONF_WILL_MESSAGE
from esphome.core import EsphomeError
CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, CONF_LOG_TOPIC, CONF_ON_JSON_MESSAGE, CONF_ON_MESSAGE, \
CONF_PASSWORD, CONF_PAYLOAD, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, \
CONF_QOS, CONF_REBOOT_TIMEOUT, CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, \
CONF_STATE_TOPIC, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \
CONF_WILL_MESSAGE
from esphome.cpp_generator import Pvariable, RawExpression, StructInitializer, TemplateArguments, \
add, get_variable, process_lambda, templatable
from esphome.cpp_types import Action, App, Component, JsonObjectConstRef, JsonObjectRef, \
@@ -26,7 +24,7 @@ def validate_message_just_topic(value):
return MQTT_MESSAGE_BASE({CONF_TOPIC: value})
MQTT_MESSAGE_BASE = vol.Schema({
MQTT_MESSAGE_BASE = cv.Schema({
vol.Required(CONF_TOPIC): cv.publish_topic,
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
vol.Optional(CONF_RETAIN, default=True): cv.boolean,
@@ -47,6 +45,7 @@ MQTTMessageTrigger = mqtt_ns.class_('MQTTMessageTrigger', Trigger.template(std_s
MQTTJsonMessageTrigger = mqtt_ns.class_('MQTTJsonMessageTrigger',
Trigger.template(JsonObjectConstRef))
MQTTComponent = mqtt_ns.class_('MQTTComponent', Component)
MQTTConnectedCondition = mqtt_ns.class_('MQTTConnectedCondition', Condition)
def validate_config(value):
@@ -67,7 +66,7 @@ def validate_fingerprint(value):
return value
CONFIG_SCHEMA = vol.All(vol.Schema({
CONFIG_SCHEMA = vol.All(cv.Schema({
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
vol.Required(CONF_BROKER): cv.string_strict,
vol.Optional(CONF_PORT): cv.port,
@@ -184,16 +183,16 @@ def to_code(config):
add(trigger.set_qos(conf[CONF_QOS]))
if CONF_PAYLOAD in conf:
add(trigger.set_payload(conf[CONF_PAYLOAD]))
automation.build_automation(trigger, std_string, conf)
automation.build_automations(trigger, [(std_string, 'x')], conf)
for conf in config.get(CONF_ON_JSON_MESSAGE, []):
rhs = mqtt.make_json_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS])
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, JsonObjectConstRef, conf)
automation.build_automations(trigger, [(JsonObjectConstRef, 'x')], conf)
CONF_MQTT_PUBLISH = 'mqtt.publish'
MQTT_PUBLISH_ACTION_SCHEMA = vol.Schema({
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema({
cv.GenerateID(): cv.use_variable_id(MQTTClientComponent),
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
vol.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload),
@@ -203,32 +202,32 @@ MQTT_PUBLISH_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_MQTT_PUBLISH, MQTT_PUBLISH_ACTION_SCHEMA)
def mqtt_publish_action_to_code(config, action_id, arg_type, template_arg):
def mqtt_publish_action_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_publish_action(template_arg)
type = MQTTPublishAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for template_ in templatable(config[CONF_TOPIC], arg_type, std_string):
for template_ in templatable(config[CONF_TOPIC], args, std_string):
yield None
add(action.set_topic(template_))
for template_ in templatable(config[CONF_PAYLOAD], arg_type, std_string):
for template_ in templatable(config[CONF_PAYLOAD], args, std_string):
yield None
add(action.set_payload(template_))
if CONF_QOS in config:
for template_ in templatable(config[CONF_QOS], arg_type, uint8):
for template_ in templatable(config[CONF_QOS], args, uint8):
yield
add(action.set_qos(template_))
if CONF_RETAIN in config:
for template_ in templatable(config[CONF_RETAIN], arg_type, bool_):
for template_ in templatable(config[CONF_RETAIN], args, bool_):
yield None
add(action.set_retain(template_))
yield action
CONF_MQTT_PUBLISH_JSON = 'mqtt.publish_json'
MQTT_PUBLISH_JSON_ACTION_SCHEMA = vol.Schema({
MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema({
cv.GenerateID(): cv.use_variable_id(MQTTClientComponent),
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
vol.Required(CONF_PAYLOAD): cv.lambda_,
@@ -238,18 +237,18 @@ MQTT_PUBLISH_JSON_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_MQTT_PUBLISH_JSON, MQTT_PUBLISH_JSON_ACTION_SCHEMA)
def mqtt_publish_json_action_to_code(config, action_id, arg_type, template_arg):
def mqtt_publish_json_action_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_publish_json_action(template_arg)
type = MQTTPublishJsonAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for template_ in templatable(config[CONF_TOPIC], arg_type, std_string):
for template_ in templatable(config[CONF_TOPIC], args, std_string):
yield None
add(action.set_topic(template_))
for lambda_ in process_lambda(config[CONF_PAYLOAD], [(arg_type, 'x'), (JsonObjectRef, 'root')],
return_type=void):
args_ = args + [(JsonObjectRef, 'root')]
for lambda_ in process_lambda(config[CONF_PAYLOAD], args_, return_type=void):
yield None
add(action.set_payload(lambda_))
if CONF_QOS in config:
@@ -272,61 +271,6 @@ def get_default_topic_for(data, component_type, name, suffix):
sanitized_name, suffix)
def build_hass_config(data, component_type, config, include_state=True, include_command=True):
if config.get(CONF_INTERNAL, False):
return None
ret = OrderedDict()
ret['platform'] = 'mqtt'
ret['name'] = config[CONF_NAME]
if include_state:
default = get_default_topic_for(data, component_type, config[CONF_NAME], 'state')
ret['state_topic'] = config.get(CONF_STATE_TOPIC, default)
if include_command:
default = get_default_topic_for(data, component_type, config[CONF_NAME], 'command')
ret['command_topic'] = config.get(CONF_STATE_TOPIC, default)
avail = config.get(CONF_AVAILABILITY, data.availability)
if avail:
ret['availability_topic'] = avail[CONF_TOPIC]
payload_available = avail[CONF_PAYLOAD_AVAILABLE]
if payload_available != 'online':
ret['payload_available'] = payload_available
payload_not_available = avail[CONF_PAYLOAD_NOT_AVAILABLE]
if payload_not_available != 'offline':
ret['payload_not_available'] = payload_not_available
return ret
class GenerateHassConfigData(object):
def __init__(self, config):
if 'mqtt' not in config:
raise EsphomeError("Cannot generate Home Assistant MQTT config if MQTT is not "
"used!")
mqtt = config[CONF_MQTT]
self.topic_prefix = mqtt.get(CONF_TOPIC_PREFIX, config[CONF_ESPHOME][CONF_NAME])
birth_message = mqtt.get(CONF_BIRTH_MESSAGE)
if CONF_BIRTH_MESSAGE not in mqtt:
birth_message = {
CONF_TOPIC: self.topic_prefix + '/status',
CONF_PAYLOAD: 'online',
}
will_message = mqtt.get(CONF_WILL_MESSAGE)
if CONF_WILL_MESSAGE not in mqtt:
will_message = {
CONF_TOPIC: self.topic_prefix + '/status',
CONF_PAYLOAD: 'offline'
}
if not birth_message or not will_message:
self.availability = None
elif birth_message[CONF_TOPIC] != will_message[CONF_TOPIC]:
self.availability = None
else:
self.availability = {
CONF_TOPIC: birth_message[CONF_TOPIC],
CONF_PAYLOAD_AVAILABLE: birth_message[CONF_PAYLOAD],
CONF_PAYLOAD_NOT_AVAILABLE: will_message[CONF_PAYLOAD],
}
def setup_mqtt_component(obj, config):
if CONF_RETAIN in config:
add(obj.set_retain(config[CONF_RETAIN]))
@@ -347,3 +291,13 @@ def setup_mqtt_component(obj, config):
LIB_DEPS = 'AsyncMqttClient@0.8.2'
BUILD_FLAGS = '-DUSE_MQTT'
CONF_MQTT_CONNECTED = 'mqtt.connected'
MQTT_CONNECTED_CONDITION_SCHEMA = cv.Schema({})
@CONDITION_REGISTRY.register(CONF_MQTT_CONNECTED, MQTT_CONNECTED_CONDITION_SCHEMA)
def mqtt_connected_to_code(config, condition_id, template_arg, args):
rhs = MQTTConnectedCondition.new(template_arg)
type = MQTTConnectedCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)

View File

@@ -12,7 +12,7 @@ from esphome.cpp_types import App, Component
MY9231OutputComponent = output.output_ns.class_('MY9231OutputComponent', Component)
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(MY9231OutputComponent),
vol.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema,
vol.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema,

View File

@@ -12,7 +12,7 @@ _LOGGER = logging.getLogger(__name__)
OTAComponent = esphome_ns.class_('OTAComponent', Component)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(OTAComponent),
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
vol.Optional(CONF_PORT): cv.port,

View File

@@ -3,7 +3,8 @@ import voluptuous as vol
from esphome.automation import ACTION_REGISTRY, maybe_simple_id
from esphome.components.power_supply import PowerSupplyComponent
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INVERTED, CONF_LEVEL, CONF_MAX_POWER, CONF_POWER_SUPPLY
from esphome.const import CONF_ID, CONF_INVERTED, CONF_LEVEL, CONF_MAX_POWER, \
CONF_MIN_POWER, CONF_POWER_SUPPLY
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, add, get_variable, templatable
from esphome.cpp_types import Action, esphome_ns, float_
@@ -12,7 +13,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
})
BINARY_OUTPUT_SCHEMA = vol.Schema({
BINARY_OUTPUT_SCHEMA = cv.Schema({
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
vol.Optional(CONF_INVERTED): cv.boolean,
})
@@ -21,6 +22,7 @@ BINARY_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_OUTPUT_SCHEMA.sche
FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({
vol.Optional(CONF_MAX_POWER): cv.percentage,
vol.Optional(CONF_MIN_POWER): cv.percentage,
})
FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema)
@@ -47,6 +49,8 @@ def setup_output_platform_(obj, config, skip_power_supply=False):
add(obj.set_power_supply(power_supply))
if CONF_MAX_POWER in config:
add(obj.set_max_power(config[CONF_MAX_POWER]))
if CONF_MIN_POWER in config:
add(obj.set_min_power(config[CONF_MIN_POWER]))
def setup_output_platform(obj, config, skip_power_supply=False):
@@ -67,11 +71,11 @@ OUTPUT_TURN_ON_ACTION = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_ON, OUTPUT_TURN_ON_ACTION)
def output_turn_on_to_code(config, action_id, arg_type, template_arg):
def output_turn_on_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_on_action(template_arg)
type = TurnOnAction.template(arg_type)
type = TurnOnAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -82,29 +86,29 @@ OUTPUT_TURN_OFF_ACTION = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_OFF, OUTPUT_TURN_OFF_ACTION)
def output_turn_off_to_code(config, action_id, arg_type, template_arg):
def output_turn_off_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_turn_off_action(template_arg)
type = TurnOffAction.template(arg_type)
type = TurnOffAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
CONF_OUTPUT_SET_LEVEL = 'output.set_level'
OUTPUT_SET_LEVEL_ACTION = vol.Schema({
OUTPUT_SET_LEVEL_ACTION = cv.Schema({
vol.Required(CONF_ID): cv.use_variable_id(FloatOutput),
vol.Required(CONF_LEVEL): cv.templatable(cv.percentage),
})
@ACTION_REGISTRY.register(CONF_OUTPUT_SET_LEVEL, OUTPUT_SET_LEVEL_ACTION)
def output_set_level_to_code(config, action_id, arg_type, template_arg):
def output_set_level_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_set_level_action(template_arg)
type = SetLevelAction.template(arg_type)
type = SetLevelAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for template_ in templatable(config[CONF_LEVEL], arg_type, float_):
for template_ in templatable(config[CONF_LEVEL], args, float_):
yield None
add(action.set_level(template_))
yield action

View File

@@ -0,0 +1,58 @@
import voluptuous as vol
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_OUTPUTS, CONF_TYPE
from esphome.cpp_generator import Pvariable, get_variable
from esphome.cpp_helpers import setup_component
BinaryCopyOutput = output.output_ns.class_('BinaryCopyOutput', output.BinaryOutput)
FloatCopyOutput = output.output_ns.class_('FloatCopyOutput', output.FloatOutput)
BINARY_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(BinaryCopyOutput),
vol.Required(CONF_TYPE): 'binary',
vol.Required(CONF_OUTPUTS): cv.ensure_list(cv.use_variable_id(output.BinaryOutput)),
})
FLOAT_SCHEMA = output.PLATFORM_SCHEMA.extend({
vol.Required(CONF_ID): cv.declare_variable_id(FloatCopyOutput),
vol.Required(CONF_TYPE): 'float',
vol.Required(CONF_OUTPUTS): cv.ensure_list(cv.use_variable_id(output.FloatOutput)),
})
def validate_copy_output(value):
if not isinstance(value, dict):
raise vol.Invalid("Value must be dict")
type = cv.string_strict(value.get(CONF_TYPE, 'float')).lower()
value[CONF_TYPE] = type
if type == 'binary':
return BINARY_SCHEMA(value)
if type == 'float':
return FLOAT_SCHEMA(value)
raise vol.Invalid("type must either be binary or float, not {}!".format(type))
PLATFORM_SCHEMA = validate_copy_output
def to_code(config):
outputs = []
for out in config[CONF_OUTPUTS]:
for var in get_variable(out):
yield
outputs.append(var)
klass = {
'binary': BinaryCopyOutput,
'float': FloatCopyOutput,
}[config[CONF_TYPE]]
rhs = klass.new(outputs)
gpio = Pvariable(config[CONF_ID], rhs)
output.setup_output_platform(gpio, config)
setup_component(gpio, config)
BUILD_FLAGS = '-DUSE_COPY_OUTPUT'

View File

@@ -13,7 +13,7 @@ MULTI_CONF = True
PCA9685OutputComponent = output.output_ns.class_('PCA9685OutputComponent',
Component, i2c.I2CDevice)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
vol.Range(min=23.84, max=1525.88)),

View File

@@ -20,7 +20,7 @@ PCF8675_GPIO_MODES = {
PCF8574GPIOInputPin = io_ns.class_('PCF8574GPIOInputPin', GPIOInputPin)
PCF8574GPIOOutputPin = io_ns.class_('PCF8574GPIOOutputPin', GPIOOutputPin)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(pins.PCF8574Component),
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
vol.Optional(CONF_PCF8575, default=False): cv.boolean,

View File

@@ -17,7 +17,7 @@ PN532Component = binary_sensor.binary_sensor_ns.class_('PN532Component', Polling
spi.SPIDevice)
PN532Trigger = binary_sensor.binary_sensor_ns.class_('PN532Trigger', Trigger.template(std_string))
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(PN532Component),
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
@@ -38,7 +38,7 @@ def to_code(config):
for conf_ in config.get(CONF_ON_TAG, []):
trigger = Pvariable(conf_[CONF_TRIGGER_ID], pn532.make_trigger())
automation.build_automation(trigger, std_string, conf_)
automation.build_automations(trigger, [(std_string, 'x')], conf_)
setup_component(pn532, config)

View File

@@ -11,7 +11,7 @@ PowerSupplyComponent = esphome_ns.class_('PowerSupplyComponent', Component)
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,

View File

@@ -1,5 +1,3 @@
import voluptuous as vol
from esphome.components import binary_sensor, uart
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_UART_ID
@@ -12,7 +10,7 @@ DEPENDENCIES = ['uart']
RDM6300Component = binary_sensor.binary_sensor_ns.class_('RDM6300Component', Component,
uart.UARTDevice)
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(RDM6300Component),
cv.GenerateID(CONF_UART_ID): cv.use_variable_id(uart.UARTComponent),
}).extend(cv.COMPONENT_SCHEMA.schema)

View File

@@ -40,9 +40,10 @@ def validate_dumpers_all(value):
raise vol.Invalid("Not valid dumpers")
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent),
vol.Required(CONF_PIN): pins.gpio_input_pin_schema,
vol.Required(CONF_PIN): vol.All(pins.internal_gpio_input_pin_schema,
pins.validate_has_interrupt),
vol.Optional(CONF_DUMP, default=[]):
vol.Any(validate_dumpers_all, cv.ensure_list(cv.one_of(*DUMPERS, lower=True))),
vol.Optional(CONF_TOLERANCE): vol.All(cv.percentage_int, vol.Range(min=0)),

View File

@@ -39,7 +39,7 @@ RC_SWITCH_TIMING_SCHEMA = vol.All([cv.uint8_t], vol.Length(min=2, max=2))
RC_SWITCH_PROTOCOL_SCHEMA = vol.Any(
vol.All(vol.Coerce(int), vol.Range(min=1, max=7)),
vol.Schema({
cv.Schema({
vol.Required(CONF_PULSE_LENGTH): cv.uint32_t,
vol.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA,
vol.Optional(CONF_ZERO, default=[1, 3]): RC_SWITCH_TIMING_SCHEMA,
@@ -48,23 +48,23 @@ RC_SWITCH_PROTOCOL_SCHEMA = vol.Any(
})
)
RC_SWITCH_RAW_SCHEMA = vol.Schema({
RC_SWITCH_RAW_SCHEMA = cv.Schema({
vol.Required(CONF_CODE): validate_rc_switch_code,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_A_SCHEMA = vol.Schema({
RC_SWITCH_TYPE_A_SCHEMA = cv.Schema({
vol.Required(CONF_GROUP): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
vol.Required(CONF_DEVICE): vol.All(validate_rc_switch_code, vol.Length(min=5, max=5)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_B_SCHEMA = vol.Schema({
RC_SWITCH_TYPE_B_SCHEMA = cv.Schema({
vol.Required(CONF_ADDRESS): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_CHANNEL): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_C_SCHEMA = vol.Schema({
RC_SWITCH_TYPE_C_SCHEMA = cv.Schema({
vol.Required(CONF_FAMILY): cv.one_of('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', lower=True),
vol.Required(CONF_GROUP): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
@@ -72,14 +72,14 @@ RC_SWITCH_TYPE_C_SCHEMA = vol.Schema({
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
RC_SWITCH_TYPE_D_SCHEMA = vol.Schema({
RC_SWITCH_TYPE_D_SCHEMA = cv.Schema({
vol.Required(CONF_GROUP): cv.one_of('a', 'b', 'c', 'd', lower=True),
vol.Required(CONF_DEVICE): vol.All(cv.uint8_t, vol.Range(min=1, max=3)),
vol.Required(CONF_STATE): cv.boolean,
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
})
CONFIG_SCHEMA = vol.Schema({
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(cv.percentage_int,

View File

@@ -5,9 +5,9 @@ from esphome.automation import ACTION_REGISTRY, maybe_simple_id
import esphome.config_validation as cv
from esphome.const import CONF_ID
from esphome.cpp_generator import Pvariable, get_variable
from esphome.cpp_types import Action, NoArg, Trigger, esphome_ns
from esphome.cpp_types import Action, Trigger, esphome_ns
Script = esphome_ns.class_('Script', Trigger.template(NoArg))
Script = esphome_ns.class_('Script', Trigger.template())
ScriptExecuteAction = esphome_ns.class_('ScriptExecuteAction', Action)
ScriptStopAction = esphome_ns.class_('ScriptStopAction', Action)
@@ -19,7 +19,7 @@ CONFIG_SCHEMA = automation.validate_automation({
def to_code(config):
for conf in config:
trigger = Pvariable(conf[CONF_ID], Script.new())
automation.build_automation(trigger, NoArg, conf)
automation.build_automations(trigger, [], conf)
CONF_SCRIPT_EXECUTE = 'script.execute'
@@ -29,11 +29,11 @@ SCRIPT_EXECUTE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_SCRIPT_EXECUTE, SCRIPT_EXECUTE_ACTION_SCHEMA)
def script_execute_action_to_code(config, action_id, arg_type, template_arg):
def script_execute_action_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_execute_action(template_arg)
type = ScriptExecuteAction.template(arg_type)
type = ScriptExecuteAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)
@@ -44,9 +44,9 @@ SCRIPT_STOP_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_SCRIPT_STOP, SCRIPT_STOP_ACTION_SCHEMA)
def script_stop_action_to_code(config, action_id, arg_type, template_arg):
def script_stop_action_to_code(config, action_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_stop_action(template_arg)
type = ScriptStopAction.template(arg_type)
type = ScriptStopAction.template(template_arg)
yield Pvariable(action_id, rhs, type=type)

View File

@@ -1,3 +1,5 @@
import math
import voluptuous as vol
from esphome import automation
@@ -6,12 +8,13 @@ from esphome.components import mqtt
from esphome.components.mqtt import setup_mqtt_component
import esphome.config_validation as cv
from esphome.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \
CONF_DEBOUNCE, CONF_DELTA, CONF_EXPIRE_AFTER, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, \
CONF_FILTER_NAN, CONF_FILTER_OUT, CONF_HEARTBEAT, CONF_ICON, CONF_ID, CONF_INTERNAL, \
CONF_LAMBDA, CONF_MQTT_ID, CONF_MULTIPLY, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE, \
CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \
CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, \
CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
CONF_CALIBRATE_LINEAR, CONF_DEBOUNCE, CONF_DELTA, CONF_EXPIRE_AFTER, \
CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, CONF_FILTER_OUT, CONF_FROM, \
CONF_HEARTBEAT, CONF_ICON, CONF_ID, CONF_INTERNAL, CONF_LAMBDA, CONF_MQTT_ID, \
CONF_MULTIPLY, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, CONF_OR, \
CONF_SEND_EVERY, CONF_SEND_FIRST_AT, CONF_SLIDING_WINDOW_MOVING_AVERAGE, \
CONF_THROTTLE, CONF_TO, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, \
CONF_WINDOW_SIZE
from esphome.core import CORE
from esphome.cpp_generator import Pvariable, add, get_variable, process_lambda, templatable
from esphome.cpp_types import App, Component, Nameable, PollingComponent, Trigger, \
@@ -35,28 +38,51 @@ def validate_send_first_at(value):
return value
FILTER_KEYS = [CONF_OFFSET, CONF_MULTIPLY, CONF_FILTER_OUT, CONF_FILTER_NAN,
FILTER_KEYS = [CONF_OFFSET, CONF_MULTIPLY, CONF_FILTER_OUT,
CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_LAMBDA,
CONF_THROTTLE, CONF_DELTA, CONF_UNIQUE, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR]
CONF_THROTTLE, CONF_DELTA, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR,
CONF_CALIBRATE_LINEAR]
def validate_datapoint(value):
if isinstance(value, dict):
return cv.Schema({
vol.Required(CONF_FROM): cv.float_,
vol.Required(CONF_TO): cv.float_,
})(value)
value = cv.string(value)
if '->' not in value:
raise vol.Invalid("Datapoint mapping must contain '->'")
a, b = value.split('->', 1)
a, b = a.strip(), b.strip()
return validate_datapoint({
CONF_FROM: cv.float_(a),
CONF_TO: cv.float_(b)
})
FILTERS_SCHEMA = cv.ensure_list({
vol.Optional(CONF_OFFSET): cv.float_,
vol.Optional(CONF_MULTIPLY): cv.float_,
vol.Optional(CONF_FILTER_OUT): cv.float_,
vol.Optional(CONF_FILTER_NAN): None,
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({
vol.Optional('filter_nan'): cv.invalid("The filter_nan filter has been removed. Please use "
"'filter_out: nan' instead"),
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(cv.Schema({
vol.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int,
vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int,
vol.Optional(CONF_SEND_FIRST_AT): cv.positive_not_null_int,
}), validate_send_first_at),
vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({
vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): cv.Schema({
vol.Optional(CONF_ALPHA, default=0.1): cv.positive_float,
vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int,
}),
vol.Optional(CONF_CALIBRATE_LINEAR): vol.All(
cv.ensure_list(validate_datapoint), vol.Length(min=2)),
vol.Optional(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds,
vol.Optional(CONF_DELTA): cv.float_,
vol.Optional(CONF_UNIQUE): None,
vol.Optional(CONF_UNIQUE): cv.invalid("The unique filter has been removed in 1.12, please "
"replace with a delta filter with small value."),
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
vol.Optional(CONF_OR): validate_recursive_filter,
@@ -85,13 +111,12 @@ LambdaFilter = sensor_ns.class_('LambdaFilter', Filter)
OffsetFilter = sensor_ns.class_('OffsetFilter', Filter)
MultiplyFilter = sensor_ns.class_('MultiplyFilter', Filter)
FilterOutValueFilter = sensor_ns.class_('FilterOutValueFilter', Filter)
FilterOutNANFilter = sensor_ns.class_('FilterOutNANFilter', Filter)
ThrottleFilter = sensor_ns.class_('ThrottleFilter', Filter)
DebounceFilter = sensor_ns.class_('DebounceFilter', Filter, Component)
HeartbeatFilter = sensor_ns.class_('HeartbeatFilter', Filter, Component)
DeltaFilter = sensor_ns.class_('DeltaFilter', Filter)
OrFilter = sensor_ns.class_('OrFilter', Filter)
UniqueFilter = sensor_ns.class_('UniqueFilter', Filter)
CalibrateLinearFilter = sensor_ns.class_('CalibrateLinearFilter', Filter)
SensorInRangeCondition = sensor_ns.class_('SensorInRangeCondition', Filter)
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
@@ -125,8 +150,6 @@ def setup_filter(config):
yield MultiplyFilter.new(config[CONF_MULTIPLY])
elif CONF_FILTER_OUT in config:
yield FilterOutValueFilter.new(config[CONF_FILTER_OUT])
elif CONF_FILTER_NAN in config:
yield FilterOutNANFilter.new()
elif CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
conf = config[CONF_SLIDING_WINDOW_MOVING_AVERAGE]
yield SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY],
@@ -151,8 +174,11 @@ def setup_filter(config):
yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
elif CONF_DEBOUNCE in config:
yield App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
elif CONF_UNIQUE in config:
yield UniqueFilter.new()
elif CONF_CALIBRATE_LINEAR in config:
x = [conf[CONF_FROM] for conf in config[CONF_CALIBRATE_LINEAR]]
y = [conf[CONF_TO] for conf in config[CONF_CALIBRATE_LINEAR]]
k, b = fit_linear(x, y)
yield CalibrateLinearFilter.new(k, b)
def setup_filters(config):
@@ -181,11 +207,11 @@ def setup_sensor_core_(sensor_var, config):
for conf in config.get(CONF_ON_VALUE, []):
rhs = sensor_var.make_state_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, float_, conf)
automation.build_automations(trigger, [(float_, 'x')], conf)
for conf in config.get(CONF_ON_RAW_VALUE, []):
rhs = sensor_var.make_raw_state_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automation(trigger, float_, conf)
automation.build_automations(trigger, [(float_, 'x')], conf)
for conf in config.get(CONF_ON_VALUE_RANGE, []):
rhs = sensor_var.make_value_range_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
@@ -198,7 +224,7 @@ def setup_sensor_core_(sensor_var, config):
for template_ in templatable(conf[CONF_BELOW], float_, float_):
yield
add(trigger.set_max(template_))
automation.build_automation(trigger, float_, conf)
automation.build_automations(trigger, [(float_, 'x')], conf)
mqtt_ = sensor_var.Pget_mqtt()
if CONF_EXPIRE_AFTER in config:
@@ -232,11 +258,11 @@ SENSOR_IN_RANGE_CONDITION_SCHEMA = vol.All({
@CONDITION_REGISTRY.register(CONF_SENSOR_IN_RANGE, SENSOR_IN_RANGE_CONDITION_SCHEMA)
def sensor_in_range_to_code(config, condition_id, arg_type, template_arg):
def sensor_in_range_to_code(config, condition_id, template_arg, args):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_sensor_in_range_condition(template_arg)
type = SensorInRangeCondition.template(arg_type)
type = SensorInRangeCondition.template(template_arg)
cond = Pvariable(condition_id, rhs, type=type)
if CONF_ABOVE in config:
@@ -247,16 +273,26 @@ def sensor_in_range_to_code(config, condition_id, arg_type, template_arg):
yield cond
def core_to_hass_config(data, config):
ret = mqtt.build_hass_config(data, 'sensor', config, include_state=True, include_command=False)
if ret is None:
return None
if CONF_UNIT_OF_MEASUREMENT in config:
ret['unit_of_measurement'] = config[CONF_UNIT_OF_MEASUREMENT]
if CONF_EXPIRE_AFTER in config:
expire = config[CONF_EXPIRE_AFTER]
if expire is not None:
ret['expire_after'] = expire.total_seconds
if CONF_ICON in config:
ret['icon'] = config[CONF_ICON]
return ret
def _mean(xs):
return sum(xs) / len(xs)
def _std(x):
return math.sqrt(sum((x_ - _mean(x))**2 for x_ in x) / (len(x) - 1))
def _correlation_coeff(x, y):
m_x, m_y = _mean(x), _mean(y)
s_xy = sum((x_ - m_x) * (y_ - m_y) for x_, y_ in zip(x, y))
s_sq_x = sum((x_ - m_x)**2 for x_ in x)
s_sq_y = sum((y_ - m_y)**2 for y_ in y)
return s_xy / math.sqrt(s_sq_x * s_sq_y)
def fit_linear(x, y):
assert len(x) == len(y)
m_x, m_y = _mean(x), _mean(y)
r = _correlation_coeff(x, y)
k = r * (_std(y) / _std(x))
b = m_y - k * m_x
return k, b

View File

@@ -56,10 +56,6 @@ def required_build_flags(config):
return None
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)
def includes(config):
if config[CONF_PIN] == 'VCC':
return 'ADC_MODE(ADC_VCC);'

View File

@@ -25,7 +25,7 @@ MUX = {
ADS1115Gain = sensor.sensor_ns.enum('ADS1115Gain')
GAIN = {
'6.144': ADS1115Gain.ADS1115_GAIN_6P144,
'4.096': ADS1115Gain.ADS1115_GAIN_6P096,
'4.096': ADS1115Gain.ADS1115_GAIN_4P096,
'2.048': ADS1115Gain.ADS1115_GAIN_2P048,
'1.024': ADS1115Gain.ADS1115_GAIN_1P024,
'0.512': ADS1115Gain.ADS1115_GAIN_0P512,
@@ -70,7 +70,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -29,7 +29,3 @@ def to_code(config):
func = getattr(hub, TYPES[config[CONF_TYPE]])
rhs = func(config[CONF_NAME])
sensor.register_sensor(rhs, config)
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -39,7 +39,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_BH1750'
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -24,7 +24,3 @@ def to_code(config):
yield
rhs = hub.make_rssi_sensor(config[CONF_NAME], make_address_array(config[CONF_MAC_ADDRESS]))
sensor.register_sensor(rhs, config)
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -85,9 +85,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_BME280'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_PRESSURE]),
sensor.core_to_hass_config(data, config[CONF_HUMIDITY])]

View File

@@ -64,7 +64,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(BME680GasResistanceSensor),
})),
vol.Optional(CONF_IIR_FILTER): cv.one_of(*IIR_FILTER_OPTIONS, upper=True),
vol.Optional(CONF_HEATER): vol.Any(None, vol.All(vol.Schema({
vol.Optional(CONF_HEATER): vol.Any(None, vol.All(cv.Schema({
vol.Optional(CONF_TEMPERATURE, default=320): vol.All(vol.Coerce(int), vol.Range(200, 400)),
vol.Optional(CONF_DURATION, default='150ms'): vol.All(
cv.positive_time_period_milliseconds, vol.Range(max=core.TimePeriod(milliseconds=4032)))
@@ -108,10 +108,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_BME680'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_PRESSURE]),
sensor.core_to_hass_config(data, config[CONF_HUMIDITY]),
sensor.core_to_hass_config(data, config[CONF_GAS_RESISTANCE])]

View File

@@ -43,8 +43,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_BMP085_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_PRESSURE])]

View File

@@ -75,8 +75,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_BMP280'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_PRESSURE])]

View File

@@ -57,11 +57,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_CSE7766'
def to_hass_config(data, config):
ret = []
for key in (CONF_VOLTAGE, CONF_CURRENT, CONF_POWER):
if key in config:
ret.append(sensor.core_to_hass_config(data, config[key]))
return ret

View File

@@ -31,7 +31,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_CUSTOM_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, sens) for sens in config[CONF_SENSORS]]

View File

@@ -32,7 +32,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -57,8 +57,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_DHT_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_HUMIDITY])]

View File

@@ -40,8 +40,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_DHT12_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_HUMIDITY])]

View File

@@ -12,7 +12,8 @@ DutyCycleSensor = sensor.sensor_ns.class_('DutyCycleSensor', sensor.PollingSenso
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(DutyCycleSensor),
vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
vol.Required(CONF_PIN): vol.All(pins.internal_gpio_input_pin_schema,
pins.validate_has_interrupt),
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA.schema))
@@ -28,7 +29,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_DUTY_CYCLE_SENSOR'
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -26,7 +26,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_ESP32_HALL_SENSOR'
def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config)

View File

@@ -40,8 +40,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_HDC1080_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, config[CONF_TEMPERATURE]),
sensor.core_to_hass_config(data, config[CONF_HUMIDITY])]

View File

@@ -66,11 +66,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_HLW8012'
def to_hass_config(data, config):
ret = []
for key in (CONF_VOLTAGE, CONF_CURRENT, CONF_POWER):
if key in config:
ret.append(sensor.core_to_hass_config(data, config[key]))
return ret

View File

@@ -87,11 +87,3 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_HMC5883L'
def to_hass_config(data, config):
ret = []
for key in (CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z, CONF_HEADING):
if key in config:
ret.append(sensor.core_to_hass_config(data, config[key]))
return ret

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