mirror of
https://github.com/esphome/esphome.git
synced 2025-11-05 17:41:49 +00:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
433b605bef | ||
|
|
6e60c6493a | ||
|
|
4e63bc96d5 | ||
|
|
ce4b339d16 | ||
|
|
ab6d293d0d | ||
|
|
5e5137960d | ||
|
|
8dba37846b | ||
|
|
5cd82d7c25 | ||
|
|
bc8354bad5 | ||
|
|
2abbe1bca3 | ||
|
|
74c70509c2 | ||
|
|
1576e1847e | ||
|
|
9ea9b4b102 | ||
|
|
490743c26e | ||
|
|
1c7bddd005 | ||
|
|
5c39f73fda | ||
|
|
2fc78a1b33 | ||
|
|
03249780fd | ||
|
|
5170a7cdf4 | ||
|
|
5680de79a9 | ||
|
|
61bd2a3a44 | ||
|
|
7802c63f5a | ||
|
|
94bef2a5a4 | ||
|
|
12c4b0788c | ||
|
|
b13cc3a4a5 | ||
|
|
c5d9bc5452 | ||
|
|
6c6d21a7ab | ||
|
|
9bb06782b2 | ||
|
|
a827b51887 | ||
|
|
2c30d80490 | ||
|
|
e0acdc3ae0 | ||
|
|
36a3f96011 | ||
|
|
6ae8e3495f | ||
|
|
6aa449115f | ||
|
|
0be29d27d5 | ||
|
|
68fa7489a2 | ||
|
|
d7699c93d6 | ||
|
|
a04438e924 | ||
|
|
e063f2aaea | ||
|
|
7b630bfb8b | ||
|
|
ec3366cce0 | ||
|
|
135117714b | ||
|
|
91e6304505 | ||
|
|
361a9da868 | ||
|
|
31d7656c07 | ||
|
|
d1a7751dc9 | ||
|
|
e47bcb9abb | ||
|
|
30b94f06b3 | ||
|
|
19dfdb77eb | ||
|
|
b6e7ad3589 | ||
|
|
1267680379 | ||
|
|
b5f6b32fad | ||
|
|
7068808d4f | ||
|
|
c82a44d541 | ||
|
|
e650473682 | ||
|
|
2ee0d4242d | ||
|
|
b2aecf29dc | ||
|
|
081c2f4e07 | ||
|
|
0c77228421 | ||
|
|
8a509c6551 | ||
|
|
d249820bcd | ||
|
|
f39cf52eae | ||
|
|
63fb252b46 | ||
|
|
2f98adca49 | ||
|
|
084fc00517 | ||
|
|
abeac23abd | ||
|
|
7264e3a4bf | ||
|
|
16eeb3af31 | ||
|
|
b799d2df7f | ||
|
|
11d55fec4f | ||
|
|
923a5990c7 | ||
|
|
a0a615c335 | ||
|
|
e9ced0cc3f | ||
|
|
1a92381994 | ||
|
|
a07a7a87a2 | ||
|
|
6a823f5777 | ||
|
|
419c5afe27 | ||
|
|
17798dee1e | ||
|
|
ee2c53585f | ||
|
|
2f05acfa5a | ||
|
|
f4d393a59e | ||
|
|
967aa53bad | ||
|
|
4f3f460105 | ||
|
|
6e85a741ae | ||
|
|
2db45898e2 | ||
|
|
eb62599a98 | ||
|
|
9f0737e5b9 | ||
|
|
7a393c1a3a | ||
|
|
4fa7bc196a | ||
|
|
65d0dd47f3 |
@@ -106,3 +106,5 @@ venv.bak/
|
|||||||
config/
|
config/
|
||||||
examples/
|
examples/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
|
.git/
|
||||||
|
tests/build/
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -104,3 +104,4 @@ venv.bak/
|
|||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
config/
|
config/
|
||||||
|
tests/build/
|
||||||
|
|||||||
187
.gitlab-ci.yml
Normal file
187
.gitlab-ci.yml
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
# Based on https://gitlab.com/hassio-addons/addon-node-red/blob/master/.gitlab-ci.yml
|
||||||
|
variables:
|
||||||
|
DOCKER_DRIVER: overlay2
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- lint
|
||||||
|
- test
|
||||||
|
- build
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
.lint: &lint
|
||||||
|
stage: lint
|
||||||
|
tags:
|
||||||
|
- python2.7
|
||||||
|
- esphomeyaml-lint
|
||||||
|
|
||||||
|
.test: &test
|
||||||
|
stage: test
|
||||||
|
before_script:
|
||||||
|
- pip install -e .
|
||||||
|
tags:
|
||||||
|
- python2.7
|
||||||
|
- esphomeyaml-test
|
||||||
|
variables:
|
||||||
|
TZ: UTC
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- tests/build
|
||||||
|
|
||||||
|
.docker-builder: &docker-builder
|
||||||
|
before_script:
|
||||||
|
- docker info
|
||||||
|
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
tags:
|
||||||
|
- hassio-builder
|
||||||
|
|
||||||
|
flake8:
|
||||||
|
<<: *lint
|
||||||
|
script:
|
||||||
|
- flake8 esphomeyaml
|
||||||
|
|
||||||
|
pylint:
|
||||||
|
<<: *lint
|
||||||
|
script:
|
||||||
|
- pylint esphomeyaml
|
||||||
|
|
||||||
|
test1:
|
||||||
|
<<: *test
|
||||||
|
script:
|
||||||
|
- esphomeyaml tests/test1.yaml compile
|
||||||
|
|
||||||
|
test2:
|
||||||
|
<<: *test
|
||||||
|
script:
|
||||||
|
- esphomeyaml tests/test2.yaml compile
|
||||||
|
|
||||||
|
.build-hassio: &build-hassio
|
||||||
|
<<: *docker-builder
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
hassio-builder.sh \
|
||||||
|
-t . \
|
||||||
|
-i ottowinter/esphomeyaml-hassio-${ADDON_ARCH} \
|
||||||
|
-d "$CI_REGISTRY" \
|
||||||
|
--${ADDON_ARCH}
|
||||||
|
- |
|
||||||
|
docker tag \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:dev" \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||||
|
- docker push "${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||||
|
- docker push "${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:dev"
|
||||||
|
retry: 2
|
||||||
|
|
||||||
|
# Generic deploy template
|
||||||
|
.deploy: &deploy
|
||||||
|
<<: *docker-builder
|
||||||
|
stage: deploy
|
||||||
|
script:
|
||||||
|
- version=${CI_COMMIT_TAG:1}
|
||||||
|
- echo "Publishing version ${version}"
|
||||||
|
- docker login -u "$DOCKER_USER" -p "$DOCKER_PASSWORD"
|
||||||
|
- docker pull "${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}"
|
||||||
|
- |
|
||||||
|
docker tag \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}" \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:latest"
|
||||||
|
- |
|
||||||
|
docker tag \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}" \
|
||||||
|
"ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${version}"
|
||||||
|
- |
|
||||||
|
docker tag \
|
||||||
|
"ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${version}" \
|
||||||
|
"ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:latest"
|
||||||
|
- docker push "${CI_REGISTRY}/ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:latest"
|
||||||
|
- docker push "ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${version}"
|
||||||
|
- docker push "ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:latest"
|
||||||
|
|
||||||
|
# Build jobs
|
||||||
|
build:normal:
|
||||||
|
<<: *docker-builder
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- docker build -t "${CI_REGISTRY}/ottowinter/esphomeyaml:dev" .
|
||||||
|
- |
|
||||||
|
docker tag \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml:dev" \
|
||||||
|
"${CI_REGISTRY}/ottowinter/esphomeyaml:${CI_COMMIT_SHA}"
|
||||||
|
- docker push "${CI_REGISTRY}/ottowinter/esphomeyaml:${CI_COMMIT_SHA}"
|
||||||
|
- docker push "${CI_REGISTRY}/ottowinter/esphomeyaml:dev"
|
||||||
|
|
||||||
|
build:armhf:
|
||||||
|
<<: *build-hassio
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: armhf
|
||||||
|
|
||||||
|
#build:aarch64:
|
||||||
|
# <<: *build
|
||||||
|
# variables:
|
||||||
|
# ADDON_ARCH: aarch64
|
||||||
|
|
||||||
|
build:i386:
|
||||||
|
<<: *build-hassio
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: i386
|
||||||
|
|
||||||
|
build:amd64:
|
||||||
|
<<: *build-hassio
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: amd64
|
||||||
|
|
||||||
|
# Deploy jobs
|
||||||
|
deploy:armhf:
|
||||||
|
<<: *deploy
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: armhf
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||||
|
except:
|
||||||
|
- /^(?!master).+@/
|
||||||
|
|
||||||
|
#deploy:aarch64:
|
||||||
|
# <<: *deploy
|
||||||
|
# variables:
|
||||||
|
# ADDON_ARCH: aarch64
|
||||||
|
# only:
|
||||||
|
# - /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||||
|
# except:
|
||||||
|
# - /^(?!master).+@/
|
||||||
|
|
||||||
|
deploy:i386:
|
||||||
|
<<: *deploy
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: i386
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||||
|
except:
|
||||||
|
- /^(?!master).+@/
|
||||||
|
|
||||||
|
deploy:amd64:
|
||||||
|
<<: *deploy
|
||||||
|
variables:
|
||||||
|
ADDON_ARCH: amd64
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||||
|
except:
|
||||||
|
- /^(?!master).+@/
|
||||||
|
|
||||||
|
deploy:pypi:
|
||||||
|
stage: deploy
|
||||||
|
before_script:
|
||||||
|
- pip install -e .
|
||||||
|
- pip install twine
|
||||||
|
script:
|
||||||
|
- python setup.py sdist
|
||||||
|
- twine upload dist/*
|
||||||
|
tags:
|
||||||
|
- python2.7
|
||||||
|
- esphomeyaml-test
|
||||||
|
only:
|
||||||
|
- /^v\d+\.\d+\.\d+(?:(?:(?:\+|\.)?[a-zA-Z0-9]+)*)?$/
|
||||||
|
except:
|
||||||
|
- /^(?!master).+@/
|
||||||
@@ -4,7 +4,7 @@ python:
|
|||||||
- "2.7"
|
- "2.7"
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
- pip install flake8==3.5.0 pylint==1.8.4
|
- pip install flake8==3.5.0 pylint==1.9.3 tzlocal pillow
|
||||||
script:
|
script:
|
||||||
- flake8 esphomeyaml
|
- flake8 esphomeyaml
|
||||||
- pylint esphomeyaml
|
- pylint esphomeyaml
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -1,21 +1,25 @@
|
|||||||
FROM python:2.7
|
FROM python:2.7
|
||||||
MAINTAINER Otto Winter <contact@otto-winter.com>
|
MAINTAINER Otto Winter <contact@otto-winter.com>
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python-pil \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV ESPHOMEYAML_OTA_HOST_PORT=6123
|
ENV ESPHOMEYAML_OTA_HOST_PORT=6123
|
||||||
EXPOSE 6123
|
EXPOSE 6123
|
||||||
VOLUME /config
|
VOLUME /config
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
COPY requirements.txt /usr/src/app/
|
RUN pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
RUN pip install --no-cache-dir -r requirements.txt && \
|
platformio settings set enable_telemetry No
|
||||||
pip install --no-cache-dir tornado esptool
|
|
||||||
|
|
||||||
COPY docker/platformio.ini /usr/src/app/
|
COPY docker/platformio.ini /usr/src/app/
|
||||||
RUN platformio settings set enable_telemetry No && \
|
RUN platformio settings set enable_telemetry No && \
|
||||||
platformio run -e espressif32 -e espressif8266; exit 0
|
platformio run -e espressif32 -e espressif8266; exit 0
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pip install -e .
|
RUN pip install --no-cache-dir -e . && \
|
||||||
|
pip install --no-cache-dir tzlocal pillow
|
||||||
|
|
||||||
WORKDIR /config
|
WORKDIR /config
|
||||||
ENTRYPOINT ["esphomeyaml"]
|
ENTRYPOINT ["esphomeyaml"]
|
||||||
|
|||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Otto Winter
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
21
docker/Dockerfile.aarch64
Normal file
21
docker/Dockerfile.aarch64
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile for aarch64 version of HassIO add-on
|
||||||
|
FROM arm64v8/ubuntu:bionic
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python \
|
||||||
|
python-pip \
|
||||||
|
python-setuptools \
|
||||||
|
python-pil \
|
||||||
|
git \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
COPY docker/platformio.ini /pio/platformio.ini
|
||||||
|
RUN platformio run -d /pio; rm -rf /pio
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN pip install --no-cache-dir --no-binary :all: -e . && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: tzlocal
|
||||||
|
|
||||||
|
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||||
21
docker/Dockerfile.amd64
Normal file
21
docker/Dockerfile.amd64
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile for amd64 version of HassIO add-on
|
||||||
|
FROM ubuntu:bionic
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python \
|
||||||
|
python-pip \
|
||||||
|
python-setuptools \
|
||||||
|
python-pil \
|
||||||
|
git \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
COPY docker/platformio.ini /pio/platformio.ini
|
||||||
|
RUN platformio run -d /pio; rm -rf /pio
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN pip install --no-cache-dir --no-binary :all: -e . && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: tzlocal
|
||||||
|
|
||||||
|
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||||
31
docker/Dockerfile.armhf
Normal file
31
docker/Dockerfile.armhf
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Dockerfile for armhf version of HassIO add-on
|
||||||
|
FROM homeassistant/armhf-base:latest
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
python2 \
|
||||||
|
python2-dev \
|
||||||
|
py2-pip \
|
||||||
|
git \
|
||||||
|
gcc \
|
||||||
|
openssh \
|
||||||
|
libc6-compat \
|
||||||
|
jpeg-dev \
|
||||||
|
zlib-dev \
|
||||||
|
freetype-dev \
|
||||||
|
lcms2-dev \
|
||||||
|
openjpeg-dev \
|
||||||
|
tiff-dev \
|
||||||
|
libc-dev \
|
||||||
|
linux-headers \
|
||||||
|
&& \
|
||||||
|
pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
COPY docker/platformio-esp8266.ini /pio/platformio.ini
|
||||||
|
RUN platformio run -d /pio; rm -rf /pio
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN pip install --no-cache-dir --no-binary :all: -e . && \
|
||||||
|
pip install --no-cache-dir pillow tzlocal
|
||||||
|
|
||||||
|
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||||
32
docker/Dockerfile.builder
Normal file
32
docker/Dockerfile.builder
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
FROM multiarch/ubuntu-core:amd64-xenial
|
||||||
|
|
||||||
|
# setup locals
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
jq \
|
||||||
|
git \
|
||||||
|
python3-setuptools \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
|
# Install docker
|
||||||
|
# https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
apt-transport-https \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
software-properties-common \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \
|
||||||
|
&& add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
|
||||||
|
&& apt-get update && apt-get install -y docker-ce \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# setup arm binary support
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
qemu-user-static \
|
||||||
|
binfmt-support \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY docker/hassio-builder.sh /usr/bin/
|
||||||
|
|
||||||
|
WORKDIR /data
|
||||||
21
docker/Dockerfile.i386
Normal file
21
docker/Dockerfile.i386
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile for i386 version of HassIO add-on
|
||||||
|
FROM i386/ubuntu:bionic
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python \
|
||||||
|
python-pip \
|
||||||
|
python-setuptools \
|
||||||
|
python-pil \
|
||||||
|
git \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
COPY docker/platformio.ini /pio/platformio.ini
|
||||||
|
RUN platformio run -d /pio; rm -rf /pio
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN pip install --no-cache-dir --no-binary :all: -e . && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: tzlocal
|
||||||
|
|
||||||
|
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||||
6
docker/Dockerfile.lint
Normal file
6
docker/Dockerfile.lint
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM python:2.7
|
||||||
|
|
||||||
|
COPY requirements.txt /requirements.txt
|
||||||
|
|
||||||
|
RUN pip install -r /requirements.txt && \
|
||||||
|
pip install flake8==3.5.0 pylint==1.9.3 tzlocal pillow
|
||||||
19
docker/Dockerfile.test
Normal file
19
docker/Dockerfile.test
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM ubuntu:bionic
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python \
|
||||||
|
python-pip \
|
||||||
|
python-setuptools \
|
||||||
|
python-pil \
|
||||||
|
git \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
|
||||||
|
pip install --no-cache-dir --no-binary :all: platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
COPY docker/platformio.ini /pio/platformio.ini
|
||||||
|
RUN platformio run -d /pio; rm -rf /pio
|
||||||
|
|
||||||
|
COPY requirements.txt /requirements.txt
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r /requirements.txt && \
|
||||||
|
pip install --no-cache-dir tzlocal pillow
|
||||||
318
docker/hassio-builder.sh
Executable file
318
docker/hassio-builder.sh
Executable file
@@ -0,0 +1,318 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Based on Home Assistant's docker builder
|
||||||
|
######################
|
||||||
|
# Hass.io Build-env
|
||||||
|
######################
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo -- "$@"
|
||||||
|
|
||||||
|
#### Variable ####
|
||||||
|
|
||||||
|
DOCKER_TIMEOUT=20
|
||||||
|
DOCKER_PID=-1
|
||||||
|
DOCKER_HUB=""
|
||||||
|
DOCKER_CACHE="true"
|
||||||
|
DOCKER_LOCAL="false"
|
||||||
|
TARGET=""
|
||||||
|
IMAGE=""
|
||||||
|
BUILD_LIST=()
|
||||||
|
BUILD_TASKS=()
|
||||||
|
|
||||||
|
#### Misc functions ####
|
||||||
|
|
||||||
|
function print_help() {
|
||||||
|
cat << EOF
|
||||||
|
Hass.io build-env for ecosystem:
|
||||||
|
docker run --rm homeassistant/{arch}-builder:latest [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help
|
||||||
|
Display this help and exit.
|
||||||
|
|
||||||
|
Repository / Data
|
||||||
|
-t, --target <PATH_TO_BUILD>
|
||||||
|
Set local folder or path inside repository for build.
|
||||||
|
|
||||||
|
Version/Image handling
|
||||||
|
-i, --image <IMAGE_NAME>
|
||||||
|
Overwrite image name of build / support {arch}
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
--armhf
|
||||||
|
Build for arm.
|
||||||
|
--amd64
|
||||||
|
Build for intel/amd 64bit.
|
||||||
|
--aarch64
|
||||||
|
Build for arm 64bit.
|
||||||
|
--i386
|
||||||
|
Build for intel/amd 32bit.
|
||||||
|
--all
|
||||||
|
Build all architecture.
|
||||||
|
|
||||||
|
Build handling
|
||||||
|
--no-cache
|
||||||
|
Disable cache for the build (from latest).
|
||||||
|
-d, --docker-hub <DOCKER_REPOSITORY>
|
||||||
|
Set or overwrite the docker repository.
|
||||||
|
|
||||||
|
Use the host docker socket if mapped into container:
|
||||||
|
/var/run/docker.sock
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#### Docker functions ####
|
||||||
|
|
||||||
|
function start_docker() {
|
||||||
|
local starttime
|
||||||
|
local endtime
|
||||||
|
|
||||||
|
if [ -S "/var/run/docker.sock" ]; then
|
||||||
|
echo "[INFO] Use host docker setup with '/var/run/docker.sock'"
|
||||||
|
DOCKER_LOCAL="true"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[INFO] Starting docker."
|
||||||
|
dockerd 2> /dev/null &
|
||||||
|
DOCKER_PID=$!
|
||||||
|
|
||||||
|
echo "[INFO] Waiting for docker to initialize..."
|
||||||
|
starttime="$(date +%s)"
|
||||||
|
endtime="$(date +%s)"
|
||||||
|
until docker info >/dev/null 2>&1; do
|
||||||
|
if [ $((endtime - starttime)) -le ${DOCKER_TIMEOUT} ]; then
|
||||||
|
sleep 1
|
||||||
|
endtime=$(date +%s)
|
||||||
|
else
|
||||||
|
echo "[ERROR] Timeout while waiting for docker to come up"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "[INFO] Docker was initialized"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function stop_docker() {
|
||||||
|
local starttime
|
||||||
|
local endtime
|
||||||
|
|
||||||
|
if [ "$DOCKER_LOCAL" == "true" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[INFO] Stopping in container docker..."
|
||||||
|
if [ "$DOCKER_PID" -gt 0 ] && kill -0 "$DOCKER_PID" 2> /dev/null; then
|
||||||
|
starttime="$(date +%s)"
|
||||||
|
endtime="$(date +%s)"
|
||||||
|
|
||||||
|
# Now wait for it to die
|
||||||
|
kill "$DOCKER_PID"
|
||||||
|
while kill -0 "$DOCKER_PID" 2> /dev/null; do
|
||||||
|
if [ $((endtime - starttime)) -le ${DOCKER_TIMEOUT} ]; then
|
||||||
|
sleep 1
|
||||||
|
endtime=$(date +%s)
|
||||||
|
else
|
||||||
|
echo "[ERROR] Timeout while waiting for container docker to die"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "[WARN] Your host might have been left with unreleased resources"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_build() {
|
||||||
|
local build_dir=$1
|
||||||
|
local repository=$2
|
||||||
|
local image=$3
|
||||||
|
local version=$4
|
||||||
|
local build_arch=$5
|
||||||
|
local docker_cli=("${!6}")
|
||||||
|
|
||||||
|
local push_images=()
|
||||||
|
|
||||||
|
# Overwrites
|
||||||
|
if [ ! -z "$DOCKER_HUB" ]; then repository="$DOCKER_HUB"; fi
|
||||||
|
if [ ! -z "$IMAGE" ]; then image="$IMAGE"; fi
|
||||||
|
|
||||||
|
# Init Cache
|
||||||
|
if [ "$DOCKER_CACHE" == "true" ]; then
|
||||||
|
echo "[INFO] Init cache for $repository/$image:$version"
|
||||||
|
if docker pull "$repository/$image:latest" > /dev/null 2>&1; then
|
||||||
|
docker_cli+=("--cache-from" "$repository/$image:latest")
|
||||||
|
else
|
||||||
|
docker_cli+=("--no-cache")
|
||||||
|
echo "[WARN] No cache image found. Cache is disabled for build"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
docker_cli+=("--no-cache")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build image
|
||||||
|
echo "[INFO] Run build for $repository/$image:$version"
|
||||||
|
docker build --pull -t "$repository/$image:$version" \
|
||||||
|
--label "io.hass.version=$version" \
|
||||||
|
--label "io.hass.arch=$build_arch" \
|
||||||
|
-f "$TARGET/docker/Dockerfile.$build_arch" \
|
||||||
|
"${docker_cli[@]}" \
|
||||||
|
"$build_dir"
|
||||||
|
|
||||||
|
echo "[INFO] Finish build for $repository/$image:$version"
|
||||||
|
docker tag "$repository/$image:$version" "$repository/$image:dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#### HassIO functions ####
|
||||||
|
|
||||||
|
function build_addon() {
|
||||||
|
local build_arch=$1
|
||||||
|
|
||||||
|
local docker_cli=()
|
||||||
|
local image=""
|
||||||
|
local repository=""
|
||||||
|
local raw_image=""
|
||||||
|
local name=""
|
||||||
|
local description=""
|
||||||
|
local url=""
|
||||||
|
local args=""
|
||||||
|
|
||||||
|
# Read addon config.json
|
||||||
|
name="$(jq --raw-output '.name // empty' "$TARGET/esphomeyaml/config.json" | sed "s/'//g")"
|
||||||
|
description="$(jq --raw-output '.description // empty' "$TARGET/esphomeyaml/config.json" | sed "s/'//g")"
|
||||||
|
url="$(jq --raw-output '.url // empty' "$TARGET/esphomeyaml/config.json")"
|
||||||
|
version="$(jq --raw-output '.version' "$TARGET/esphomeyaml/config.json")"
|
||||||
|
raw_image="$(jq --raw-output '.image // empty' "$TARGET/esphomeyaml/config.json")"
|
||||||
|
|
||||||
|
# Read data from image
|
||||||
|
if [ ! -z "$raw_image" ]; then
|
||||||
|
repository="$(echo "$raw_image" | cut -f 1 -d '/')"
|
||||||
|
image="$(echo "$raw_image" | cut -f 2 -d '/')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set additional labels
|
||||||
|
docker_cli+=("--label" "io.hass.name=$name")
|
||||||
|
docker_cli+=("--label" "io.hass.description=$description")
|
||||||
|
docker_cli+=("--label" "io.hass.type=addon")
|
||||||
|
|
||||||
|
if [ ! -z "$url" ]; then
|
||||||
|
docker_cli+=("--label" "io.hass.url=$url")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start build
|
||||||
|
run_build "$TARGET" "$repository" "$image" "$version" \
|
||||||
|
"$build_arch" docker_cli[@]
|
||||||
|
}
|
||||||
|
|
||||||
|
#### initialized cross-build ####
|
||||||
|
|
||||||
|
function init_crosscompile() {
|
||||||
|
echo "[INFO] Setup crosscompiling feature"
|
||||||
|
(
|
||||||
|
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
||||||
|
update-binfmts --enable qemu-arm
|
||||||
|
update-binfmts --enable qemu-aarch64
|
||||||
|
) > /dev/null 2>&1 || echo "[WARN] Can't enable crosscompiling feature"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clean_crosscompile() {
|
||||||
|
echo "[INFO] Clean crosscompiling feature"
|
||||||
|
if [ -f /proc/sys/fs/binfmt_misc ]; then
|
||||||
|
umount /proc/sys/fs/binfmt_misc || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
update-binfmts --disable qemu-arm
|
||||||
|
update-binfmts --disable qemu-aarch64
|
||||||
|
) > /dev/null 2>&1 || echo "[WARN] No crosscompiling feature found for cleanup"
|
||||||
|
}
|
||||||
|
|
||||||
|
#### Error handling ####
|
||||||
|
|
||||||
|
function error_handling() {
|
||||||
|
stop_docker
|
||||||
|
clean_crosscompile
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
trap 'error_handling' SIGINT SIGTERM
|
||||||
|
|
||||||
|
#### Parse arguments ####
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
key=$1
|
||||||
|
case ${key} in
|
||||||
|
-h|--help)
|
||||||
|
print_help
|
||||||
|
;;
|
||||||
|
-t|--target)
|
||||||
|
TARGET=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-i|--image)
|
||||||
|
IMAGE=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-cache)
|
||||||
|
DOCKER_CACHE="false"
|
||||||
|
;;
|
||||||
|
-d|--docker-hub)
|
||||||
|
DOCKER_HUB=$2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--armhf)
|
||||||
|
BUILD_LIST+=("armhf")
|
||||||
|
;;
|
||||||
|
--amd64)
|
||||||
|
BUILD_LIST+=("amd64")
|
||||||
|
;;
|
||||||
|
--i386)
|
||||||
|
BUILD_LIST+=("i386")
|
||||||
|
;;
|
||||||
|
--aarch64)
|
||||||
|
BUILD_LIST+=("aarch64")
|
||||||
|
;;
|
||||||
|
--all)
|
||||||
|
BUILD_LIST=("armhf" "amd64" "i386" "aarch64")
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "[WARN] $0 : Argument '$1' unknown will be Ignoring"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if an architecture is available
|
||||||
|
if [ "${#BUILD_LIST[@]}" -eq 0 ]; then
|
||||||
|
echo "[ERROR] You need select an architecture for build!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#### Main ####
|
||||||
|
|
||||||
|
mkdir -p /data
|
||||||
|
|
||||||
|
# Setup docker env
|
||||||
|
init_crosscompile
|
||||||
|
start_docker
|
||||||
|
|
||||||
|
# Select arch build
|
||||||
|
for arch in "${BUILD_LIST[@]}"; do
|
||||||
|
(build_addon "$arch") &
|
||||||
|
BUILD_TASKS+=($!)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Wait until all build jobs are done
|
||||||
|
wait "${BUILD_TASKS[@]}"
|
||||||
|
|
||||||
|
# Cleanup docker env
|
||||||
|
clean_crosscompile
|
||||||
|
stop_docker
|
||||||
|
|
||||||
|
exit 0
|
||||||
7
docker/platformio-esp8266.ini
Normal file
7
docker/platformio-esp8266.ini
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
; This file allows the docker build file to install the required platformio
|
||||||
|
; platforms
|
||||||
|
|
||||||
|
[env:espressif8266]
|
||||||
|
platform = espressif8266
|
||||||
|
board = nodemcuv2
|
||||||
|
framework = arduino
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
; This file allows the docker build file to install the required platformio
|
; This file allows the docker build file to install the required platformio
|
||||||
; platforms
|
; platforms
|
||||||
|
|
||||||
[env:espressif32]
|
|
||||||
platform = espressif32
|
|
||||||
board = nodemcu-32s
|
|
||||||
framework = arduino
|
|
||||||
|
|
||||||
[env:espressif8266]
|
[env:espressif8266]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
board = nodemcuv2
|
board = nodemcuv2
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
|
[env:espressif32]
|
||||||
|
platform = espressif32
|
||||||
|
board = nodemcu-32s
|
||||||
|
framework = arduino
|
||||||
|
|||||||
59
esphomeyaml-edge/Dockerfile
Normal file
59
esphomeyaml-edge/Dockerfile
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Dockerfile for HassIO add-on
|
||||||
|
ARG BUILD_FROM=ubuntu:bionic
|
||||||
|
FROM ${BUILD_FROM}
|
||||||
|
|
||||||
|
# Re-declare BUILD_FROM to fix weird docker issue
|
||||||
|
ARG BUILD_FROM
|
||||||
|
|
||||||
|
# On amd64 and alike, using ubuntu as the base is better as building
|
||||||
|
# for the ESP32 only works with glibc (and ubuntu). However, on armhf
|
||||||
|
# the build toolchain frequently procudes segfaults under ubuntu.
|
||||||
|
# -> Use ubuntu for most architectures, except alpine for armhf
|
||||||
|
#
|
||||||
|
# * python and related required because this is a python project
|
||||||
|
# * git required for platformio library dependencies downloads
|
||||||
|
# * libc6-compat and openssh required on alpine for weird reasons
|
||||||
|
# * disable platformio telemetry on install
|
||||||
|
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python python-pip python-setuptools python-pil git && \
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/*; \
|
||||||
|
else \
|
||||||
|
apk add --no-cache \
|
||||||
|
python2 \
|
||||||
|
python2-dev \
|
||||||
|
py2-pip \
|
||||||
|
git \
|
||||||
|
gcc \
|
||||||
|
openssh \
|
||||||
|
libc6-compat \
|
||||||
|
jpeg-dev \
|
||||||
|
zlib-dev \
|
||||||
|
freetype-dev \
|
||||||
|
lcms2-dev \
|
||||||
|
openjpeg-dev \
|
||||||
|
tiff-dev \
|
||||||
|
libc-dev \
|
||||||
|
linux-headers; \
|
||||||
|
fi" && \
|
||||||
|
pip install --no-cache-dir platformio && \
|
||||||
|
platformio settings set enable_telemetry No
|
||||||
|
|
||||||
|
|
||||||
|
# Create fake project to make platformio install all depdencies.
|
||||||
|
# * Ignore build errors from platformio - empty project
|
||||||
|
# * On alpine, only install ESP8266 toolchain
|
||||||
|
COPY platformio.ini /pio/platformio.ini
|
||||||
|
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
|
||||||
|
platformio run -e espressif32 -e espressif8266 -d /pio; exit 0; \
|
||||||
|
else \
|
||||||
|
echo \"\$(head -8 /pio/platformio.ini)\" >/pio/platformio.ini; \
|
||||||
|
platformio run -e espressif8266 -d /pio; exit 0; \
|
||||||
|
fi"
|
||||||
|
|
||||||
|
# Install latest esphomeyaml from git
|
||||||
|
RUN pip install --no-cache-dir \
|
||||||
|
git+git://github.com/OttoWinter/esphomeyaml.git && \
|
||||||
|
pip install --no-cache-dir pillow tzlocal
|
||||||
|
|
||||||
|
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||||
10
esphomeyaml-edge/build.json
Normal file
10
esphomeyaml-edge/build.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"squash": false,
|
||||||
|
"build_from": {
|
||||||
|
"aarch64": "arm64v8/ubuntu:bionic",
|
||||||
|
"amd64": "ubuntu:bionic",
|
||||||
|
"armhf": "homeassistant/armhf-base:latest",
|
||||||
|
"i386": "i386/ubuntu:bionic"
|
||||||
|
},
|
||||||
|
"args": {}
|
||||||
|
}
|
||||||
33
esphomeyaml-edge/config.json
Normal file
33
esphomeyaml-edge/config.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "esphomeyaml-edge",
|
||||||
|
"version": "dev",
|
||||||
|
"slug": "esphomeyaml-edge",
|
||||||
|
"description": "Development build of the esphomeyaml HassIO add-on.",
|
||||||
|
"url": "https://esphomelib.com/esphomeyaml/index.html",
|
||||||
|
"startup": "application",
|
||||||
|
"webui": "http://[HOST]:[PORT:6052]",
|
||||||
|
"boot": "auto",
|
||||||
|
"ports": {
|
||||||
|
"6052/tcp": 6052,
|
||||||
|
"6053/tcp": 6053
|
||||||
|
},
|
||||||
|
"arch": [
|
||||||
|
"aarch64",
|
||||||
|
"amd64",
|
||||||
|
"armhf",
|
||||||
|
"i386"
|
||||||
|
],
|
||||||
|
"auto_uart": true,
|
||||||
|
"map": [
|
||||||
|
"config:rw"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"password": ""
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"password": "str?"
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"ESPHOMEYAML_OTA_HOST_PORT": "6053"
|
||||||
|
}
|
||||||
|
}
|
||||||
12
esphomeyaml-edge/platformio.ini
Normal file
12
esphomeyaml-edge/platformio.ini
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
; This file allows the docker build file to install the required platformio
|
||||||
|
; platforms
|
||||||
|
|
||||||
|
[env:espressif8266]
|
||||||
|
platform = espressif8266
|
||||||
|
board = nodemcuv2
|
||||||
|
framework = arduino
|
||||||
|
|
||||||
|
[env:espressif32]
|
||||||
|
platform = espressif32
|
||||||
|
board = nodemcu-32s
|
||||||
|
framework = arduino
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Dockerfile for HassIO add-on
|
|
||||||
ARG BUILD_FROM
|
|
||||||
FROM $BUILD_FROM
|
|
||||||
|
|
||||||
ENV LANG C.UTF-8
|
|
||||||
|
|
||||||
# Install requirements for add-on
|
|
||||||
RUN apk add --no-cache python2 py2-pip git openssh libc6-compat && \
|
|
||||||
pip install --no-cache-dir platformio && \
|
|
||||||
platformio platform install espressif8266 \
|
|
||||||
--with-package tool-esptool \
|
|
||||||
--with-package framework-arduinoespressif8266 \
|
|
||||||
--with-package tool-mkspiffs \
|
|
||||||
--with-package tool-espotapy
|
|
||||||
|
|
||||||
RUN pip install --no-cache-dir \
|
|
||||||
git+git://github.com/OttoWinter/esphomeyaml.git@v1.6.0 \
|
|
||||||
tornado esptool
|
|
||||||
|
|
||||||
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
from datetime import datetime
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util
|
from esphomeyaml import const, core, core_config, mqtt, wizard, writer, yaml_util
|
||||||
from esphomeyaml.config import core_to_code, get_component, iter_components, read_config
|
from esphomeyaml.config import get_component, iter_components, read_config
|
||||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, CONF_HOSTNAME, \
|
from esphomeyaml.const import CONF_BAUD_RATE, CONF_BUILD_PATH, CONF_DOMAIN, CONF_ESPHOMEYAML, \
|
||||||
CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, ESP_PLATFORM_ESP8266
|
CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \
|
||||||
|
CONF_WIFI, ESP_PLATFORM_ESP8266
|
||||||
from esphomeyaml.core import ESPHomeYAMLError
|
from esphomeyaml.core import ESPHomeYAMLError
|
||||||
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
|
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
|
||||||
add_task, color, get_variable, indent, quote, statement
|
add_job, color, flush_tasks, indent, quote, statement
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -25,7 +26,8 @@ def get_name(config):
|
|||||||
|
|
||||||
|
|
||||||
def get_base_path(config):
|
def get_base_path(config):
|
||||||
return os.path.join(os.path.dirname(core.CONFIG_PATH), get_name(config))
|
build_path = config[CONF_ESPHOMEYAML].get(CONF_BUILD_PATH, get_name(config))
|
||||||
|
return os.path.join(os.path.dirname(core.CONFIG_PATH), build_path)
|
||||||
|
|
||||||
|
|
||||||
def get_serial_ports():
|
def get_serial_ports():
|
||||||
@@ -102,43 +104,42 @@ def run_miniterm(config, port, escape=False):
|
|||||||
|
|
||||||
with serial.Serial(port, baudrate=baud_rate) as ser:
|
with serial.Serial(port, baudrate=baud_rate) as ser:
|
||||||
while True:
|
while True:
|
||||||
line = ser.readline()
|
try:
|
||||||
|
raw = ser.readline()
|
||||||
|
except serial.SerialException:
|
||||||
|
_LOGGER.error("Serial port closed!")
|
||||||
|
return
|
||||||
|
line = raw.replace('\r', '').replace('\n', '')
|
||||||
time = datetime.now().time().strftime('[%H:%M:%S]')
|
time = datetime.now().time().strftime('[%H:%M:%S]')
|
||||||
message = time + line.decode('unicode-escape').replace('\r', '').replace('\n', '')
|
message = time + line
|
||||||
if escape:
|
if escape:
|
||||||
message = message.replace('\033', '\\033').encode('ascii', 'replace')
|
message = message.replace('\033', '\\033')
|
||||||
print(message)
|
try:
|
||||||
|
print(message)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
print(message.encode('ascii', 'backslashreplace'))
|
||||||
|
|
||||||
|
|
||||||
def write_cpp(config):
|
def write_cpp(config):
|
||||||
_LOGGER.info("Generating C++ source...")
|
_LOGGER.info("Generating C++ source...")
|
||||||
|
|
||||||
add_task(core_to_code, config[CONF_ESPHOMEYAML])
|
add_job(core_config.to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml')
|
||||||
for domain in PRE_INITIALIZE:
|
for domain in PRE_INITIALIZE:
|
||||||
if domain == CONF_ESPHOMEYAML:
|
if domain == CONF_ESPHOMEYAML or domain not in config:
|
||||||
continue
|
continue
|
||||||
if domain in config:
|
add_job(get_component(domain).to_code, config[domain], domain=domain)
|
||||||
add_task(get_component(domain).to_code, config[domain])
|
|
||||||
|
|
||||||
# Clear queue
|
|
||||||
get_variable(None)
|
|
||||||
add(RawStatement(''))
|
|
||||||
|
|
||||||
for domain, component, conf in iter_components(config):
|
for domain, component, conf in iter_components(config):
|
||||||
if domain in PRE_INITIALIZE:
|
if domain in PRE_INITIALIZE or not hasattr(component, 'to_code'):
|
||||||
continue
|
continue
|
||||||
if not hasattr(component, 'to_code'):
|
add_job(component.to_code, conf, domain=domain)
|
||||||
continue
|
|
||||||
add_task(component.to_code, conf)
|
|
||||||
|
|
||||||
# Clear queue
|
flush_tasks()
|
||||||
get_variable(None)
|
|
||||||
add(RawStatement(''))
|
add(RawStatement(''))
|
||||||
add(RawStatement(''))
|
add(RawStatement(''))
|
||||||
|
|
||||||
all_code = []
|
all_code = []
|
||||||
for exp in _EXPRESSIONS:
|
for exp in _EXPRESSIONS:
|
||||||
if core.SIMPLIFY:
|
if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]:
|
||||||
if isinstance(exp, Expression) and not exp.required:
|
if isinstance(exp, Expression) and not exp.required:
|
||||||
continue
|
continue
|
||||||
if isinstance(exp, AssignmentExpression) and not exp.obj.required:
|
if isinstance(exp, AssignmentExpression) and not exp.obj.required:
|
||||||
@@ -147,9 +148,7 @@ def write_cpp(config):
|
|||||||
exp = exp.rhs
|
exp = exp.rhs
|
||||||
all_code.append(unicode(statement(exp)))
|
all_code.append(unicode(statement(exp)))
|
||||||
|
|
||||||
platformio_ini_s = writer.get_ini_content(config)
|
writer.write_platformio_project(config, get_base_path(config))
|
||||||
ini_path = os.path.join(get_base_path(config), 'platformio.ini')
|
|
||||||
writer.write_platformio_ini(platformio_ini_s, ini_path)
|
|
||||||
|
|
||||||
code_s = indent('\n'.join(line.rstrip() for line in all_code))
|
code_s = indent('\n'.join(line.rstrip() for line in all_code))
|
||||||
cpp_path = os.path.join(get_base_path(config), 'src', 'main.cpp')
|
cpp_path = os.path.join(get_base_path(config), 'src', 'main.cpp')
|
||||||
@@ -157,9 +156,12 @@ def write_cpp(config):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def compile_program(config):
|
def compile_program(args, config):
|
||||||
_LOGGER.info("Compiling app...")
|
_LOGGER.info("Compiling app...")
|
||||||
return run_platformio('platformio', 'run', '-d', get_base_path(config))
|
command = ['platformio', 'run', '-d', get_base_path(config)]
|
||||||
|
if args.verbose:
|
||||||
|
command.append('-v')
|
||||||
|
return run_platformio(*command)
|
||||||
|
|
||||||
|
|
||||||
def get_upload_host(config):
|
def get_upload_host(config):
|
||||||
@@ -185,17 +187,28 @@ def upload_using_esptool(config, port):
|
|||||||
|
|
||||||
def upload_program(config, args, port):
|
def upload_program(config, args, port):
|
||||||
_LOGGER.info("Uploading binary...")
|
_LOGGER.info("Uploading binary...")
|
||||||
if port != 'OTA':
|
|
||||||
|
# if upload is to a serial port use platformio, otherwise assume ota
|
||||||
|
serial_port = port.startswith('/') or port.startswith('COM')
|
||||||
|
if port != 'OTA' and serial_port:
|
||||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266 and args.use_esptoolpy:
|
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266 and args.use_esptoolpy:
|
||||||
return upload_using_esptool(config, port)
|
return upload_using_esptool(config, port)
|
||||||
return run_platformio('platformio', 'run', '-d', get_base_path(config),
|
command = ['platformio', 'run', '-d', get_base_path(config),
|
||||||
'-t', 'upload', '--upload-port', port)
|
'-t', 'upload', '--upload-port', port]
|
||||||
|
if args.verbose:
|
||||||
|
command.append('-v')
|
||||||
|
return run_platformio(*command)
|
||||||
|
|
||||||
if 'ota' not in config:
|
if 'ota' not in config:
|
||||||
_LOGGER.error("No serial port found and OTA not enabled. Can't upload!")
|
_LOGGER.error("No serial port found and OTA not enabled. Can't upload!")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
host = get_upload_host(config)
|
# If hostname/ip is explicitly provided as upload-port argument, use this instead of zeroconf
|
||||||
|
# hostname. This is to support use cases where zeroconf (hostname.local) does not work.
|
||||||
|
if port != 'OTA':
|
||||||
|
host = port
|
||||||
|
else:
|
||||||
|
host = get_upload_host(config)
|
||||||
|
|
||||||
from esphomeyaml.components import ota
|
from esphomeyaml.components import ota
|
||||||
from esphomeyaml import espota
|
from esphomeyaml import espota
|
||||||
@@ -208,11 +221,14 @@ def upload_program(config, args, port):
|
|||||||
espota_args = ['espota.py', '--debug', '--progress', '-i', host,
|
espota_args = ['espota.py', '--debug', '--progress', '-i', host,
|
||||||
'-p', str(ota.get_port(config)), '-f', bin_file,
|
'-p', str(ota.get_port(config)), '-f', bin_file,
|
||||||
'-a', ota.get_auth(config), '-P', str(host_port)]
|
'-a', ota.get_auth(config), '-P', str(host_port)]
|
||||||
|
if args.verbose:
|
||||||
|
espota_args.append('-d')
|
||||||
return espota.main(espota_args)
|
return espota.main(espota_args)
|
||||||
|
|
||||||
|
|
||||||
def show_logs(config, args, port, escape=False):
|
def show_logs(config, args, port, escape=False):
|
||||||
if port != 'OTA':
|
serial_port = port.startswith('/') or port.startswith('COM')
|
||||||
|
if port != 'OTA' and serial_port:
|
||||||
run_miniterm(config, port, escape=escape)
|
run_miniterm(config, port, escape=escape)
|
||||||
return 0
|
return 0
|
||||||
return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id,
|
return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id,
|
||||||
@@ -223,8 +239,9 @@ def clean_mqtt(config, args):
|
|||||||
return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id)
|
return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id)
|
||||||
|
|
||||||
|
|
||||||
def setup_log():
|
def setup_log(debug=False):
|
||||||
logging.basicConfig(level=logging.INFO)
|
log_level = logging.DEBUG if debug else logging.INFO
|
||||||
|
logging.basicConfig(level=log_level)
|
||||||
fmt = "%(levelname)s [%(name)s] %(message)s"
|
fmt = "%(levelname)s [%(name)s] %(message)s"
|
||||||
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
|
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
|
||||||
datefmt = '%H:%M:%S'
|
datefmt = '%H:%M:%S'
|
||||||
@@ -253,7 +270,28 @@ def command_wizard(args):
|
|||||||
return wizard.wizard(args.configuration)
|
return wizard.wizard(args.configuration)
|
||||||
|
|
||||||
|
|
||||||
|
def strip_default_ids(config):
|
||||||
|
value = config
|
||||||
|
if isinstance(config, list):
|
||||||
|
value = type(config)()
|
||||||
|
for x in config:
|
||||||
|
if isinstance(x, core.ID) and not x.is_manual:
|
||||||
|
continue
|
||||||
|
value.append(strip_default_ids(x))
|
||||||
|
return value
|
||||||
|
elif isinstance(config, dict):
|
||||||
|
value = type(config)()
|
||||||
|
for k, v in config.iteritems():
|
||||||
|
if isinstance(v, core.ID) and not v.is_manual:
|
||||||
|
continue
|
||||||
|
value[k] = strip_default_ids(v)
|
||||||
|
return value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def command_config(args, config):
|
def command_config(args, config):
|
||||||
|
if not args.verbose:
|
||||||
|
config = strip_default_ids(config)
|
||||||
print(yaml_util.dump(config))
|
print(yaml_util.dump(config))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -262,7 +300,10 @@ def command_compile(args, config):
|
|||||||
exit_code = write_cpp(config)
|
exit_code = write_cpp(config)
|
||||||
if exit_code != 0:
|
if exit_code != 0:
|
||||||
return exit_code
|
return exit_code
|
||||||
exit_code = compile_program(config)
|
if args.only_generate:
|
||||||
|
_LOGGER.info(u"Successfully generated source code.")
|
||||||
|
return 0
|
||||||
|
exit_code = compile_program(args, config)
|
||||||
if exit_code != 0:
|
if exit_code != 0:
|
||||||
return exit_code
|
return exit_code
|
||||||
_LOGGER.info(u"Successfully compiled program.")
|
_LOGGER.info(u"Successfully compiled program.")
|
||||||
@@ -287,7 +328,7 @@ def command_run(args, config):
|
|||||||
exit_code = write_cpp(config)
|
exit_code = write_cpp(config)
|
||||||
if exit_code != 0:
|
if exit_code != 0:
|
||||||
return exit_code
|
return exit_code
|
||||||
exit_code = compile_program(config)
|
exit_code = compile_program(args, config)
|
||||||
if exit_code != 0:
|
if exit_code != 0:
|
||||||
return exit_code
|
return exit_code
|
||||||
_LOGGER.info(u"Successfully compiled program.")
|
_LOGGER.info(u"Successfully compiled program.")
|
||||||
@@ -339,13 +380,19 @@ POST_CONFIG_ACTIONS = {
|
|||||||
|
|
||||||
def parse_args(argv):
|
def parse_args(argv):
|
||||||
parser = argparse.ArgumentParser(prog='esphomeyaml')
|
parser = argparse.ArgumentParser(prog='esphomeyaml')
|
||||||
|
parser.add_argument('-v', '--verbose', help="Enable verbose esphomeyaml logs.",
|
||||||
|
action='store_true')
|
||||||
parser.add_argument('configuration', help='Your YAML configuration file.')
|
parser.add_argument('configuration', help='Your YAML configuration file.')
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(help='Commands', dest='command')
|
subparsers = parser.add_subparsers(help='Commands', dest='command')
|
||||||
subparsers.required = True
|
subparsers.required = True
|
||||||
subparsers.add_parser('config', help='Validate the configuration and spit it out.')
|
subparsers.add_parser('config', help='Validate the configuration and spit it out.')
|
||||||
|
|
||||||
subparsers.add_parser('compile', help='Read the configuration and compile a program.')
|
parser_compile = subparsers.add_parser('compile',
|
||||||
|
help='Read the configuration and compile a program.')
|
||||||
|
parser_compile.add_argument('--only-generate',
|
||||||
|
help="Only generate source code, do not compile.",
|
||||||
|
action='store_true')
|
||||||
|
|
||||||
parser_upload = subparsers.add_parser('upload', help='Validate the configuration '
|
parser_upload = subparsers.add_parser('upload', help='Validate the configuration '
|
||||||
'and upload the latest binary.')
|
'and upload the latest binary.')
|
||||||
@@ -369,7 +416,7 @@ def parse_args(argv):
|
|||||||
|
|
||||||
parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, '
|
parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, '
|
||||||
'upload it, and start MQTT logs.')
|
'upload it, and start MQTT logs.')
|
||||||
parser_run.add_argument('--upload-port', help="Manually specify the upload port to use. "
|
parser_run.add_argument('--upload-port', help="Manually specify the upload port/ip to use. "
|
||||||
"For example /dev/cu.SLAB_USBtoUART.")
|
"For example /dev/cu.SLAB_USBtoUART.")
|
||||||
parser_run.add_argument('--host-port', help="Specify the host port to use for OTA", type=int)
|
parser_run.add_argument('--host-port', help="Specify the host port to use for OTA", type=int)
|
||||||
parser_run.add_argument('--no-logs', help='Disable starting MQTT logs.',
|
parser_run.add_argument('--no-logs', help='Disable starting MQTT logs.',
|
||||||
@@ -402,13 +449,15 @@ def parse_args(argv):
|
|||||||
help="Create a simple webserver for a dashboard.")
|
help="Create a simple webserver for a dashboard.")
|
||||||
dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int,
|
dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int,
|
||||||
default=6052)
|
default=6052)
|
||||||
|
dashboard.add_argument("--password", help="The optional password to require for all requests.",
|
||||||
|
type=str, default='')
|
||||||
|
|
||||||
return parser.parse_args(argv[1:])
|
return parser.parse_args(argv[1:])
|
||||||
|
|
||||||
|
|
||||||
def run_esphomeyaml(argv):
|
def run_esphomeyaml(argv):
|
||||||
setup_log()
|
|
||||||
args = parse_args(argv)
|
args = parse_args(argv)
|
||||||
|
setup_log(args.verbose)
|
||||||
if args.command in PRE_CONFIG_ACTIONS:
|
if args.command in PRE_CONFIG_ACTIONS:
|
||||||
try:
|
try:
|
||||||
return PRE_CONFIG_ACTIONS[args.command](args)
|
return PRE_CONFIG_ACTIONS[args.command](args)
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import cover, fan
|
from esphomeyaml import core
|
||||||
from esphomeyaml.const import CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, CONF_BLUE, \
|
from esphomeyaml.components import cover, deep_sleep, fan, output
|
||||||
CONF_BRIGHTNESS, CONF_CONDITION_ID, CONF_DELAY, CONF_EFFECT, CONF_FLASH_LENGTH, CONF_GREEN, \
|
from esphomeyaml.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \
|
||||||
CONF_ID, CONF_IF, CONF_LAMBDA, CONF_OR, CONF_OSCILLATING, CONF_PAYLOAD, \
|
CONF_BELOW, CONF_BLUE, CONF_BRIGHTNESS, CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, \
|
||||||
CONF_QOS, CONF_RANGE, CONF_RED, CONF_RETAIN, CONF_SPEED, CONF_THEN, CONF_TOPIC, \
|
CONF_EFFECT, CONF_ELSE, CONF_FLASH_LENGTH, CONF_GREEN, CONF_ID, CONF_IF, CONF_LAMBDA, \
|
||||||
CONF_TRANSITION_LENGTH, CONF_TRIGGER_ID, CONF_WHITE, CONF_ABOVE, CONF_BELOW
|
CONF_LEVEL, CONF_OR, CONF_OSCILLATING, CONF_PAYLOAD, CONF_QOS, CONF_RANGE, CONF_RED, \
|
||||||
|
CONF_RETAIN, CONF_SPEED, CONF_THEN, CONF_TOPIC, CONF_TRANSITION_LENGTH, CONF_TRIGGER_ID, \
|
||||||
|
CONF_WHITE, CONF_COLOR_TEMPERATURE
|
||||||
from esphomeyaml.core import ESPHomeYAMLError
|
from esphomeyaml.core import ESPHomeYAMLError
|
||||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, TemplateArguments, add, \
|
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, TemplateArguments, add, add_job, \
|
||||||
bool_, esphomelib_ns, float_, get_variable, process_lambda, std_string, templatable, uint32, \
|
bool_, esphomelib_ns, float_, get_variable, process_lambda, std_string, templatable, uint32, \
|
||||||
uint8
|
uint8
|
||||||
|
|
||||||
@@ -25,14 +27,40 @@ CONF_COVER_STOP = 'cover.stop'
|
|||||||
CONF_FAN_TOGGLE = 'fan.toggle'
|
CONF_FAN_TOGGLE = 'fan.toggle'
|
||||||
CONF_FAN_TURN_OFF = 'fan.turn_off'
|
CONF_FAN_TURN_OFF = 'fan.turn_off'
|
||||||
CONF_FAN_TURN_ON = 'fan.turn_on'
|
CONF_FAN_TURN_ON = 'fan.turn_on'
|
||||||
|
CONF_OUTPUT_TURN_ON = 'output.turn_on'
|
||||||
|
CONF_OUTPUT_TURN_OFF = 'output.turn_off'
|
||||||
|
CONF_OUTPUT_SET_LEVEL = 'output.set_level'
|
||||||
|
CONF_DEEP_SLEEP_ENTER = 'deep_sleep.enter'
|
||||||
|
CONF_DEEP_SLEEP_PREVENT = 'deep_sleep.prevent'
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_simple_id(*validators):
|
||||||
|
validator = vol.All(*validators)
|
||||||
|
|
||||||
|
def validate(value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return validator(value)
|
||||||
|
return validator({CONF_ID: value})
|
||||||
|
|
||||||
|
return validate
|
||||||
|
|
||||||
|
|
||||||
|
def validate_recursive_condition(value):
|
||||||
|
return CONDITIONS_SCHEMA(value)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_recursive_action(value):
|
||||||
|
return ACTIONS_SCHEMA(value)
|
||||||
|
|
||||||
|
|
||||||
ACTION_KEYS = [CONF_DELAY, CONF_MQTT_PUBLISH, CONF_LIGHT_TOGGLE, CONF_LIGHT_TURN_OFF,
|
ACTION_KEYS = [CONF_DELAY, CONF_MQTT_PUBLISH, CONF_LIGHT_TOGGLE, CONF_LIGHT_TURN_OFF,
|
||||||
CONF_LIGHT_TURN_ON, CONF_SWITCH_TOGGLE, CONF_SWITCH_TURN_OFF, CONF_SWITCH_TURN_ON,
|
CONF_LIGHT_TURN_ON, CONF_SWITCH_TOGGLE, CONF_SWITCH_TURN_OFF, CONF_SWITCH_TURN_ON,
|
||||||
CONF_LAMBDA, CONF_COVER_OPEN, CONF_COVER_CLOSE, CONF_COVER_STOP, CONF_FAN_TOGGLE,
|
CONF_LAMBDA, CONF_COVER_OPEN, CONF_COVER_CLOSE, CONF_COVER_STOP, CONF_FAN_TOGGLE,
|
||||||
CONF_FAN_TURN_OFF, CONF_FAN_TURN_ON]
|
CONF_FAN_TURN_OFF, CONF_FAN_TURN_ON, CONF_OUTPUT_TURN_ON, CONF_OUTPUT_TURN_OFF,
|
||||||
|
CONF_OUTPUT_SET_LEVEL, CONF_IF, CONF_DEEP_SLEEP_ENTER, CONF_DEEP_SLEEP_PREVENT]
|
||||||
|
|
||||||
ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
||||||
cv.GenerateID('action', CONF_ACTION_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_ACTION_ID): cv.declare_variable_id(None),
|
||||||
vol.Optional(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds),
|
vol.Optional(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds),
|
||||||
vol.Optional(CONF_MQTT_PUBLISH): vol.Schema({
|
vol.Optional(CONF_MQTT_PUBLISH): vol.Schema({
|
||||||
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
|
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
|
||||||
@@ -40,16 +68,16 @@ ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
|||||||
vol.Optional(CONF_QOS): cv.templatable(cv.mqtt_qos),
|
vol.Optional(CONF_QOS): cv.templatable(cv.mqtt_qos),
|
||||||
vol.Optional(CONF_RETAIN): cv.templatable(cv.boolean),
|
vol.Optional(CONF_RETAIN): cv.templatable(cv.boolean),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_LIGHT_TOGGLE): vol.Schema({
|
vol.Optional(CONF_LIGHT_TOGGLE): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_LIGHT_TURN_OFF): vol.Schema({
|
vol.Optional(CONF_LIGHT_TURN_OFF): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_LIGHT_TURN_ON): vol.Schema({
|
vol.Optional(CONF_LIGHT_TURN_ON): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
vol.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'):
|
vol.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'):
|
||||||
cv.templatable(cv.positive_time_period_milliseconds),
|
cv.templatable(cv.positive_time_period_milliseconds),
|
||||||
vol.Exclusive(CONF_FLASH_LENGTH, 'transformer'):
|
vol.Exclusive(CONF_FLASH_LENGTH, 'transformer'):
|
||||||
@@ -59,63 +87,79 @@ ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
|||||||
vol.Optional(CONF_GREEN): cv.templatable(cv.percentage),
|
vol.Optional(CONF_GREEN): cv.templatable(cv.percentage),
|
||||||
vol.Optional(CONF_BLUE): cv.templatable(cv.percentage),
|
vol.Optional(CONF_BLUE): cv.templatable(cv.percentage),
|
||||||
vol.Optional(CONF_WHITE): cv.templatable(cv.percentage),
|
vol.Optional(CONF_WHITE): cv.templatable(cv.percentage),
|
||||||
|
vol.Optional(CONF_COLOR_TEMPERATURE): cv.templatable(cv.positive_float),
|
||||||
vol.Optional(CONF_EFFECT): cv.templatable(cv.string),
|
vol.Optional(CONF_EFFECT): cv.templatable(cv.string),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_SWITCH_TOGGLE): vol.Schema({
|
vol.Optional(CONF_SWITCH_TOGGLE): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_SWITCH_TURN_OFF): vol.Schema({
|
vol.Optional(CONF_SWITCH_TURN_OFF): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_SWITCH_TURN_ON): vol.Schema({
|
vol.Optional(CONF_SWITCH_TURN_ON): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_OPEN): vol.Schema({
|
vol.Optional(CONF_COVER_OPEN): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
|
vol.Optional(CONF_COVER_CLOSE): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_STOP): vol.Schema({
|
vol.Optional(CONF_COVER_STOP): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_OPEN): vol.Schema({
|
vol.Optional(CONF_COVER_OPEN): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
|
vol.Optional(CONF_COVER_CLOSE): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_COVER_STOP): vol.Schema({
|
vol.Optional(CONF_COVER_STOP): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_FAN_TOGGLE): vol.Schema({
|
vol.Optional(CONF_FAN_TOGGLE): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_FAN_TURN_OFF): vol.Schema({
|
vol.Optional(CONF_FAN_TURN_OFF): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
}),
|
}),
|
||||||
vol.Optional(CONF_FAN_TURN_ON): vol.Schema({
|
vol.Optional(CONF_FAN_TURN_ON): maybe_simple_id({
|
||||||
vol.Required(CONF_ID): cv.variable_id,
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
|
vol.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
|
||||||
vol.Optional(CONF_SPEED): cv.templatable(fan.validate_fan_speed),
|
vol.Optional(CONF_SPEED): cv.templatable(fan.validate_fan_speed),
|
||||||
}),
|
}),
|
||||||
|
vol.Optional(CONF_OUTPUT_TURN_OFF): maybe_simple_id({
|
||||||
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_OUTPUT_TURN_ON): maybe_simple_id({
|
||||||
|
vol.Required(CONF_ID): cv.use_variable_id(None)
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_OUTPUT_SET_LEVEL): {
|
||||||
|
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_LEVEL): cv.percentage,
|
||||||
|
},
|
||||||
|
vol.Optional(CONF_DEEP_SLEEP_ENTER): maybe_simple_id({
|
||||||
|
vol.Required(CONF_ID): cv.use_variable_id(deep_sleep.DeepSleepComponent),
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_DEEP_SLEEP_PREVENT): maybe_simple_id({
|
||||||
|
vol.Required(CONF_ID): cv.use_variable_id(deep_sleep.DeepSleepComponent),
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_IF): vol.All({
|
||||||
|
vol.Required(CONF_CONDITION): validate_recursive_condition,
|
||||||
|
vol.Optional(CONF_THEN): validate_recursive_action,
|
||||||
|
vol.Optional(CONF_ELSE): validate_recursive_action,
|
||||||
|
}, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE)),
|
||||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||||
}, cv.has_at_exactly_one_key(*ACTION_KEYS))])
|
}, cv.has_exactly_one_key(*ACTION_KEYS))])
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
DelayAction = esphomelib_ns.DelayAction
|
DelayAction = esphomelib_ns.DelayAction
|
||||||
LambdaAction = esphomelib_ns.LambdaAction
|
LambdaAction = esphomelib_ns.LambdaAction
|
||||||
|
IfAction = esphomelib_ns.IfAction
|
||||||
Automation = esphomelib_ns.Automation
|
Automation = esphomelib_ns.Automation
|
||||||
|
|
||||||
|
CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [cv.templatable({
|
||||||
def validate_recursive_condition(value):
|
cv.GenerateID(CONF_CONDITION_ID): cv.declare_variable_id(None),
|
||||||
return CONDITIONS_SCHEMA(value)
|
|
||||||
|
|
||||||
|
|
||||||
CONDITION_KEYS = [CONF_AND, CONF_OR, CONF_RANGE, CONF_LAMBDA]
|
|
||||||
|
|
||||||
CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
|
||||||
cv.GenerateID('condition', CONF_CONDITION_ID): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_AND): validate_recursive_condition,
|
vol.Optional(CONF_AND): validate_recursive_condition,
|
||||||
vol.Optional(CONF_OR): validate_recursive_condition,
|
vol.Optional(CONF_OR): validate_recursive_condition,
|
||||||
vol.Optional(CONF_RANGE): vol.All(vol.Schema({
|
vol.Optional(CONF_RANGE): vol.All(vol.Schema({
|
||||||
@@ -123,7 +167,7 @@ CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
|||||||
vol.Optional(CONF_BELOW): vol.Coerce(float),
|
vol.Optional(CONF_BELOW): vol.Coerce(float),
|
||||||
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)),
|
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)),
|
||||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||||
}), cv.has_at_exactly_one_key(*CONDITION_KEYS)])
|
})])
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
AndCondition = esphomelib_ns.AndCondition
|
AndCondition = esphomelib_ns.AndCondition
|
||||||
@@ -131,9 +175,25 @@ OrCondition = esphomelib_ns.OrCondition
|
|||||||
RangeCondition = esphomelib_ns.RangeCondition
|
RangeCondition = esphomelib_ns.RangeCondition
|
||||||
LambdaCondition = esphomelib_ns.LambdaCondition
|
LambdaCondition = esphomelib_ns.LambdaCondition
|
||||||
|
|
||||||
|
|
||||||
|
def validate_automation(extra_schema=None):
|
||||||
|
schema = AUTOMATION_SCHEMA.extend(extra_schema or {})
|
||||||
|
|
||||||
|
def validator(value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
return schema({CONF_THEN: value})
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
if CONF_THEN in value:
|
||||||
|
return schema(value)
|
||||||
|
return schema({CONF_THEN: value})
|
||||||
|
return schema(value)
|
||||||
|
|
||||||
|
return validator
|
||||||
|
|
||||||
|
|
||||||
AUTOMATION_SCHEMA = vol.Schema({
|
AUTOMATION_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('trigger', CONF_TRIGGER_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(None),
|
||||||
cv.GenerateID('automation', CONF_AUTOMATION_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(None),
|
||||||
vol.Optional(CONF_IF): CONDITIONS_SCHEMA,
|
vol.Optional(CONF_IF): CONDITIONS_SCHEMA,
|
||||||
vol.Required(CONF_THEN): ACTIONS_SCHEMA,
|
vol.Required(CONF_THEN): ACTIONS_SCHEMA,
|
||||||
})
|
})
|
||||||
@@ -141,157 +201,298 @@ AUTOMATION_SCHEMA = vol.Schema({
|
|||||||
|
|
||||||
def build_condition(config, arg_type):
|
def build_condition(config, arg_type):
|
||||||
template_arg = TemplateArguments(arg_type)
|
template_arg = TemplateArguments(arg_type)
|
||||||
if CONF_AND in config:
|
if isinstance(config, core.Lambda):
|
||||||
return AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg))
|
lambda_ = None
|
||||||
if CONF_OR in config:
|
for lambda_ in process_lambda(config, [(arg_type, 'x')]):
|
||||||
return OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg))
|
yield
|
||||||
if CONF_LAMBDA in config:
|
yield LambdaCondition.new(template_arg, lambda_)
|
||||||
return LambdaCondition.new(template_arg,
|
elif CONF_AND in config:
|
||||||
process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]))
|
yield AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg))
|
||||||
if CONF_RANGE in config:
|
elif CONF_OR in config:
|
||||||
|
yield OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg))
|
||||||
|
elif CONF_LAMBDA in config:
|
||||||
|
lambda_ = None
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]):
|
||||||
|
yield
|
||||||
|
yield LambdaCondition.new(template_arg, lambda_)
|
||||||
|
elif CONF_RANGE in config:
|
||||||
conf = config[CONF_RANGE]
|
conf = config[CONF_RANGE]
|
||||||
rhs = RangeCondition.new(template_arg)
|
rhs = RangeCondition.new(template_arg)
|
||||||
condition = Pvariable(RangeCondition.template(template_arg), config[CONF_CONDITION_ID], rhs)
|
type = RangeCondition.template(template_arg)
|
||||||
|
condition = Pvariable(config[CONF_CONDITION_ID], rhs, type=type)
|
||||||
if CONF_ABOVE in conf:
|
if CONF_ABOVE in conf:
|
||||||
condition.set_min(templatable(conf[CONF_ABOVE], arg_type, float_))
|
template_ = None
|
||||||
|
for template_ in templatable(conf[CONF_ABOVE], arg_type, float_):
|
||||||
|
yield
|
||||||
|
condition.set_min(template_)
|
||||||
if CONF_BELOW in conf:
|
if CONF_BELOW in conf:
|
||||||
condition.set_max(templatable(conf[CONF_BELOW], arg_type, float_))
|
template_ = None
|
||||||
return condition
|
for template_ in templatable(conf[CONF_BELOW], arg_type, float_):
|
||||||
raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
|
yield
|
||||||
|
condition.set_max(template_)
|
||||||
|
yield condition
|
||||||
|
else:
|
||||||
|
raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
|
||||||
|
|
||||||
|
|
||||||
def build_conditions(config, arg_type):
|
def build_conditions(config, arg_type):
|
||||||
return ArrayInitializer(*[build_condition(x, arg_type) for x in config])
|
conditions = []
|
||||||
|
for conf in config:
|
||||||
|
condition = None
|
||||||
|
for condition in build_condition(conf, arg_type):
|
||||||
|
yield None
|
||||||
|
conditions.append(condition)
|
||||||
|
yield ArrayInitializer(*conditions)
|
||||||
|
|
||||||
|
|
||||||
def build_action(config, arg_type):
|
def build_action(full_config, arg_type):
|
||||||
from esphomeyaml.components import light, mqtt, switch
|
from esphomeyaml.components import light, mqtt, switch
|
||||||
|
|
||||||
template_arg = TemplateArguments(arg_type)
|
template_arg = TemplateArguments(arg_type)
|
||||||
if CONF_DELAY in config:
|
# Keep pylint from freaking out
|
||||||
|
var = None
|
||||||
|
action_id = full_config[CONF_ACTION_ID]
|
||||||
|
key, config = next((k, v) for k, v in full_config.items() if k in ACTION_KEYS)
|
||||||
|
if key == CONF_DELAY:
|
||||||
rhs = App.register_component(DelayAction.new(template_arg))
|
rhs = App.register_component(DelayAction.new(template_arg))
|
||||||
action = Pvariable(DelayAction.template(template_arg), config[CONF_ACTION_ID], rhs)
|
type = DelayAction.template(template_arg)
|
||||||
add(action.set_delay(templatable(config[CONF_DELAY], arg_type, uint32)))
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
return action
|
for template_ in templatable(config, arg_type, uint32):
|
||||||
elif CONF_LAMBDA in config:
|
yield
|
||||||
rhs = LambdaAction.new(template_arg, process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]))
|
add(action.set_delay(template_))
|
||||||
return Pvariable(LambdaAction.template(template_arg), config[CONF_ACTION_ID], rhs)
|
yield action
|
||||||
elif CONF_MQTT_PUBLISH in config:
|
elif key == CONF_LAMBDA:
|
||||||
conf = config[CONF_MQTT_PUBLISH]
|
for lambda_ in process_lambda(config, [(arg_type, 'x')]):
|
||||||
rhs = App.Pget_mqtt_client().Pmake_publish_action()
|
yield None
|
||||||
action = Pvariable(mqtt.MQTTPublishAction.template(template_arg), config[CONF_ACTION_ID],
|
rhs = LambdaAction.new(template_arg, lambda_)
|
||||||
rhs)
|
type = LambdaAction.template(template_arg)
|
||||||
add(action.set_topic(templatable(conf[CONF_TOPIC], arg_type, std_string)))
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
add(action.set_payload(templatable(conf[CONF_PAYLOAD], arg_type, std_string)))
|
elif key == CONF_MQTT_PUBLISH:
|
||||||
if CONF_QOS in conf:
|
rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg)
|
||||||
add(action.set_qos(templatable(conf[CONF_QOS], arg_type, uint8)))
|
type = mqtt.MQTTPublishAction.template(template_arg)
|
||||||
if CONF_RETAIN in conf:
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
add(action.set_retain(templatable(conf[CONF_RETAIN], arg_type, bool_)))
|
for template_ in templatable(config[CONF_TOPIC], arg_type, std_string):
|
||||||
return action
|
yield None
|
||||||
elif CONF_LIGHT_TOGGLE in config:
|
add(action.set_topic(template_))
|
||||||
conf = config[CONF_LIGHT_TOGGLE]
|
|
||||||
var = get_variable(conf[CONF_ID])
|
for template_ in templatable(config[CONF_PAYLOAD], arg_type, std_string):
|
||||||
|
yield None
|
||||||
|
add(action.set_payload(template_))
|
||||||
|
if CONF_QOS in config:
|
||||||
|
for template_ in templatable(config[CONF_QOS], arg_type, uint8):
|
||||||
|
yield
|
||||||
|
add(action.set_qos(template_))
|
||||||
|
if CONF_RETAIN in config:
|
||||||
|
for template_ in templatable(config[CONF_RETAIN], arg_type, bool_):
|
||||||
|
yield None
|
||||||
|
add(action.set_retain(template_))
|
||||||
|
yield action
|
||||||
|
elif key == CONF_LIGHT_TOGGLE:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_toggle_action(template_arg)
|
rhs = var.make_toggle_action(template_arg)
|
||||||
action = Pvariable(light.ToggleAction.template(template_arg), config[CONF_ACTION_ID], rhs)
|
type = light.ToggleAction.template(template_arg)
|
||||||
if CONF_TRANSITION_LENGTH in conf:
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
add(action.set_transition_length(
|
if CONF_TRANSITION_LENGTH in config:
|
||||||
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
|
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||||
))
|
yield None
|
||||||
return action
|
add(action.set_transition_length(template_))
|
||||||
elif CONF_LIGHT_TURN_OFF in config:
|
yield action
|
||||||
conf = config[CONF_LIGHT_TURN_OFF]
|
elif key == CONF_LIGHT_TURN_OFF:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_off_action(template_arg)
|
rhs = var.make_turn_off_action(template_arg)
|
||||||
action = Pvariable(light.TurnOffAction.template(template_arg), config[CONF_ACTION_ID], rhs)
|
type = light.TurnOffAction.template(template_arg)
|
||||||
if CONF_TRANSITION_LENGTH in conf:
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
add(action.set_transition_length(
|
if CONF_TRANSITION_LENGTH in config:
|
||||||
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
|
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||||
))
|
yield None
|
||||||
return action
|
add(action.set_transition_length(template_))
|
||||||
elif CONF_LIGHT_TURN_ON in config:
|
yield action
|
||||||
conf = config[CONF_LIGHT_TURN_ON]
|
elif key == CONF_LIGHT_TURN_ON:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_on_action(template_arg)
|
rhs = var.make_turn_on_action(template_arg)
|
||||||
action = Pvariable(light.TurnOnAction.template(template_arg), config[CONF_ACTION_ID], rhs)
|
type = light.TurnOnAction.template(template_arg)
|
||||||
if CONF_TRANSITION_LENGTH in conf:
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
add(action.set_transition_length(
|
if CONF_TRANSITION_LENGTH in config:
|
||||||
templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32)
|
for template_ in templatable(config[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||||
))
|
yield None
|
||||||
if CONF_FLASH_LENGTH in conf:
|
add(action.set_transition_length(template_))
|
||||||
add(action.set_flash_length(templatable(conf[CONF_FLASH_LENGTH], arg_type, uint32)))
|
if CONF_FLASH_LENGTH in config:
|
||||||
if CONF_BRIGHTNESS in conf:
|
for template_ in templatable(config[CONF_FLASH_LENGTH], arg_type, uint32):
|
||||||
add(action.set_brightness(templatable(conf[CONF_BRIGHTNESS], arg_type, float_)))
|
yield None
|
||||||
if CONF_RED in conf:
|
add(action.set_flash_length(template_))
|
||||||
add(action.set_red(templatable(conf[CONF_RED], arg_type, float_)))
|
if CONF_BRIGHTNESS in config:
|
||||||
if CONF_GREEN in conf:
|
for template_ in templatable(config[CONF_BRIGHTNESS], arg_type, float_):
|
||||||
add(action.set_green(templatable(conf[CONF_GREEN], arg_type, float_)))
|
yield None
|
||||||
if CONF_BLUE in conf:
|
add(action.set_brightness(template_))
|
||||||
add(action.set_blue(templatable(conf[CONF_BLUE], arg_type, float_)))
|
if CONF_RED in config:
|
||||||
if CONF_WHITE in conf:
|
for template_ in templatable(config[CONF_RED], arg_type, float_):
|
||||||
add(action.set_white(templatable(conf[CONF_WHITE], arg_type, float_)))
|
yield None
|
||||||
if CONF_EFFECT in conf:
|
add(action.set_red(template_))
|
||||||
add(action.set_effect(templatable(conf[CONF_EFFECT], arg_type, std_string)))
|
if CONF_GREEN in config:
|
||||||
return action
|
for template_ in templatable(config[CONF_GREEN], arg_type, float_):
|
||||||
elif CONF_SWITCH_TOGGLE in config:
|
yield None
|
||||||
conf = config[CONF_SWITCH_TOGGLE]
|
add(action.set_green(template_))
|
||||||
var = get_variable(conf[CONF_ID])
|
if CONF_BLUE in config:
|
||||||
|
for template_ in templatable(config[CONF_BLUE], arg_type, float_):
|
||||||
|
yield None
|
||||||
|
add(action.set_blue(template_))
|
||||||
|
if CONF_WHITE in config:
|
||||||
|
for template_ in templatable(config[CONF_WHITE], arg_type, 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_):
|
||||||
|
yield None
|
||||||
|
add(action.set_color_temperature(template_))
|
||||||
|
if CONF_EFFECT in config:
|
||||||
|
for template_ in templatable(config[CONF_EFFECT], arg_type, std_string):
|
||||||
|
yield None
|
||||||
|
add(action.set_effect(template_))
|
||||||
|
yield action
|
||||||
|
elif key == CONF_SWITCH_TOGGLE:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_toggle_action(template_arg)
|
rhs = var.make_toggle_action(template_arg)
|
||||||
return Pvariable(switch.ToggleAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = switch.ToggleAction.template(arg_type)
|
||||||
elif CONF_SWITCH_TURN_OFF in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_SWITCH_TURN_OFF]
|
elif key == CONF_SWITCH_TURN_OFF:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_off_action(template_arg)
|
rhs = var.make_turn_off_action(template_arg)
|
||||||
return Pvariable(switch.TurnOffAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = switch.TurnOffAction.template(arg_type)
|
||||||
elif CONF_SWITCH_TURN_ON in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_SWITCH_TURN_ON]
|
elif key == CONF_SWITCH_TURN_ON:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_on_action(template_arg)
|
rhs = var.make_turn_on_action(template_arg)
|
||||||
return Pvariable(switch.TurnOnAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = switch.TurnOnAction.template(arg_type)
|
||||||
elif CONF_COVER_OPEN in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_COVER_OPEN]
|
elif key == CONF_COVER_OPEN:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_open_action(template_arg)
|
rhs = var.make_open_action(template_arg)
|
||||||
return Pvariable(cover.OpenAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = cover.OpenAction.template(arg_type)
|
||||||
elif CONF_COVER_CLOSE in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_COVER_CLOSE]
|
elif key == CONF_COVER_CLOSE:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_close_action(template_arg)
|
rhs = var.make_close_action(template_arg)
|
||||||
return Pvariable(cover.CloseAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = cover.CloseAction.template(arg_type)
|
||||||
elif CONF_COVER_STOP in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_COVER_STOP]
|
elif key == CONF_COVER_STOP:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_stop_action(template_arg)
|
rhs = var.make_stop_action(template_arg)
|
||||||
return Pvariable(cover.StopAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = cover.StopAction.template(arg_type)
|
||||||
elif CONF_FAN_TOGGLE in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_FAN_TOGGLE]
|
elif key == CONF_FAN_TOGGLE:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_toggle_action(template_arg)
|
rhs = var.make_toggle_action(template_arg)
|
||||||
return Pvariable(fan.ToggleAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = fan.ToggleAction.template(arg_type)
|
||||||
elif CONF_FAN_TURN_OFF in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_FAN_TURN_OFF]
|
elif key == CONF_FAN_TURN_OFF:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_off_action(template_arg)
|
rhs = var.make_turn_off_action(template_arg)
|
||||||
return Pvariable(fan.TurnOffAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = fan.TurnOffAction.template(arg_type)
|
||||||
elif CONF_FAN_TURN_ON in config:
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
conf = config[CONF_FAN_TURN_ON]
|
elif key == CONF_FAN_TURN_ON:
|
||||||
var = get_variable(conf[CONF_ID])
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
rhs = var.make_turn_on_action(template_arg)
|
rhs = var.make_turn_on_action(template_arg)
|
||||||
action = Pvariable(fan.TurnOnAction.template(arg_type), config[CONF_ACTION_ID], rhs)
|
type = fan.TurnOnAction.template(arg_type)
|
||||||
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
if CONF_OSCILLATING in config:
|
if CONF_OSCILLATING in config:
|
||||||
add(action.set_oscillating(templatable(conf[CONF_OSCILLATING], arg_type, bool_)))
|
for template_ in templatable(config[CONF_OSCILLATING], arg_type, bool_):
|
||||||
|
yield None
|
||||||
|
add(action.set_oscillating(template_))
|
||||||
if CONF_SPEED in config:
|
if CONF_SPEED in config:
|
||||||
add(action.set_speed(templatable(conf[CONF_SPEED], arg_type, fan.FanSpeed)))
|
for template_ in templatable(config[CONF_SPEED], arg_type, fan.FanSpeed):
|
||||||
return action
|
yield None
|
||||||
raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
|
add(action.set_speed(template_))
|
||||||
|
yield action
|
||||||
|
elif key == CONF_OUTPUT_TURN_OFF:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
|
rhs = var.make_turn_off_action(template_arg)
|
||||||
|
type = output.TurnOffAction.template(arg_type)
|
||||||
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
|
elif key == CONF_OUTPUT_TURN_ON:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
|
rhs = var.make_turn_on_action(template_arg)
|
||||||
|
type = output.TurnOnAction.template(arg_type)
|
||||||
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
|
elif key == CONF_OUTPUT_SET_LEVEL:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
|
rhs = var.make_set_level_action(template_arg)
|
||||||
|
type = output.SetLevelAction.template(arg_type)
|
||||||
|
action = Pvariable(action_id, rhs, type=type)
|
||||||
|
for template_ in templatable(config[CONF_LEVEL], arg_type, bool_):
|
||||||
|
yield None
|
||||||
|
add(action.set_level(template_))
|
||||||
|
yield action
|
||||||
|
elif key == CONF_IF:
|
||||||
|
for conditions in build_conditions(config[CONF_CONDITION], arg_type):
|
||||||
|
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):
|
||||||
|
yield None
|
||||||
|
add(action.add_then(actions))
|
||||||
|
if CONF_ELSE in config:
|
||||||
|
for actions in build_actions(config[CONF_ELSE], arg_type):
|
||||||
|
yield None
|
||||||
|
add(action.add_else(actions))
|
||||||
|
yield action
|
||||||
|
elif key == CONF_DEEP_SLEEP_ENTER:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
|
rhs = var.make_enter_deep_sleep_action(template_arg)
|
||||||
|
type = deep_sleep.EnterDeepSleepAction.template(arg_type)
|
||||||
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
|
elif key == CONF_DEEP_SLEEP_PREVENT:
|
||||||
|
for var in get_variable(config[CONF_ID]):
|
||||||
|
yield None
|
||||||
|
rhs = var.make_prevent_deep_sleep_action(template_arg)
|
||||||
|
type = deep_sleep.PreventDeepSleepAction.template(arg_type)
|
||||||
|
yield Pvariable(action_id, rhs, type=type)
|
||||||
|
else:
|
||||||
|
raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
|
||||||
|
|
||||||
|
|
||||||
def build_actions(config, arg_type):
|
def build_actions(config, arg_type):
|
||||||
return ArrayInitializer(*[build_action(x, arg_type) for x in config])
|
actions = []
|
||||||
|
for conf in config:
|
||||||
|
action = None
|
||||||
|
for action in build_action(conf, arg_type):
|
||||||
|
yield None
|
||||||
|
actions.append(action)
|
||||||
|
yield ArrayInitializer(*actions, multiline=False)
|
||||||
|
|
||||||
|
|
||||||
|
def build_automation_(trigger, arg_type, config):
|
||||||
|
rhs = App.make_automation(TemplateArguments(arg_type), trigger)
|
||||||
|
type = Automation.template(arg_type)
|
||||||
|
obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type)
|
||||||
|
if CONF_IF in config:
|
||||||
|
conditions = None
|
||||||
|
for conditions in build_conditions(config[CONF_IF], arg_type):
|
||||||
|
yield None
|
||||||
|
add(obj.add_conditions(conditions))
|
||||||
|
actions = None
|
||||||
|
for actions in build_actions(config[CONF_THEN], arg_type):
|
||||||
|
yield None
|
||||||
|
add(obj.add_actions(actions))
|
||||||
|
yield obj
|
||||||
|
|
||||||
|
|
||||||
def build_automation(trigger, arg_type, config):
|
def build_automation(trigger, arg_type, config):
|
||||||
rhs = App.make_automation(trigger)
|
add_job(build_automation_, trigger, arg_type, config)
|
||||||
obj = Pvariable(Automation.template(arg_type), config[CONF_AUTOMATION_ID], rhs)
|
|
||||||
if CONF_IF in config:
|
|
||||||
add(obj.add_conditions(build_conditions(config[CONF_IF], arg_type)))
|
|
||||||
add(obj.add_actions(build_actions(config[CONF_THEN], arg_type)))
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ ADS1115Component = sensor.sensor_ns.ADS1115Component
|
|||||||
RATE_REMOVE_MESSAGE = """The rate option has been removed in 1.5.0 and is no longer required."""
|
RATE_REMOVE_MESSAGE = """The rate option has been removed in 1.5.0 and is no longer required."""
|
||||||
|
|
||||||
ADS1115_SCHEMA = vol.Schema({
|
ADS1115_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('ads1115'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
|
||||||
vol.Required(CONF_ADDRESS): cv.i2c_address,
|
vol.Required(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
|
||||||
vol.Optional(CONF_RATE): cv.invalid(RATE_REMOVE_MESSAGE)
|
vol.Optional(CONF_RATE): cv.invalid(RATE_REMOVE_MESSAGE)
|
||||||
@@ -24,7 +24,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
|
|||||||
def to_code(config):
|
def to_code(config):
|
||||||
for conf in config:
|
for conf in config:
|
||||||
rhs = App.make_ads1115_component(conf[CONF_ADDRESS])
|
rhs = App.make_ads1115_component(conf[CONF_ADDRESS])
|
||||||
Pvariable(ADS1115Component, conf[CONF_ID], rhs)
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
|
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import voluptuous as vol
|
|||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml import automation
|
from esphomeyaml import automation
|
||||||
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INVERTED, CONF_MAX_LENGTH, \
|
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INTERNAL, CONF_INVERTED, \
|
||||||
CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, CONF_ON_PRESS, \
|
CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, \
|
||||||
CONF_ON_RELEASE, CONF_TRIGGER_ID
|
CONF_ON_PRESS, CONF_ON_RELEASE, CONF_TRIGGER_ID, CONF_FILTERS, CONF_INVERT, CONF_DELAYED_ON, \
|
||||||
from esphomeyaml.helpers import App, NoArg, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
CONF_DELAYED_OFF, CONF_LAMBDA, CONF_HEARTBEAT
|
||||||
|
from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \
|
||||||
|
setup_mqtt_component, bool_, process_lambda, ArrayInitializer
|
||||||
|
|
||||||
DEVICE_CLASSES = [
|
DEVICE_CLASSES = [
|
||||||
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
|
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
|
||||||
@@ -24,72 +26,133 @@ ReleaseTrigger = binary_sensor_ns.ReleaseTrigger
|
|||||||
ClickTrigger = binary_sensor_ns.ClickTrigger
|
ClickTrigger = binary_sensor_ns.ClickTrigger
|
||||||
DoubleClickTrigger = binary_sensor_ns.DoubleClickTrigger
|
DoubleClickTrigger = binary_sensor_ns.DoubleClickTrigger
|
||||||
BinarySensor = binary_sensor_ns.BinarySensor
|
BinarySensor = binary_sensor_ns.BinarySensor
|
||||||
|
InvertFilter = binary_sensor_ns.InvertFilter
|
||||||
|
LambdaFilter = binary_sensor_ns.LambdaFilter
|
||||||
|
DelayedOnFilter = binary_sensor_ns.DelayedOnFilter
|
||||||
|
DelayedOffFilter = binary_sensor_ns.DelayedOffFilter
|
||||||
|
HeartbeatFilter = binary_sensor_ns.HeartbeatFilter
|
||||||
MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent
|
MQTTBinarySensorComponent = binary_sensor_ns.MQTTBinarySensorComponent
|
||||||
|
|
||||||
|
FILTER_KEYS = [CONF_INVERT, CONF_DELAYED_ON, CONF_DELAYED_OFF, CONF_LAMBDA]
|
||||||
|
|
||||||
|
FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
||||||
|
vol.Optional(CONF_INVERT): None,
|
||||||
|
vol.Optional(CONF_DELAYED_ON): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_DELAYED_OFF): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||||
|
}, cv.has_exactly_one_key(*FILTER_KEYS))])
|
||||||
|
|
||||||
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
||||||
cv.GenerateID('mqtt_binary_sensor', CONF_MQTT_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTBinarySensorComponent),
|
||||||
cv.GenerateID('binary_sensor'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(BinarySensor),
|
||||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
|
||||||
vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower, cv.one_of(*DEVICE_CLASSES)),
|
vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower, cv.one_of(*DEVICE_CLASSES)),
|
||||||
vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
|
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
|
||||||
vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
|
vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
vol.Optional(CONF_ON_CLICK): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PressTrigger),
|
||||||
|
})]),
|
||||||
|
vol.Optional(CONF_ON_RELEASE): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ReleaseTrigger),
|
||||||
|
})]),
|
||||||
|
vol.Optional(CONF_ON_CLICK): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ClickTrigger),
|
||||||
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
|
||||||
})]),
|
})]),
|
||||||
vol.Optional(CONF_ON_DOUBLE_CLICK):
|
vol.Optional(CONF_ON_DOUBLE_CLICK):
|
||||||
vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
|
vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(DoubleClickTrigger),
|
||||||
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
|
||||||
})]),
|
})]),
|
||||||
|
|
||||||
|
vol.Optional(CONF_INVERTED): cv.invalid(
|
||||||
|
"The inverted binary_sensor property has been replaced by the "
|
||||||
|
"new 'invert' binary sensor filter. Please see "
|
||||||
|
"https://esphomelib.com/esphomeyaml/components/binary_sensor/index.html."
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
BINARY_SENSOR_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_SENSOR_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_filter(config):
|
||||||
|
if CONF_INVERT in config:
|
||||||
|
yield InvertFilter.new()
|
||||||
|
elif CONF_DELAYED_OFF in config:
|
||||||
|
yield App.register_component(DelayedOffFilter.new(config[CONF_DELAYED_OFF]))
|
||||||
|
elif CONF_DELAYED_ON in config:
|
||||||
|
yield App.register_component(DelayedOnFilter.new(config[CONF_DELAYED_ON]))
|
||||||
|
elif CONF_HEARTBEAT in config:
|
||||||
|
yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
|
||||||
|
elif CONF_LAMBDA in config:
|
||||||
|
lambda_ = None
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(bool_, 'x')]):
|
||||||
|
yield None
|
||||||
|
yield LambdaFilter.new(lambda_)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_filters(config):
|
||||||
|
filters = []
|
||||||
|
for conf in config:
|
||||||
|
filter = None
|
||||||
|
for filter in setup_filter(conf):
|
||||||
|
yield None
|
||||||
|
filters.append(filter)
|
||||||
|
yield ArrayInitializer(*filters)
|
||||||
|
|
||||||
|
|
||||||
def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config):
|
def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config):
|
||||||
|
if CONF_INTERNAL in config:
|
||||||
|
add(binary_sensor_var.set_internal(CONF_INTERNAL))
|
||||||
if CONF_DEVICE_CLASS in config:
|
if CONF_DEVICE_CLASS in config:
|
||||||
add(binary_sensor_var.set_device_class(config[CONF_DEVICE_CLASS]))
|
add(binary_sensor_var.set_device_class(config[CONF_DEVICE_CLASS]))
|
||||||
if CONF_INVERTED in config:
|
if CONF_INVERTED in config:
|
||||||
add(binary_sensor_var.set_inverted(config[CONF_INVERTED]))
|
add(binary_sensor_var.set_inverted(config[CONF_INVERTED]))
|
||||||
|
if CONF_FILTERS in config:
|
||||||
|
filters = None
|
||||||
|
for filters in setup_filters(config[CONF_FILTERS]):
|
||||||
|
yield
|
||||||
|
add(binary_sensor_var.add_filters(filters))
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_PRESS, []):
|
for conf in config.get(CONF_ON_PRESS, []):
|
||||||
rhs = binary_sensor_var.make_press_trigger()
|
rhs = binary_sensor_var.make_press_trigger()
|
||||||
trigger = Pvariable(PressTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, NoArg, conf)
|
automation.build_automation(trigger, NoArg, conf)
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_RELEASE, []):
|
for conf in config.get(CONF_ON_RELEASE, []):
|
||||||
rhs = binary_sensor_var.make_release_trigger()
|
rhs = binary_sensor_var.make_release_trigger()
|
||||||
trigger = Pvariable(ReleaseTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, NoArg, conf)
|
automation.build_automation(trigger, NoArg, conf)
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_CLICK, []):
|
for conf in config.get(CONF_ON_CLICK, []):
|
||||||
rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH])
|
rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH])
|
||||||
trigger = Pvariable(ClickTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, NoArg, conf)
|
automation.build_automation(trigger, NoArg, conf)
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_DOUBLE_CLICK, []):
|
for conf in config.get(CONF_ON_DOUBLE_CLICK, []):
|
||||||
rhs = binary_sensor_var.make_double_click_trigger(conf[CONF_MIN_LENGTH],
|
rhs = binary_sensor_var.make_double_click_trigger(conf[CONF_MIN_LENGTH],
|
||||||
conf[CONF_MAX_LENGTH])
|
conf[CONF_MAX_LENGTH])
|
||||||
trigger = Pvariable(DoubleClickTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, NoArg, conf)
|
automation.build_automation(trigger, NoArg, conf)
|
||||||
|
|
||||||
setup_mqtt_component(mqtt_var, config)
|
setup_mqtt_component(mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
def setup_binary_sensor(binary_sensor_obj, mqtt_obj, config):
|
def setup_binary_sensor(binary_sensor_obj, mqtt_obj, config):
|
||||||
binary_sensor_var = Pvariable(BinarySensor, config[CONF_ID], binary_sensor_obj,
|
binary_sensor_var = Pvariable(config[CONF_ID], binary_sensor_obj,
|
||||||
has_side_effects=False)
|
has_side_effects=False)
|
||||||
mqtt_var = Pvariable(MQTTBinarySensorComponent, config[CONF_MQTT_ID], mqtt_obj,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj,
|
||||||
has_side_effects=False)
|
has_side_effects=False)
|
||||||
setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config)
|
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
def register_binary_sensor(var, config):
|
def register_binary_sensor(var, config):
|
||||||
binary_sensor_var = Pvariable(BinarySensor, config[CONF_ID], var,
|
binary_sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
|
||||||
has_side_effects=True)
|
|
||||||
rhs = App.register_binary_sensor(binary_sensor_var)
|
rhs = App.register_binary_sensor(binary_sensor_var)
|
||||||
mqtt_var = Pvariable(MQTTBinarySensorComponent, config[CONF_MQTT_ID], rhs,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
|
||||||
has_side_effects=True)
|
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
|
||||||
setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config)
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
|
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
|
||||||
from esphomeyaml.components import binary_sensor
|
|
||||||
from esphomeyaml.components.esp32_ble import ESP32BLETracker
|
|
||||||
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME, ESP_PLATFORM_ESP32
|
|
||||||
from esphomeyaml.core import HexInt, MACAddress
|
|
||||||
from esphomeyaml.helpers import ArrayInitializer, get_variable
|
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
|
||||||
DEPENDENCIES = ['esp32_ble']
|
|
||||||
|
|
||||||
|
|
||||||
def validate_mac(value):
|
|
||||||
value = cv.string_strict(value)
|
|
||||||
parts = value.split(':')
|
|
||||||
if len(parts) != 6:
|
|
||||||
raise vol.Invalid("MAC Address must consist of 6 : (colon) separated parts")
|
|
||||||
parts_int = []
|
|
||||||
if any(len(part) != 2 for part in parts):
|
|
||||||
raise vol.Invalid("MAC Address must be format XX:XX:XX:XX:XX:XX")
|
|
||||||
for part in parts:
|
|
||||||
try:
|
|
||||||
parts_int.append(int(part, 16))
|
|
||||||
except ValueError:
|
|
||||||
raise vol.Invalid("MAC Address parts must be hexadecimal values from 00 to FF")
|
|
||||||
|
|
||||||
return MACAddress(*parts_int)
|
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
vol.Required(CONF_MAC_ADDRESS): validate_mac,
|
|
||||||
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
|
||||||
hub = get_variable(None, type=ESP32BLETracker)
|
|
||||||
addr = [HexInt(i) for i in config[CONF_MAC_ADDRESS].parts]
|
|
||||||
rhs = hub.make_device(config[CONF_NAME], ArrayInitializer(*addr, multiline=False))
|
|
||||||
binary_sensor.register_binary_sensor(rhs, config)
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
|
|
||||||
23
esphomeyaml/components/binary_sensor/esp32_ble_tracker.py
Normal file
23
esphomeyaml/components/binary_sensor/esp32_ble_tracker.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \
|
||||||
|
make_address_array
|
||||||
|
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME
|
||||||
|
from esphomeyaml.helpers import get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_MAC_ADDRESS): cv.mac_address,
|
||||||
|
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker)
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_ESP32_BLE_ID]):
|
||||||
|
yield
|
||||||
|
rhs = hub.make_presence_sensor(config[CONF_NAME], make_address_array(config[CONF_MAC_ADDRESS]))
|
||||||
|
binary_sensor.register_binary_sensor(rhs, config)
|
||||||
@@ -11,6 +11,8 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
|||||||
|
|
||||||
DEPENDENCIES = ['esp32_touch']
|
DEPENDENCIES = ['esp32_touch']
|
||||||
|
|
||||||
|
CONF_ESP32_TOUCH_ID = 'esp32_touch_id'
|
||||||
|
|
||||||
TOUCH_PADS = {
|
TOUCH_PADS = {
|
||||||
4: global_ns.TOUCH_PAD_NUM0,
|
4: global_ns.TOUCH_PAD_NUM0,
|
||||||
0: global_ns.TOUCH_PAD_NUM1,
|
0: global_ns.TOUCH_PAD_NUM1,
|
||||||
@@ -32,14 +34,17 @@ def validate_touch_pad(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_PIN): validate_touch_pad,
|
vol.Required(CONF_PIN): validate_touch_pad,
|
||||||
vol.Required(CONF_THRESHOLD): cv.uint16_t,
|
vol.Required(CONF_THRESHOLD): cv.uint16_t,
|
||||||
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
|
cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_variable_id(ESP32TouchComponent),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
hub = get_variable(None, type=ESP32TouchComponent)
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_ESP32_TOUCH_ID]):
|
||||||
|
yield
|
||||||
touch_pad = TOUCH_PADS[config[CONF_PIN]]
|
touch_pad = TOUCH_PADS[config[CONF_PIN]]
|
||||||
rhs = hub.make_touch_pad(config[CONF_NAME], touch_pad, config[CONF_THRESHOLD])
|
rhs = hub.make_touch_pad(config[CONF_NAME], touch_pad, config[CONF_THRESHOLD])
|
||||||
binary_sensor.register_binary_sensor(rhs, config)
|
binary_sensor.register_binary_sensor(rhs, config)
|
||||||
|
|||||||
@@ -6,18 +6,20 @@ from esphomeyaml.components import binary_sensor
|
|||||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
|
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
|
||||||
from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application
|
from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application
|
||||||
|
|
||||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('gpio_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_PIN): pins.GPIO_INPUT_PIN_SCHEMA
|
|
||||||
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
|
|
||||||
|
|
||||||
MakeGPIOBinarySensor = Application.MakeGPIOBinarySensor
|
MakeGPIOBinarySensor = Application.MakeGPIOBinarySensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOBinarySensor),
|
||||||
|
vol.Required(CONF_PIN): pins.gpio_input_pin_schema
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_gpio_binary_sensor(config[CONF_NAME],
|
pin = None
|
||||||
gpio_input_pin_expression(config[CONF_PIN]))
|
for pin in gpio_input_pin_expression(config[CONF_PIN]):
|
||||||
gpio = variable(MakeGPIOBinarySensor, config[CONF_MAKE_ID], rhs)
|
yield
|
||||||
|
rhs = App.make_gpio_binary_sensor(config[CONF_NAME], pin)
|
||||||
|
gpio = variable(config[CONF_MAKE_ID], rhs)
|
||||||
binary_sensor.setup_binary_sensor(gpio.Pgpio, gpio.Pmqtt, config)
|
binary_sensor.setup_binary_sensor(gpio.Pgpio, gpio.Pmqtt, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
26
esphomeyaml/components/binary_sensor/nextion.py
Normal file
26
esphomeyaml/components/binary_sensor/nextion.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.display.nextion import Nextion
|
||||||
|
from esphomeyaml.const import CONF_COMPONENT_ID, CONF_NAME, CONF_PAGE_ID
|
||||||
|
from esphomeyaml.helpers import get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['display']
|
||||||
|
|
||||||
|
CONF_NEXTION_ID = 'nextion_id'
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_PAGE_ID): cv.uint8_t,
|
||||||
|
vol.Required(CONF_COMPONENT_ID): cv.uint8_t,
|
||||||
|
cv.GenerateID(CONF_NEXTION_ID): cv.use_variable_id(Nextion)
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_NEXTION_ID]):
|
||||||
|
yield
|
||||||
|
rhs = hub.make_touch_component(config[CONF_NAME], config[CONF_PAGE_ID],
|
||||||
|
config[CONF_COMPONENT_ID])
|
||||||
|
binary_sensor.register_binary_sensor(rhs, config)
|
||||||
42
esphomeyaml/components/binary_sensor/pn532.py
Normal file
42
esphomeyaml/components/binary_sensor/pn532.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.pn532 import PN532Component
|
||||||
|
from esphomeyaml.const import CONF_NAME, CONF_UID
|
||||||
|
from esphomeyaml.core import HexInt
|
||||||
|
from esphomeyaml.helpers import ArrayInitializer, get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['pn532']
|
||||||
|
|
||||||
|
CONF_PN532_ID = 'pn532_id'
|
||||||
|
|
||||||
|
|
||||||
|
def validate_uid(value):
|
||||||
|
value = cv.string_strict(value)
|
||||||
|
for x in value.split('-'):
|
||||||
|
if len(x) != 2:
|
||||||
|
raise vol.Invalid("Each part (separated by '-') of the UID must be two characters "
|
||||||
|
"long.")
|
||||||
|
try:
|
||||||
|
x = int(x, 16)
|
||||||
|
except ValueError:
|
||||||
|
raise vol.Invalid("Valid characters for parts of a UID are 0123456789ABCDEF.")
|
||||||
|
if x < 0 or x > 255:
|
||||||
|
raise vol.Invalid("Valid values for UID parts (separated by '-') are 00 to FF")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_UID): validate_uid,
|
||||||
|
cv.GenerateID(CONF_PN532_ID): cv.use_variable_id(PN532Component)
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_PN532_ID]):
|
||||||
|
yield
|
||||||
|
addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')]
|
||||||
|
rhs = hub.make_tag(config[CONF_NAME], ArrayInitializer(*addr, multiline=False))
|
||||||
|
binary_sensor.register_binary_sensor(rhs, config)
|
||||||
23
esphomeyaml/components/binary_sensor/rdm6300.py
Normal file
23
esphomeyaml/components/binary_sensor/rdm6300.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor, rdm6300
|
||||||
|
from esphomeyaml.const import CONF_NAME, CONF_UID
|
||||||
|
from esphomeyaml.helpers import get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['rdm6300']
|
||||||
|
|
||||||
|
CONF_RDM6300_ID = 'rdm6300_id'
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_UID): cv.uint32_t,
|
||||||
|
cv.GenerateID(CONF_RDM6300_ID): cv.use_variable_id(rdm6300.RDM6300Component)
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_RDM6300_ID]):
|
||||||
|
yield
|
||||||
|
rhs = hub.make_card(config[CONF_NAME], config[CONF_UID])
|
||||||
|
binary_sensor.register_binary_sensor(rhs, config)
|
||||||
114
esphomeyaml/components/binary_sensor/remote_receiver.py
Normal file
114
esphomeyaml/components/binary_sensor/remote_receiver.py
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.remote_receiver import RemoteReceiverComponent, remote_ns
|
||||||
|
from esphomeyaml.components.remote_transmitter import RC_SWITCH_RAW_SCHEMA, \
|
||||||
|
RC_SWITCH_TYPE_A_SCHEMA, RC_SWITCH_TYPE_B_SCHEMA, RC_SWITCH_TYPE_C_SCHEMA, \
|
||||||
|
RC_SWITCH_TYPE_D_SCHEMA, binary_code, build_rc_switch_protocol
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_CHANNEL, CONF_CODE, CONF_COMMAND, CONF_DATA, \
|
||||||
|
CONF_DEVICE, CONF_FAMILY, CONF_GROUP, CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, \
|
||||||
|
CONF_PANASONIC, CONF_PROTOCOL, CONF_RAW, CONF_RC_SWITCH_RAW, CONF_RC_SWITCH_TYPE_A, \
|
||||||
|
CONF_RC_SWITCH_TYPE_B, CONF_RC_SWITCH_TYPE_C, CONF_RC_SWITCH_TYPE_D, CONF_SONY, CONF_STATE
|
||||||
|
from esphomeyaml.helpers import ArrayInitializer, Pvariable, get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['remote_receiver']
|
||||||
|
|
||||||
|
REMOTE_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW, CONF_RC_SWITCH_RAW,
|
||||||
|
CONF_RC_SWITCH_TYPE_A, CONF_RC_SWITCH_TYPE_B, CONF_RC_SWITCH_TYPE_C,
|
||||||
|
CONF_RC_SWITCH_TYPE_D]
|
||||||
|
|
||||||
|
CONF_REMOTE_RECEIVER_ID = 'remote_receiver_id'
|
||||||
|
CONF_RECEIVER_ID = 'receiver_id'
|
||||||
|
|
||||||
|
RemoteReceiver = remote_ns.RemoteReceiver
|
||||||
|
LGReceiver = remote_ns.LGReceiver
|
||||||
|
NECReceiver = remote_ns.NECReceiver
|
||||||
|
PanasonicReceiver = remote_ns.PanasonicReceiver
|
||||||
|
RawReceiver = remote_ns.RawReceiver
|
||||||
|
SonyReceiver = remote_ns.SonyReceiver
|
||||||
|
RCSwitchRawReceiver = remote_ns.RCSwitchRawReceiver
|
||||||
|
RCSwitchTypeAReceiver = remote_ns.RCSwitchTypeAReceiver
|
||||||
|
RCSwitchTypeBReceiver = remote_ns.RCSwitchTypeBReceiver
|
||||||
|
RCSwitchTypeCReceiver = remote_ns.RCSwitchTypeCReceiver
|
||||||
|
RCSwitchTypeDReceiver = remote_ns.RCSwitchTypeDReceiver
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_LG): vol.Schema({
|
||||||
|
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||||
|
vol.Optional(CONF_NBITS, default=28): vol.All(vol.Coerce(int), cv.one_of(28, 32)),
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_NEC): vol.Schema({
|
||||||
|
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||||
|
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_SONY): vol.Schema({
|
||||||
|
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||||
|
vol.Optional(CONF_NBITS, default=12): vol.All(vol.Coerce(int), cv.one_of(12, 15, 20)),
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_PANASONIC): vol.Schema({
|
||||||
|
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||||
|
vol.Required(CONF_COMMAND): cv.hex_uint32_t,
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_RAW): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)],
|
||||||
|
vol.Optional(CONF_RC_SWITCH_RAW): RC_SWITCH_RAW_SCHEMA,
|
||||||
|
vol.Optional(CONF_RC_SWITCH_TYPE_A): RC_SWITCH_TYPE_A_SCHEMA,
|
||||||
|
vol.Optional(CONF_RC_SWITCH_TYPE_B): RC_SWITCH_TYPE_B_SCHEMA,
|
||||||
|
vol.Optional(CONF_RC_SWITCH_TYPE_C): RC_SWITCH_TYPE_C_SCHEMA,
|
||||||
|
vol.Optional(CONF_RC_SWITCH_TYPE_D): RC_SWITCH_TYPE_D_SCHEMA,
|
||||||
|
|
||||||
|
cv.GenerateID(CONF_REMOTE_RECEIVER_ID): cv.use_variable_id(RemoteReceiverComponent),
|
||||||
|
cv.GenerateID(CONF_RECEIVER_ID): cv.declare_variable_id(RemoteReceiver),
|
||||||
|
}), cv.has_exactly_one_key(*REMOTE_KEYS))
|
||||||
|
|
||||||
|
|
||||||
|
def receiver_base(full_config):
|
||||||
|
name = full_config[CONF_NAME]
|
||||||
|
key, config = next((k, v) for k, v in full_config.items() if k in REMOTE_KEYS)
|
||||||
|
if key == CONF_LG:
|
||||||
|
return LGReceiver.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||||
|
elif key == CONF_NEC:
|
||||||
|
return NECReceiver.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||||
|
elif key == CONF_PANASONIC:
|
||||||
|
return PanasonicReceiver.new(name, config[CONF_ADDRESS], config[CONF_COMMAND])
|
||||||
|
elif key == CONF_SONY:
|
||||||
|
return SonyReceiver.new(name, config[CONF_DATA], config[CONF_NBITS])
|
||||||
|
elif key == CONF_RAW:
|
||||||
|
data = ArrayInitializer(*config[CONF_RAW], multiline=False)
|
||||||
|
return RawReceiver.new(name, data)
|
||||||
|
elif key == CONF_RC_SWITCH_RAW:
|
||||||
|
return RCSwitchRawReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||||
|
binary_code(config[CONF_CODE]), len(config[CONF_CODE]))
|
||||||
|
elif key == CONF_RC_SWITCH_TYPE_A:
|
||||||
|
return RCSwitchTypeAReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||||
|
binary_code(config[CONF_GROUP]),
|
||||||
|
binary_code(config[CONF_DEVICE]),
|
||||||
|
config[CONF_STATE])
|
||||||
|
elif key == CONF_RC_SWITCH_TYPE_B:
|
||||||
|
return RCSwitchTypeBReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||||
|
config[CONF_ADDRESS], config[CONF_CHANNEL],
|
||||||
|
config[CONF_STATE])
|
||||||
|
elif key == CONF_RC_SWITCH_TYPE_C:
|
||||||
|
return RCSwitchTypeCReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||||
|
ord(config[CONF_FAMILY][0]) - ord('a'),
|
||||||
|
config[CONF_GROUP], config[CONF_DEVICE],
|
||||||
|
config[CONF_STATE])
|
||||||
|
elif key == CONF_RC_SWITCH_TYPE_D:
|
||||||
|
return RCSwitchTypeDReceiver.new(name, build_rc_switch_protocol(config[CONF_PROTOCOL]),
|
||||||
|
ord(config[CONF_GROUP][0]) - ord('a'),
|
||||||
|
config[CONF_DEVICE], config[CONF_STATE])
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Unknown receiver type {}".format(config))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
remote = None
|
||||||
|
for remote in get_variable(config[CONF_REMOTE_RECEIVER_ID]):
|
||||||
|
yield
|
||||||
|
rhs = receiver_base(config)
|
||||||
|
receiver = Pvariable(config[CONF_RECEIVER_ID], rhs)
|
||||||
|
|
||||||
|
binary_sensor.register_binary_sensor(remote.add_decoder(receiver), config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER'
|
||||||
@@ -5,16 +5,16 @@ from esphomeyaml.helpers import App, Application, variable
|
|||||||
|
|
||||||
DEPENDENCIES = ['mqtt']
|
DEPENDENCIES = ['mqtt']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('status_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
|
|
||||||
|
|
||||||
MakeStatusBinarySensor = Application.MakeStatusBinarySensor
|
MakeStatusBinarySensor = Application.MakeStatusBinarySensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeStatusBinarySensor),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_status_binary_sensor(config[CONF_NAME])
|
rhs = App.make_status_binary_sensor(config[CONF_NAME])
|
||||||
status = variable(MakeStatusBinarySensor, config[CONF_MAKE_ID], rhs)
|
status = variable(config[CONF_MAKE_ID], rhs)
|
||||||
binary_sensor.setup_binary_sensor(status.Pstatus, status.Pmqtt, config)
|
binary_sensor.setup_binary_sensor(status.Pstatus, status.Pmqtt, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,26 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import binary_sensor
|
from esphomeyaml.components import binary_sensor
|
||||||
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME
|
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME
|
||||||
from esphomeyaml.helpers import App, Application, process_lambda, variable
|
from esphomeyaml.helpers import App, Application, process_lambda, variable, optional, bool_, add
|
||||||
|
|
||||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('template_binary_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_LAMBDA): cv.lambda_,
|
|
||||||
}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema)
|
|
||||||
|
|
||||||
MakeTemplateBinarySensor = Application.MakeTemplateBinarySensor
|
MakeTemplateBinarySensor = Application.MakeTemplateBinarySensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateBinarySensor),
|
||||||
|
vol.Required(CONF_LAMBDA): cv.lambda_,
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
template_ = process_lambda(config[CONF_LAMBDA], [])
|
rhs = App.make_template_binary_sensor(config[CONF_NAME])
|
||||||
rhs = App.make_template_binary_sensor(config[CONF_NAME], template_)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
make = variable(MakeTemplateBinarySensor, config[CONF_MAKE_ID], rhs)
|
|
||||||
binary_sensor.setup_binary_sensor(make.Ptemplate_, make.Pmqtt, config)
|
binary_sensor.setup_binary_sensor(make.Ptemplate_, make.Pmqtt, config)
|
||||||
|
|
||||||
|
template_ = None
|
||||||
|
for template_ in process_lambda(config[CONF_LAMBDA], [],
|
||||||
|
return_type=optional.template(bool_)):
|
||||||
|
yield
|
||||||
|
add(make.Ptemplate_.set_template(template_))
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_TEMPLATE_BINARY_SENSOR'
|
BUILD_FLAGS = '-DUSE_TEMPLATE_BINARY_SENSOR'
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID
|
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_INTERNAL
|
||||||
from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component
|
from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component, add
|
||||||
|
|
||||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
|
||||||
cv.GenerateID('cover'): cv.register_variable_id,
|
|
||||||
cv.GenerateID('mqtt_cover', CONF_MQTT_ID): cv.register_variable_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
cover_ns = esphomelib_ns.namespace('cover')
|
cover_ns = esphomelib_ns.namespace('cover')
|
||||||
Cover = cover_ns.Cover
|
Cover = cover_ns.Cover
|
||||||
MQTTCoverComponent = cover_ns.MQTTCoverComponent
|
MQTTCoverComponent = cover_ns.MQTTCoverComponent
|
||||||
@@ -21,15 +16,23 @@ OpenAction = cover_ns.OpenAction
|
|||||||
CloseAction = cover_ns.CloseAction
|
CloseAction = cover_ns.CloseAction
|
||||||
StopAction = cover_ns.StopAction
|
StopAction = cover_ns.StopAction
|
||||||
|
|
||||||
|
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(Cover),
|
||||||
|
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTCoverComponent),
|
||||||
|
})
|
||||||
|
|
||||||
|
COVER_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(COVER_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
def setup_cover_core_(cover_var, mqtt_var, config):
|
def setup_cover_core_(cover_var, mqtt_var, config):
|
||||||
|
if CONF_INTERNAL in config:
|
||||||
|
add(cover_var.set_internal(config[CONF_INTERNAL]))
|
||||||
setup_mqtt_component(mqtt_var, config)
|
setup_mqtt_component(mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
def setup_cover(cover_obj, mqtt_obj, config):
|
def setup_cover(cover_obj, mqtt_obj, config):
|
||||||
cover_var = Pvariable(Cover, config[CONF_ID], cover_obj, has_side_effects=False)
|
cover_var = Pvariable(config[CONF_ID], cover_obj, has_side_effects=False)
|
||||||
mqtt_var = Pvariable(MQTTCoverComponent, config[CONF_MQTT_ID], mqtt_obj,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||||
has_side_effects=False)
|
|
||||||
setup_cover_core_(cover_var, mqtt_var, config)
|
setup_cover_core_(cover_var, mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,40 +5,43 @@ from esphomeyaml import automation
|
|||||||
from esphomeyaml.components import cover
|
from esphomeyaml.components import cover
|
||||||
from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \
|
from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \
|
||||||
CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC
|
CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC
|
||||||
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable
|
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable, optional
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.All(cover.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('template_cover', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
|
||||||
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
|
||||||
vol.Optional(CONF_OPEN_ACTION): automation.ACTIONS_SCHEMA,
|
|
||||||
vol.Optional(CONF_CLOSE_ACTION): automation.ACTIONS_SCHEMA,
|
|
||||||
vol.Optional(CONF_STOP_ACTION): automation.ACTIONS_SCHEMA,
|
|
||||||
}).extend(cover.COVER_SCHEMA.schema), cv.has_at_exactly_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
|
|
||||||
|
|
||||||
MakeTemplateCover = Application.MakeTemplateCover
|
MakeTemplateCover = Application.MakeTemplateCover
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(cover.COVER_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateCover),
|
||||||
|
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||||
|
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
||||||
|
vol.Optional(CONF_OPEN_ACTION): automation.validate_automation(),
|
||||||
|
vol.Optional(CONF_CLOSE_ACTION): automation.validate_automation(),
|
||||||
|
vol.Optional(CONF_STOP_ACTION): automation.validate_automation(),
|
||||||
|
}), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_template_cover(config[CONF_NAME])
|
rhs = App.make_template_cover(config[CONF_NAME])
|
||||||
make = variable(MakeTemplateCover, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
|
||||||
if CONF_LAMBDA in config:
|
|
||||||
template_ = process_lambda(config[CONF_LAMBDA], [])
|
|
||||||
add(make.Ptemplate.set_state_lambda(template_))
|
|
||||||
if CONF_OPEN_ACTION in config:
|
|
||||||
actions = automation.build_actions(config[CONF_OPEN_ACTION], NoArg)
|
|
||||||
add(make.Ptemplate_.add_open_actions(actions))
|
|
||||||
if CONF_CLOSE_ACTION in config:
|
|
||||||
actions = automation.build_actions(config[CONF_CLOSE_ACTION], NoArg)
|
|
||||||
add(make.Ptemplate_.add_close_actions(actions))
|
|
||||||
if CONF_STOP_ACTION in config:
|
|
||||||
actions = automation.build_actions(config[CONF_STOP_ACTION], NoArg)
|
|
||||||
add(make.Ptemplate_.add_stop_actions(actions))
|
|
||||||
if CONF_OPTIMISTIC in config:
|
|
||||||
add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC]))
|
|
||||||
|
|
||||||
cover.setup_cover(make.Ptemplate_, make.Pmqtt, config)
|
cover.setup_cover(make.Ptemplate_, make.Pmqtt, config)
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
template_ = None
|
||||||
|
for template_ in process_lambda(config[CONF_LAMBDA], [],
|
||||||
|
return_type=optional.template(cover.CoverState)):
|
||||||
|
yield
|
||||||
|
add(make.Ptemplate_.set_state_lambda(template_))
|
||||||
|
if CONF_OPEN_ACTION in config:
|
||||||
|
automation.build_automation(make.Ptemplate_.get_open_trigger(), NoArg,
|
||||||
|
config[CONF_OPEN_ACTION])
|
||||||
|
if CONF_CLOSE_ACTION in config:
|
||||||
|
automation.build_automation(make.Ptemplate_.get_close_trigger(), NoArg,
|
||||||
|
config[CONF_CLOSE_ACTION])
|
||||||
|
if CONF_STOP_ACTION in config:
|
||||||
|
automation.build_automation(make.Ptemplate_.get_stop_trigger(), NoArg,
|
||||||
|
config[CONF_STOP_ACTION])
|
||||||
|
if CONF_OPTIMISTIC in config:
|
||||||
|
add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC]))
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_TEMPLATE_COVER'
|
BUILD_FLAGS = '-DUSE_TEMPLATE_COVER'
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ from esphomeyaml.helpers import App, Pvariable
|
|||||||
DallasComponent = sensor.sensor_ns.DallasComponent
|
DallasComponent = sensor.sensor_ns.DallasComponent
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
||||||
cv.GenerateID('dallas'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(DallasComponent),
|
||||||
vol.Required(CONF_PIN): pins.input_output_pin,
|
vol.Required(CONF_PIN): pins.input_output_pin,
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
})])
|
})])
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
for conf in config:
|
for conf in config:
|
||||||
rhs = App.make_dallas_component(conf[CONF_PIN], conf.get(CONF_UPDATE_INTERVAL))
|
rhs = App.make_dallas_component(conf[CONF_PIN], conf.get(CONF_UPDATE_INTERVAL))
|
||||||
Pvariable(DallasComponent, conf[CONF_ID], rhs)
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'
|
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'
|
||||||
|
|||||||
@@ -14,26 +14,42 @@ def validate_pin_number(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
DeepSleepComponent = esphomelib_ns.DeepSleepComponent
|
||||||
|
EnterDeepSleepAction = esphomelib_ns.EnterDeepSleepAction
|
||||||
|
PreventDeepSleepAction = esphomelib_ns.PreventDeepSleepAction
|
||||||
|
|
||||||
|
WAKEUP_PIN_MODES = {
|
||||||
|
'IGNORE': esphomelib_ns.WAKEUP_PIN_MODE_IGNORE,
|
||||||
|
'KEEP_AWAKE': esphomelib_ns.WAKEUP_PIN_MODE_KEEP_AWAKE,
|
||||||
|
'INVERT_WAKEUP': esphomelib_ns.WAKEUP_PIN_MODE_INVERT_WAKEUP,
|
||||||
|
}
|
||||||
|
|
||||||
|
CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('deep_sleep'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent),
|
||||||
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.GPIO_INTERNAL_INPUT_PIN_SCHEMA,
|
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
|
||||||
validate_pin_number),
|
validate_pin_number),
|
||||||
|
vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32, vol.Upper,
|
||||||
|
cv.one_of(*WAKEUP_PIN_MODES)),
|
||||||
vol.Optional(CONF_RUN_CYCLES): cv.positive_int,
|
vol.Optional(CONF_RUN_CYCLES): cv.positive_int,
|
||||||
vol.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
|
||||||
})
|
})
|
||||||
|
|
||||||
DeepSleepComponent = esphomelib_ns.DeepSleepComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_deep_sleep_component()
|
rhs = App.make_deep_sleep_component()
|
||||||
deep_sleep = Pvariable(DeepSleepComponent, config[CONF_ID], rhs)
|
deep_sleep = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_SLEEP_DURATION in config:
|
if CONF_SLEEP_DURATION in config:
|
||||||
add(deep_sleep.set_sleep_duration(config[CONF_SLEEP_DURATION]))
|
add(deep_sleep.set_sleep_duration(config[CONF_SLEEP_DURATION]))
|
||||||
if CONF_WAKEUP_PIN in config:
|
if CONF_WAKEUP_PIN in config:
|
||||||
pin = gpio_input_pin_expression(config[CONF_WAKEUP_PIN])
|
pin = None
|
||||||
|
for pin in gpio_input_pin_expression(config[CONF_WAKEUP_PIN]):
|
||||||
|
yield
|
||||||
add(deep_sleep.set_wakeup_pin(pin))
|
add(deep_sleep.set_wakeup_pin(pin))
|
||||||
|
if CONF_WAKEUP_PIN_MODE in config:
|
||||||
|
add(deep_sleep.set_wakeup_pin_mode(WAKEUP_PIN_MODES[config[CONF_WAKEUP_PIN_MODE]]))
|
||||||
if CONF_RUN_CYCLES in config:
|
if CONF_RUN_CYCLES in config:
|
||||||
add(deep_sleep.set_run_cycles(config[CONF_RUN_CYCLES]))
|
add(deep_sleep.set_run_cycles(config[CONF_RUN_CYCLES]))
|
||||||
if CONF_RUN_DURATION in config:
|
if CONF_RUN_DURATION in config:
|
||||||
|
|||||||
56
esphomeyaml/components/display/__init__.py
Normal file
56
esphomeyaml/components/display/__init__.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.const import CONF_LAMBDA, CONF_ROTATION, CONF_UPDATE_INTERVAL
|
||||||
|
from esphomeyaml.helpers import add, add_job, esphomelib_ns
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
display_ns = esphomelib_ns.namespace('display')
|
||||||
|
DisplayBuffer = display_ns.DisplayBuffer
|
||||||
|
DisplayBufferRef = DisplayBuffer.operator('ref')
|
||||||
|
|
||||||
|
DISPLAY_ROTATIONS = {
|
||||||
|
0: display_ns.DISPLAY_ROTATION_0_DEGREES,
|
||||||
|
90: display_ns.DISPLAY_ROTATION_90_DEGREES,
|
||||||
|
180: display_ns.DISPLAY_ROTATION_180_DEGREES,
|
||||||
|
270: display_ns.DISPLAY_ROTATION_270_DEGREES,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_rotation(value):
|
||||||
|
value = cv.string(value)
|
||||||
|
if value.endswith(u"°"):
|
||||||
|
value = value[:-1]
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
raise vol.Invalid(u"Expected integer for rotation")
|
||||||
|
return cv.one_of(*DISPLAY_ROTATIONS)(value)
|
||||||
|
|
||||||
|
|
||||||
|
BASIC_DISPLAY_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||||
|
})
|
||||||
|
|
||||||
|
FULL_DISPLAY_PLATFORM_SCHEMA = BASIC_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_ROTATION): validate_rotation,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def setup_display_core_(display_var, config):
|
||||||
|
if CONF_UPDATE_INTERVAL in config:
|
||||||
|
add(display_var.set_update_interval(config[CONF_UPDATE_INTERVAL]))
|
||||||
|
if CONF_ROTATION in config:
|
||||||
|
add(display_var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]]))
|
||||||
|
|
||||||
|
|
||||||
|
def setup_display(display_var, config):
|
||||||
|
add_job(setup_display_core_, display_var, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_DISPLAY'
|
||||||
72
esphomeyaml/components/display/lcd_gpio.py
Normal file
72
esphomeyaml/components/display/lcd_gpio.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.const import CONF_DATA_PINS, CONF_DIMENSIONS, CONF_ENABLE_PIN, CONF_ID, \
|
||||||
|
CONF_LAMBDA, CONF_RS_PIN, CONF_RW_PIN
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, gpio_output_pin_expression, process_lambda
|
||||||
|
|
||||||
|
GPIOLCDDisplay = display.display_ns.GPIOLCDDisplay
|
||||||
|
LCDDisplay = display.display_ns.LCDDisplay
|
||||||
|
LCDDisplayRef = LCDDisplay.operator('ref')
|
||||||
|
|
||||||
|
|
||||||
|
def validate_lcd_dimensions(value):
|
||||||
|
value = cv.dimensions(value)
|
||||||
|
if value[0] > 0x40:
|
||||||
|
raise vol.Invalid("LCD displays can't have more than 64 columns")
|
||||||
|
if value[1] > 4:
|
||||||
|
raise vol.Invalid("LCD displays can't have more than 4 rows")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def validate_pin_length(value):
|
||||||
|
if len(value) != 4 and len(value) != 8:
|
||||||
|
raise vol.Invalid("LCD Displays can either operate in 4-pin or 8-pin mode,"
|
||||||
|
"not {}-pin mode".format(len(value)))
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.BASIC_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(GPIOLCDDisplay),
|
||||||
|
vol.Required(CONF_DIMENSIONS): validate_lcd_dimensions,
|
||||||
|
|
||||||
|
vol.Required(CONF_DATA_PINS): vol.All([pins.gpio_output_pin_schema], validate_pin_length),
|
||||||
|
vol.Required(CONF_ENABLE_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_RS_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Optional(CONF_RW_PIN): pins.gpio_output_pin_schema,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_gpio_lcd_display(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1])
|
||||||
|
lcd = Pvariable(config[CONF_ID], rhs)
|
||||||
|
pins_ = []
|
||||||
|
for conf in config[CONF_DATA_PINS]:
|
||||||
|
for pin in gpio_output_pin_expression(conf):
|
||||||
|
yield
|
||||||
|
pins_.append(pin)
|
||||||
|
add(lcd.set_data_pins(*pins_))
|
||||||
|
for enable in gpio_output_pin_expression(config[CONF_ENABLE_PIN]):
|
||||||
|
yield
|
||||||
|
add(lcd.set_enable_pin(enable))
|
||||||
|
|
||||||
|
for rs in gpio_output_pin_expression(config[CONF_RS_PIN]):
|
||||||
|
yield
|
||||||
|
add(lcd.set_rs_pin(rs))
|
||||||
|
|
||||||
|
if CONF_RW_PIN in config:
|
||||||
|
for rw in gpio_output_pin_expression(config[CONF_RW_PIN]):
|
||||||
|
yield
|
||||||
|
add(lcd.set_rw_pin(rw))
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(LCDDisplayRef, 'it')]):
|
||||||
|
yield
|
||||||
|
add(lcd.set_writer(lambda_))
|
||||||
|
|
||||||
|
display.setup_display(lcd, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_LCD_DISPLAY'
|
||||||
35
esphomeyaml/components/display/lcd_pcf8574.py
Normal file
35
esphomeyaml/components/display/lcd_pcf8574.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.display.lcd_gpio import LCDDisplayRef, validate_lcd_dimensions
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_DIMENSIONS, CONF_ID, CONF_LAMBDA
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, process_lambda
|
||||||
|
|
||||||
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
PCF8574LCDDisplay = display.display_ns.PCF8574LCDDisplay
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.BASIC_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(PCF8574LCDDisplay),
|
||||||
|
vol.Required(CONF_DIMENSIONS): validate_lcd_dimensions,
|
||||||
|
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_pcf8574_lcd_display(config[CONF_DIMENSIONS][0], config[CONF_DIMENSIONS][1])
|
||||||
|
lcd = Pvariable(config[CONF_ID], rhs)
|
||||||
|
|
||||||
|
if CONF_ADDRESS in config:
|
||||||
|
add(lcd.set_address(config[CONF_ADDRESS]))
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(LCDDisplayRef, 'it')]):
|
||||||
|
yield
|
||||||
|
add(lcd.set_writer(lambda_))
|
||||||
|
|
||||||
|
display.setup_display(lcd, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = ['-DUSE_LCD_DISPLAY', '-DUSE_LCD_DISPLAY_PCF8574']
|
||||||
48
esphomeyaml/components/display/max7219.py
Normal file
48
esphomeyaml/components/display/max7219.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.spi import SPIComponent
|
||||||
|
from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_INTENSITY, CONF_LAMBDA, CONF_NUM_CHIPS, \
|
||||||
|
CONF_SPI_ID
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, get_variable, gpio_output_pin_expression, \
|
||||||
|
process_lambda
|
||||||
|
|
||||||
|
DEPENDENCIES = ['spi']
|
||||||
|
|
||||||
|
MAX7219Component = display.display_ns.MAX7219Component
|
||||||
|
MAX7219ComponentRef = MAX7219Component.operator('ref')
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.BASIC_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(MAX7219Component),
|
||||||
|
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
|
||||||
|
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
|
||||||
|
|
||||||
|
vol.Optional(CONF_NUM_CHIPS): vol.All(cv.uint8_t, vol.Range(min=1)),
|
||||||
|
vol.Optional(CONF_INTENSITY): vol.All(cv.uint8_t, vol.Range(min=0, max=15)),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for spi in get_variable(config[CONF_SPI_ID]):
|
||||||
|
yield
|
||||||
|
for cs in gpio_output_pin_expression(config[CONF_CS_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_max7219(spi, cs)
|
||||||
|
max7219 = Pvariable(config[CONF_ID], rhs)
|
||||||
|
|
||||||
|
if CONF_NUM_CHIPS in config:
|
||||||
|
add(max7219.set_num_chips(config[CONF_NUM_CHIPS]))
|
||||||
|
if CONF_INTENSITY in config:
|
||||||
|
add(max7219.set_intensity(config[CONF_INTENSITY]))
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(MAX7219ComponentRef, 'it')]):
|
||||||
|
yield
|
||||||
|
add(max7219.set_writer(lambda_))
|
||||||
|
|
||||||
|
display.setup_display(max7219, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_MAX7219'
|
||||||
32
esphomeyaml/components/display/nextion.py
Normal file
32
esphomeyaml/components/display/nextion.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.uart import UARTComponent
|
||||||
|
from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_UART_ID
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, get_variable, process_lambda
|
||||||
|
|
||||||
|
DEPENDENCIES = ['uart']
|
||||||
|
|
||||||
|
Nextion = display.display_ns.Nextion
|
||||||
|
NextionRef = Nextion.operator('ref')
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.BASIC_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(Nextion),
|
||||||
|
cv.GenerateID(CONF_UART_ID): cv.use_variable_id(UARTComponent),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for uart in get_variable(config[CONF_UART_ID]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_nextion(uart)
|
||||||
|
nextion = Pvariable(config[CONF_ID], rhs)
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(NextionRef, 'it')]):
|
||||||
|
yield
|
||||||
|
add(nextion.set_writer(lambda_))
|
||||||
|
|
||||||
|
display.setup_display(nextion, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_NEXTION'
|
||||||
39
esphomeyaml/components/display/ssd1306_i2c.py
Normal file
39
esphomeyaml/components/display/ssd1306_i2c.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.display import ssd1306_spi
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_EXTERNAL_VCC, CONF_ID, CONF_MODEL, CONF_RESET_PIN
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, gpio_output_pin_expression
|
||||||
|
|
||||||
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
I2CSSD1306 = display.display_ns.I2CSSD1306
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(I2CSSD1306),
|
||||||
|
vol.Required(CONF_MODEL): ssd1306_spi.SSD1306_MODEL,
|
||||||
|
vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Optional(CONF_EXTERNAL_VCC): cv.boolean,
|
||||||
|
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
ssd = Pvariable(config[CONF_ID], App.make_i2c_ssd1306())
|
||||||
|
add(ssd.set_model(ssd1306_spi.MODELS[config[CONF_MODEL]]))
|
||||||
|
|
||||||
|
if CONF_RESET_PIN in config:
|
||||||
|
for reset in gpio_output_pin_expression(config[CONF_RESET_PIN]):
|
||||||
|
yield
|
||||||
|
add(ssd.set_reset_pin(reset))
|
||||||
|
if CONF_EXTERNAL_VCC in config:
|
||||||
|
add(ssd.set_external_vcc(config[CONF_EXTERNAL_VCC]))
|
||||||
|
if CONF_ADDRESS in config:
|
||||||
|
add(ssd.set_address(config[CONF_ADDRESS]))
|
||||||
|
|
||||||
|
display.setup_display(ssd, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_SSD1306'
|
||||||
59
esphomeyaml/components/display/ssd1306_spi.py
Normal file
59
esphomeyaml/components/display/ssd1306_spi.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.spi import SPIComponent
|
||||||
|
from esphomeyaml.const import CONF_CS_PIN, CONF_DC_PIN, CONF_EXTERNAL_VCC, CONF_ID, CONF_MODEL, \
|
||||||
|
CONF_RESET_PIN, CONF_SPI_ID
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, get_variable, gpio_output_pin_expression
|
||||||
|
|
||||||
|
DEPENDENCIES = ['spi']
|
||||||
|
|
||||||
|
SPISSD1306 = display.display_ns.SPISSD1306
|
||||||
|
|
||||||
|
MODELS = {
|
||||||
|
'SSD1306_128X32': display.display_ns.SSD1306_MODEL_128_32,
|
||||||
|
'SSD1306_128X64': display.display_ns.SSD1306_MODEL_128_64,
|
||||||
|
'SSD1306_96X16': display.display_ns.SSD1306_MODEL_96_16,
|
||||||
|
'SH1106_128X32': display.display_ns.SH1106_MODEL_128_32,
|
||||||
|
'SH1106_128X64': display.display_ns.SH1106_MODEL_128_64,
|
||||||
|
'SH1106_96X16': display.display_ns.SH1106_MODEL_96_16,
|
||||||
|
}
|
||||||
|
|
||||||
|
SSD1306_MODEL = vol.All(vol.Upper, vol.Replace(' ', '_'), cv.one_of(*MODELS))
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(SPISSD1306),
|
||||||
|
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
|
||||||
|
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_DC_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_MODEL): SSD1306_MODEL,
|
||||||
|
vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Optional(CONF_EXTERNAL_VCC): cv.boolean,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for spi in get_variable(config[CONF_SPI_ID]):
|
||||||
|
yield
|
||||||
|
for cs in gpio_output_pin_expression(config[CONF_CS_PIN]):
|
||||||
|
yield
|
||||||
|
for dc in gpio_output_pin_expression(config[CONF_DC_PIN]):
|
||||||
|
yield
|
||||||
|
|
||||||
|
rhs = App.make_spi_ssd1306(spi, cs, dc)
|
||||||
|
ssd = Pvariable(config[CONF_ID], rhs)
|
||||||
|
add(ssd.set_model(MODELS[config[CONF_MODEL]]))
|
||||||
|
|
||||||
|
if CONF_RESET_PIN in config:
|
||||||
|
for reset in gpio_output_pin_expression(config[CONF_RESET_PIN]):
|
||||||
|
yield
|
||||||
|
add(ssd.set_reset_pin(reset))
|
||||||
|
if CONF_EXTERNAL_VCC in config:
|
||||||
|
add(ssd.set_external_vcc(config[CONF_EXTERNAL_VCC]))
|
||||||
|
|
||||||
|
display.setup_display(ssd, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_SSD1306'
|
||||||
84
esphomeyaml/components/display/waveshare_epaper.py
Normal file
84
esphomeyaml/components/display/waveshare_epaper.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.components.spi import SPIComponent
|
||||||
|
from esphomeyaml.const import CONF_BUSY_PIN, CONF_CS_PIN, CONF_DC_PIN, CONF_FULL_UPDATE_EVERY, \
|
||||||
|
CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, get_variable, gpio_input_pin_expression, \
|
||||||
|
gpio_output_pin_expression, process_lambda
|
||||||
|
|
||||||
|
DEPENDENCIES = ['spi']
|
||||||
|
|
||||||
|
WaveshareEPaperTypeA = display.display_ns.WaveshareEPaperTypeA
|
||||||
|
WaveshareEPaper = display.display_ns.WaveshareEPaper
|
||||||
|
|
||||||
|
MODELS = {
|
||||||
|
'1.54in': ('a', display.display_ns.WAVESHARE_EPAPER_1_54_IN),
|
||||||
|
'2.13in': ('a', display.display_ns.WAVESHARE_EPAPER_2_13_IN),
|
||||||
|
'2.90in': ('a', display.display_ns.WAVESHARE_EPAPER_2_9_IN),
|
||||||
|
'2.70in': ('b', display.display_ns.WAVESHARE_EPAPER_2_7_IN),
|
||||||
|
'4.20in': ('b', display.display_ns.WAVESHARE_EPAPER_4_2_IN),
|
||||||
|
'7.50in': ('b', display.display_ns.WAVESHARE_EPAPER_7_5_IN),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_full_update_every_only_type_a(value):
|
||||||
|
if CONF_FULL_UPDATE_EVERY not in value:
|
||||||
|
return value
|
||||||
|
if MODELS[value[CONF_MODEL]][0] != 'a':
|
||||||
|
raise vol.Invalid("The 'full_update_every' option is only available for models "
|
||||||
|
"'1.54in', '2.13in' and '2.90in'.")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.All(display.FULL_DISPLAY_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(None),
|
||||||
|
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
|
||||||
|
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_DC_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_MODEL): vol.All(vol.Lower, cv.one_of(*MODELS)),
|
||||||
|
vol.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema,
|
||||||
|
vol.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t,
|
||||||
|
}), validate_full_update_every_only_type_a)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for spi in get_variable(config[CONF_SPI_ID]):
|
||||||
|
yield
|
||||||
|
for cs in gpio_output_pin_expression(config[CONF_CS_PIN]):
|
||||||
|
yield
|
||||||
|
for dc in gpio_output_pin_expression(config[CONF_DC_PIN]):
|
||||||
|
yield
|
||||||
|
|
||||||
|
model_type, model = MODELS[config[CONF_MODEL]]
|
||||||
|
if model_type == 'a':
|
||||||
|
rhs = App.make_waveshare_epaper_type_a(spi, cs, dc, model)
|
||||||
|
epaper = Pvariable(config[CONF_ID], rhs, type=WaveshareEPaperTypeA)
|
||||||
|
elif model_type == 'b':
|
||||||
|
rhs = App.make_waveshare_epaper_type_b(spi, cs, dc, model)
|
||||||
|
epaper = Pvariable(config[CONF_ID], rhs, type=WaveshareEPaper)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
if CONF_LAMBDA in config:
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')]):
|
||||||
|
yield
|
||||||
|
add(epaper.set_writer(lambda_))
|
||||||
|
if CONF_RESET_PIN in config:
|
||||||
|
for reset in gpio_output_pin_expression(config[CONF_RESET_PIN]):
|
||||||
|
yield
|
||||||
|
add(epaper.set_reset_pin(reset))
|
||||||
|
if CONF_BUSY_PIN in config:
|
||||||
|
for reset in gpio_input_pin_expression(config[CONF_BUSY_PIN]):
|
||||||
|
yield
|
||||||
|
add(epaper.set_busy_pin(reset))
|
||||||
|
if CONF_FULL_UPDATE_EVERY in config:
|
||||||
|
add(epaper.set_full_update_every(config[CONF_FULL_UPDATE_EVERY]))
|
||||||
|
|
||||||
|
display.setup_display(epaper, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_WAVESHARE_EPAPER'
|
||||||
@@ -1,24 +1,5 @@
|
|||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from esphomeyaml import config_validation as cv
|
from esphomeyaml import config_validation as cv
|
||||||
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
|
|
||||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns
|
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
CONFIG_SCHEMA = cv.invalid("The 'esp32_ble' component has been renamed to the 'esp32_ble_tracker' "
|
||||||
|
"component in order to avoid confusion with the new 'esp32_ble_beacon' "
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
"component.")
|
||||||
cv.GenerateID('esp32_ble'): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
ESP32BLETracker = esphomelib_ns.ESP32BLETracker
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
|
||||||
rhs = App.make_esp32_ble_tracker()
|
|
||||||
ble = Pvariable(ESP32BLETracker, config[CONF_ID], rhs)
|
|
||||||
if CONF_SCAN_INTERVAL in config:
|
|
||||||
add(ble.set_scan_interval(config[CONF_SCAN_INTERVAL]))
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
|
|
||||||
|
|||||||
35
esphomeyaml/components/esp32_ble_beacon.py
Normal file
35
esphomeyaml/components/esp32_ble_beacon.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from esphomeyaml import config_validation as cv
|
||||||
|
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32, CONF_UUID, CONF_TYPE
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, RawExpression, ArrayInitializer
|
||||||
|
|
||||||
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
|
|
||||||
|
ESP32BLEBeacon = esphomelib_ns.ESP32BLEBeacon
|
||||||
|
|
||||||
|
CONF_MAJOR = 'major'
|
||||||
|
CONF_MINOR = 'minor'
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(ESP32BLEBeacon),
|
||||||
|
vol.Required(CONF_TYPE): vol.All(vol.Upper, cv.one_of('IBEACON')),
|
||||||
|
vol.Required(CONF_UUID): cv.uuid,
|
||||||
|
vol.Optional(CONF_MAJOR): cv.uint16_t,
|
||||||
|
vol.Optional(CONF_MINOR): cv.uint16_t,
|
||||||
|
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
uuid = config[CONF_UUID].hex
|
||||||
|
uuid_arr = [RawExpression('0x{}'.format(uuid[i:i+2])) for i in range(0, len(uuid), 2)]
|
||||||
|
rhs = App.make_esp32_ble_beacon(ArrayInitializer(*uuid_arr, multiline=False))
|
||||||
|
ble = Pvariable(config[CONF_ID], rhs)
|
||||||
|
if CONF_MAJOR in config:
|
||||||
|
add(ble.set_major(config[CONF_MAJOR]))
|
||||||
|
if CONF_MINOR in config:
|
||||||
|
add(ble.set_minor(config[CONF_MINOR]))
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_ESP32_BLE_BEACON'
|
||||||
31
esphomeyaml/components/esp32_ble_tracker.py
Normal file
31
esphomeyaml/components/esp32_ble_tracker.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from esphomeyaml import config_validation as cv
|
||||||
|
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
|
||||||
|
from esphomeyaml.core import HexInt
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, ArrayInitializer
|
||||||
|
|
||||||
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
|
|
||||||
|
CONF_ESP32_BLE_ID = 'esp32_ble_id'
|
||||||
|
ESP32BLETracker = esphomelib_ns.ESP32BLETracker
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker),
|
||||||
|
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def make_address_array(address):
|
||||||
|
addr = [HexInt(i) for i in address.parts]
|
||||||
|
return ArrayInitializer(*addr, multiline=False)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_esp32_ble_tracker()
|
||||||
|
ble = Pvariable(config[CONF_ID], rhs)
|
||||||
|
if CONF_SCAN_INTERVAL in config:
|
||||||
|
add(ble.set_scan_interval(config[CONF_SCAN_INTERVAL]))
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
|
||||||
@@ -41,8 +41,10 @@ VOLTAGE_ATTENUATION = {
|
|||||||
'0V': global_ns.TOUCH_HVOLT_ATTEN_0V,
|
'0V': global_ns.TOUCH_HVOLT_ATTEN_0V,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESP32TouchComponent = binary_sensor.binary_sensor_ns.ESP32TouchComponent
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('esp32_ble'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent),
|
||||||
vol.Optional(CONF_SETUP_MODE): cv.boolean,
|
vol.Optional(CONF_SETUP_MODE): cv.boolean,
|
||||||
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_SLEEP_DURATION):
|
vol.Optional(CONF_SLEEP_DURATION):
|
||||||
@@ -54,18 +56,16 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
vol.Optional(CONF_VOLTAGE_ATTENUATION): validate_voltage(VOLTAGE_ATTENUATION),
|
vol.Optional(CONF_VOLTAGE_ATTENUATION): validate_voltage(VOLTAGE_ATTENUATION),
|
||||||
})
|
})
|
||||||
|
|
||||||
ESP32TouchComponent = binary_sensor.binary_sensor_ns.ESP32TouchComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_esp32_touch_component()
|
rhs = App.make_esp32_touch_component()
|
||||||
touch = Pvariable(ESP32TouchComponent, config[CONF_ID], rhs)
|
touch = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_SETUP_MODE in config:
|
if CONF_SETUP_MODE in config:
|
||||||
add(touch.set_setup_mode(config[CONF_SETUP_MODE]))
|
add(touch.set_setup_mode(config[CONF_SETUP_MODE]))
|
||||||
if CONF_IIR_FILTER in config:
|
if CONF_IIR_FILTER in config:
|
||||||
add(touch.set_iir_filter(config[CONF_IIR_FILTER]))
|
add(touch.set_iir_filter(config[CONF_IIR_FILTER]))
|
||||||
if CONF_SLEEP_DURATION in config:
|
if CONF_SLEEP_DURATION in config:
|
||||||
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 6.6667)
|
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 0.15)
|
||||||
add(touch.set_sleep_duration(sleep_duration))
|
add(touch.set_sleep_duration(sleep_duration))
|
||||||
if CONF_MEASUREMENT_DURATION in config:
|
if CONF_MEASUREMENT_DURATION in config:
|
||||||
measurement_duration = int(config[CONF_MEASUREMENT_DURATION].total_microseconds * 0.125)
|
measurement_duration = int(config[CONF_MEASUREMENT_DURATION].total_microseconds * 0.125)
|
||||||
|
|||||||
@@ -2,20 +2,13 @@ import voluptuous as vol
|
|||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_OSCILLATION_COMMAND_TOPIC, \
|
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_OSCILLATION_COMMAND_TOPIC, \
|
||||||
CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
|
CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_INTERNAL
|
||||||
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
||||||
|
|
||||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
|
||||||
cv.GenerateID('fan'): cv.register_variable_id,
|
|
||||||
cv.GenerateID('mqtt_fan', CONF_MQTT_ID): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.publish_topic,
|
|
||||||
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic,
|
|
||||||
})
|
|
||||||
|
|
||||||
fan_ns = esphomelib_ns.namespace('fan')
|
fan_ns = esphomelib_ns.namespace('fan')
|
||||||
FanState = fan_ns.FanState
|
FanState = fan_ns.FanState
|
||||||
MQTTFanComponent = fan_ns.MQTTFanComponent
|
MQTTFanComponent = fan_ns.MQTTFanComponent
|
||||||
@@ -29,6 +22,15 @@ FAN_SPEED_LOW = fan_ns.FAN_SPEED_LOW
|
|||||||
FAN_SPEED_MEDIUM = fan_ns.FAN_SPEED_MEDIUM
|
FAN_SPEED_MEDIUM = fan_ns.FAN_SPEED_MEDIUM
|
||||||
FAN_SPEED_HIGH = fan_ns.FAN_SPEED_HIGH
|
FAN_SPEED_HIGH = fan_ns.FAN_SPEED_HIGH
|
||||||
|
|
||||||
|
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(FanState),
|
||||||
|
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTFanComponent),
|
||||||
|
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.publish_topic,
|
||||||
|
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic,
|
||||||
|
})
|
||||||
|
|
||||||
|
FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
FAN_SPEEDS = {
|
FAN_SPEEDS = {
|
||||||
'OFF': FAN_SPEED_OFF,
|
'OFF': FAN_SPEED_OFF,
|
||||||
@@ -43,6 +45,9 @@ def validate_fan_speed(value):
|
|||||||
|
|
||||||
|
|
||||||
def setup_fan_core_(fan_var, mqtt_var, config):
|
def setup_fan_core_(fan_var, mqtt_var, config):
|
||||||
|
if CONF_INTERNAL in config:
|
||||||
|
add(fan_var.set_internal(config[CONF_INTERNAL]))
|
||||||
|
|
||||||
if CONF_OSCILLATION_STATE_TOPIC in config:
|
if CONF_OSCILLATION_STATE_TOPIC in config:
|
||||||
add(mqtt_var.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC]))
|
add(mqtt_var.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC]))
|
||||||
if CONF_OSCILLATION_COMMAND_TOPIC in config:
|
if CONF_OSCILLATION_COMMAND_TOPIC in config:
|
||||||
@@ -55,8 +60,8 @@ def setup_fan_core_(fan_var, mqtt_var, config):
|
|||||||
|
|
||||||
|
|
||||||
def setup_fan(fan_obj, mqtt_obj, config):
|
def setup_fan(fan_obj, mqtt_obj, config):
|
||||||
fan_var = Pvariable(FanState, config[CONF_ID], fan_obj, has_side_effects=False)
|
fan_var = Pvariable(config[CONF_ID], fan_obj, has_side_effects=False)
|
||||||
mqtt_var = Pvariable(MQTTFanComponent, config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||||
setup_fan_core_(fan_var, mqtt_var, config)
|
setup_fan_core_(fan_var, mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,25 @@ from esphomeyaml.components import fan
|
|||||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT
|
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT
|
||||||
from esphomeyaml.helpers import App, add, get_variable, variable
|
from esphomeyaml.helpers import App, add, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('binary_fan', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
|
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
|
||||||
}).extend(fan.FAN_SCHEMA.schema)
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
output = get_variable(config[CONF_OUTPUT])
|
output = None
|
||||||
|
for output in get_variable(config[CONF_OUTPUT]):
|
||||||
|
yield
|
||||||
|
|
||||||
rhs = App.make_fan(config[CONF_NAME])
|
rhs = App.make_fan(config[CONF_NAME])
|
||||||
fan_struct = variable(fan.MakeFan, config[CONF_MAKE_ID], rhs)
|
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
add(fan_struct.Poutput.set_binary(output))
|
add(fan_struct.Poutput.set_binary(output))
|
||||||
if CONF_OSCILLATION_OUTPUT in config:
|
if CONF_OSCILLATION_OUTPUT in config:
|
||||||
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
|
oscillation_output = None
|
||||||
|
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
|
||||||
|
yield
|
||||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||||
|
|
||||||
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
||||||
|
|||||||
@@ -7,24 +7,26 @@ from esphomeyaml.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CO
|
|||||||
CONF_SPEED_STATE_TOPIC
|
CONF_SPEED_STATE_TOPIC
|
||||||
from esphomeyaml.helpers import App, add, get_variable, variable
|
from esphomeyaml.helpers import App, add, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('speed_fan', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
|
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
|
||||||
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
|
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
|
||||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
|
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_SPEED): vol.Schema({
|
vol.Optional(CONF_SPEED): vol.Schema({
|
||||||
vol.Required(CONF_LOW): cv.percentage,
|
vol.Required(CONF_LOW): cv.percentage,
|
||||||
vol.Required(CONF_MEDIUM): cv.percentage,
|
vol.Required(CONF_MEDIUM): cv.percentage,
|
||||||
vol.Required(CONF_HIGH): cv.percentage,
|
vol.Required(CONF_HIGH): cv.percentage,
|
||||||
}),
|
}),
|
||||||
}).extend(fan.FAN_SCHEMA.schema)
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
output = get_variable(config[CONF_OUTPUT])
|
output = None
|
||||||
|
for output in get_variable(config[CONF_OUTPUT]):
|
||||||
|
yield
|
||||||
rhs = App.make_fan(config[CONF_NAME])
|
rhs = App.make_fan(config[CONF_NAME])
|
||||||
fan_struct = variable(fan.MakeFan, config[CONF_MAKE_ID], rhs)
|
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
if CONF_SPEED in config:
|
if CONF_SPEED in config:
|
||||||
speeds = config[CONF_SPEED]
|
speeds = config[CONF_SPEED]
|
||||||
add(fan_struct.Poutput.set_speed(output, 0.0,
|
add(fan_struct.Poutput.set_speed(output, 0.0,
|
||||||
@@ -35,7 +37,9 @@ def to_code(config):
|
|||||||
add(fan_struct.Poutput.set_speed(output))
|
add(fan_struct.Poutput.set_speed(output))
|
||||||
|
|
||||||
if CONF_OSCILLATION_OUTPUT in config:
|
if CONF_OSCILLATION_OUTPUT in config:
|
||||||
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
|
oscillation_output = None
|
||||||
|
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
|
||||||
|
yield
|
||||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||||
|
|
||||||
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
||||||
|
|||||||
121
esphomeyaml/components/font.py
Normal file
121
esphomeyaml/components/font.py
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import core
|
||||||
|
from esphomeyaml.components import display
|
||||||
|
from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE
|
||||||
|
from esphomeyaml.core import HexInt
|
||||||
|
from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \
|
||||||
|
relative_path
|
||||||
|
|
||||||
|
DEPENDENCIES = ['display']
|
||||||
|
|
||||||
|
Font = display.display_ns.Font
|
||||||
|
Glyph = display.display_ns.Glyph
|
||||||
|
|
||||||
|
|
||||||
|
def validate_glyphs(value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = vol.Schema([cv.string])(value)
|
||||||
|
value = vol.Schema([cv.string])(list(value))
|
||||||
|
|
||||||
|
def comparator(x, y):
|
||||||
|
x_ = x.encode('utf-8')
|
||||||
|
y_ = y.encode('utf-8')
|
||||||
|
|
||||||
|
for c in range(min(len(x_), len(y_))):
|
||||||
|
if x_[c] < y_[c]:
|
||||||
|
return -1
|
||||||
|
if x_[c] > y_[c]:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if len(x_) < len(y_):
|
||||||
|
return -1
|
||||||
|
elif len(x_) > len(y_):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
raise vol.Invalid(u"Found duplicate glyph {}".format(x))
|
||||||
|
|
||||||
|
value.sort(cmp=comparator)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def validate_pillow_installed(value):
|
||||||
|
try:
|
||||||
|
import PIL
|
||||||
|
except ImportError:
|
||||||
|
raise vol.Invalid("Please install the pillow python package to use this feature. "
|
||||||
|
"(pip2 install pillow)")
|
||||||
|
|
||||||
|
if PIL.__version__[0] < '4':
|
||||||
|
raise vol.Invalid("Please update your pillow installation to at least 4.0.x. "
|
||||||
|
"(pip2 install -U pillow)")
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def validate_truetype_file(value):
|
||||||
|
if value.endswith('.zip'): # for Google Fonts downloads
|
||||||
|
raise vol.Invalid(u"Please unzip the font archive '{}' first and then use the .ttf files "
|
||||||
|
u"inside.".format(value))
|
||||||
|
if not value.endswith('.ttf'):
|
||||||
|
raise vol.Invalid(u"Only truetype (.ttf) files are supported. Please make sure you're "
|
||||||
|
u"using the correct format or rename the extension to .ttf")
|
||||||
|
return cv.file_(value)
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°'
|
||||||
|
CONF_RAW_DATA_ID = 'raw_data_id'
|
||||||
|
|
||||||
|
FONT_SCHEMA = vol.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,
|
||||||
|
vol.Optional(CONF_SIZE, default=20): vol.All(cv.int_, vol.Range(min=1)),
|
||||||
|
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None),
|
||||||
|
})
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.All(validate_pillow_installed, cv.ensure_list, [FONT_SCHEMA])
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
from PIL import ImageFont
|
||||||
|
|
||||||
|
for conf in config:
|
||||||
|
path = relative_path(conf[CONF_FILE])
|
||||||
|
try:
|
||||||
|
font = ImageFont.truetype(path, conf[CONF_SIZE])
|
||||||
|
except Exception as e:
|
||||||
|
raise core.ESPHomeYAMLError(u"Could not load truetype file {}: {}".format(path, e))
|
||||||
|
|
||||||
|
ascent, descent = font.getmetrics()
|
||||||
|
|
||||||
|
glyph_args = {}
|
||||||
|
data = []
|
||||||
|
for glyph in conf[CONF_GLYPHS]:
|
||||||
|
mask = font.getmask(glyph, mode='1')
|
||||||
|
_, (offset_x, offset_y) = font.font.getsize(glyph)
|
||||||
|
width, height = mask.size
|
||||||
|
width8 = ((width + 7) // 8) * 8
|
||||||
|
glyph_data = [0 for _ in range(height * width8 // 8)] # noqa: F812
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
if not mask.getpixel((x, y)):
|
||||||
|
continue
|
||||||
|
pos = x + y * width8
|
||||||
|
glyph_data[pos // 8] |= 0x80 >> (pos % 8)
|
||||||
|
glyph_args[glyph] = (len(data), offset_x, offset_y, width, height)
|
||||||
|
data += glyph_data
|
||||||
|
|
||||||
|
raw_data = MockObj(conf[CONF_RAW_DATA_ID])
|
||||||
|
add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format(
|
||||||
|
raw_data, len(data),
|
||||||
|
ArrayInitializer(*[HexInt(x) for x in data], multiline=False))))
|
||||||
|
|
||||||
|
glyphs = []
|
||||||
|
for glyph in conf[CONF_GLYPHS]:
|
||||||
|
glyphs.append(Glyph(glyph, raw_data, *glyph_args[glyph]))
|
||||||
|
|
||||||
|
rhs = App.make_font(ArrayInitializer(*glyphs), ascent, ascent + descent)
|
||||||
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
@@ -6,25 +6,26 @@ from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CON
|
|||||||
CONF_RECEIVE_TIMEOUT
|
CONF_RECEIVE_TIMEOUT
|
||||||
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
|
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
|
||||||
|
|
||||||
|
I2CComponent = esphomelib_ns.I2CComponent
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('i2c'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(I2CComponent),
|
||||||
vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin,
|
vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin,
|
||||||
vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin,
|
vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin,
|
||||||
vol.Optional(CONF_FREQUENCY): cv.positive_int,
|
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)),
|
||||||
vol.Optional(CONF_RECEIVE_TIMEOUT): cv.positive_time_period_milliseconds,
|
|
||||||
vol.Optional(CONF_SCAN): cv.boolean,
|
vol.Optional(CONF_SCAN): cv.boolean,
|
||||||
})
|
|
||||||
|
|
||||||
I2CComponent = esphomelib_ns.I2CComponent
|
vol.Optional(CONF_RECEIVE_TIMEOUT): cv.invalid("The receive_timeout option has been removed "
|
||||||
|
"because timeouts are already handled by the "
|
||||||
|
"low-level i2c interface.")
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.init_i2c(config[CONF_SDA], config[CONF_SCL], config.get(CONF_SCAN))
|
rhs = App.init_i2c(config[CONF_SDA], config[CONF_SCL], config.get(CONF_SCAN))
|
||||||
i2c = Pvariable(I2CComponent, config[CONF_ID], rhs)
|
i2c = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_FREQUENCY in config:
|
if CONF_FREQUENCY in config:
|
||||||
add(i2c.set_frequency(config[CONF_FREQUENCY]))
|
add(i2c.set_frequency(config[CONF_FREQUENCY]))
|
||||||
if CONF_RECEIVE_TIMEOUT in config:
|
|
||||||
add(i2c.set_receive_timeout(config[CONF_RECEIVE_TIMEOUT]))
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_I2C'
|
BUILD_FLAGS = '-DUSE_I2C'
|
||||||
|
|||||||
65
esphomeyaml/components/image.py
Normal file
65
esphomeyaml/components/image.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import core
|
||||||
|
from esphomeyaml.components import display, font
|
||||||
|
from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE
|
||||||
|
from esphomeyaml.core import HexInt
|
||||||
|
from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \
|
||||||
|
relative_path
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DEPENDENCIES = ['display']
|
||||||
|
|
||||||
|
Image_ = display.display_ns.Image
|
||||||
|
|
||||||
|
CONF_RAW_DATA_ID = 'raw_data_id'
|
||||||
|
|
||||||
|
IMAGE_SCHEMA = vol.Schema({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(Image_),
|
||||||
|
vol.Required(CONF_FILE): cv.file_,
|
||||||
|
vol.Optional(CONF_RESIZE): cv.dimensions,
|
||||||
|
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None),
|
||||||
|
})
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.All(font.validate_pillow_installed, cv.ensure_list, [IMAGE_SCHEMA])
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
for conf in config:
|
||||||
|
path = relative_path(conf[CONF_FILE])
|
||||||
|
try:
|
||||||
|
image = Image.open(path)
|
||||||
|
except Exception as e:
|
||||||
|
raise core.ESPHomeYAMLError(u"Could not load image file {}: {}".format(path, e))
|
||||||
|
|
||||||
|
if CONF_RESIZE in conf:
|
||||||
|
image.thumbnail(conf[CONF_RESIZE])
|
||||||
|
|
||||||
|
image = image.convert('1', dither=Image.NONE)
|
||||||
|
width, height = image.size
|
||||||
|
if width > 500 or height > 500:
|
||||||
|
_LOGGER.warning("The image you requested is very big. Please consider using the resize "
|
||||||
|
"parameter")
|
||||||
|
width8 = ((width + 7) // 8) * 8
|
||||||
|
data = [0 for _ in range(height * width8 // 8)]
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
if image.getpixel((x, y)):
|
||||||
|
continue
|
||||||
|
pos = x + y * width8
|
||||||
|
data[pos // 8] |= 0x80 >> (pos % 8)
|
||||||
|
|
||||||
|
raw_data = MockObj(conf[CONF_RAW_DATA_ID])
|
||||||
|
add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format(
|
||||||
|
raw_data, len(data),
|
||||||
|
ArrayInitializer(*[HexInt(x) for x in data], multiline=False))))
|
||||||
|
|
||||||
|
rhs = App.make_image(raw_data, width, height)
|
||||||
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
@@ -1,26 +1,6 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
|
||||||
from esphomeyaml import pins
|
|
||||||
from esphomeyaml.components import switch
|
|
||||||
from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN
|
|
||||||
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
def CONFIG_SCHEMA(config):
|
||||||
cv.GenerateID('ir_transmitter'): cv.register_variable_id,
|
raise vol.Invalid("The ir_transmitter component has been renamed to "
|
||||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
"remote_transmitter because of 433MHz signal support.")
|
||||||
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int),
|
|
||||||
vol.Range(min=1, max=100)),
|
|
||||||
})])
|
|
||||||
|
|
||||||
IRTransmitterComponent = switch.switch_ns.namespace('IRTransmitterComponent')
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
|
||||||
for conf in config:
|
|
||||||
pin = gpio_output_pin_expression(conf[CONF_PIN])
|
|
||||||
rhs = App.make_ir_transmitter(pin, conf.get(CONF_CARRIER_DUTY_PERCENT))
|
|
||||||
Pvariable(IRTransmitterComponent, conf[CONF_ID], rhs)
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_IR_TRANSMITTER'
|
|
||||||
|
|||||||
@@ -1,40 +1,340 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, \
|
from esphomeyaml.const import CONF_ALPHA, CONF_BLUE, CONF_BRIGHTNESS, CONF_COLORS, \
|
||||||
CONF_MQTT_ID
|
CONF_DEFAULT_TRANSITION_LENGTH, CONF_DURATION, CONF_EFFECTS, CONF_EFFECT_ID, \
|
||||||
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
CONF_GAMMA_CORRECT, \
|
||||||
|
CONF_GREEN, CONF_ID, CONF_INTERNAL, CONF_LAMBDA, CONF_MQTT_ID, CONF_NAME, CONF_NUM_LEDS, \
|
||||||
|
CONF_RANDOM, CONF_RED, CONF_SPEED, CONF_STATE, CONF_TRANSITION_LENGTH, CONF_UPDATE_INTERVAL, \
|
||||||
|
CONF_WHITE, CONF_WIDTH
|
||||||
|
from esphomeyaml.helpers import Application, ArrayInitializer, Pvariable, RawExpression, \
|
||||||
|
StructInitializer, add, add_job, esphomelib_ns, process_lambda, setup_mqtt_component
|
||||||
|
|
||||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
|
||||||
cv.GenerateID('light'): cv.register_variable_id,
|
|
||||||
cv.GenerateID('mqtt_light', CONF_MQTT_ID): cv.register_variable_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
light_ns = esphomelib_ns.namespace('light')
|
light_ns = esphomelib_ns.namespace('light')
|
||||||
LightState = light_ns.LightState
|
LightState = light_ns.LightState
|
||||||
|
LightColorValues = light_ns.LightColorValues
|
||||||
MQTTJSONLightComponent = light_ns.MQTTJSONLightComponent
|
MQTTJSONLightComponent = light_ns.MQTTJSONLightComponent
|
||||||
ToggleAction = light_ns.ToggleAction
|
ToggleAction = light_ns.ToggleAction
|
||||||
TurnOffAction = light_ns.TurnOffAction
|
TurnOffAction = light_ns.TurnOffAction
|
||||||
TurnOnAction = light_ns.TurnOnAction
|
TurnOnAction = light_ns.TurnOnAction
|
||||||
MakeLight = Application.MakeLight
|
MakeLight = Application.MakeLight
|
||||||
|
RandomLightEffect = light_ns.RandomLightEffect
|
||||||
|
LambdaLightEffect = light_ns.LambdaLightEffect
|
||||||
|
StrobeLightEffect = light_ns.StrobeLightEffect
|
||||||
|
StrobeLightEffectColor = light_ns.StrobeLightEffectColor
|
||||||
|
FlickerLightEffect = light_ns.FlickerLightEffect
|
||||||
|
FastLEDLambdaLightEffect = light_ns.FastLEDLambdaLightEffect
|
||||||
|
FastLEDRainbowLightEffect = light_ns.FastLEDRainbowLightEffect
|
||||||
|
FastLEDColorWipeEffect = light_ns.FastLEDColorWipeEffect
|
||||||
|
FastLEDColorWipeEffectColor = light_ns.FastLEDColorWipeEffectColor
|
||||||
|
FastLEDScanEffect = light_ns.FastLEDScanEffect
|
||||||
|
FastLEDScanEffectColor = light_ns.FastLEDScanEffectColor
|
||||||
|
FastLEDTwinkleEffect = light_ns.FastLEDTwinkleEffect
|
||||||
|
FastLEDRandomTwinkleEffect = light_ns.FastLEDRandomTwinkleEffect
|
||||||
|
FastLEDFireworksEffect = light_ns.FastLEDFireworksEffect
|
||||||
|
FastLEDFlickerEffect = light_ns.FastLEDFlickerEffect
|
||||||
|
FastLEDLightOutputComponent = light_ns.FastLEDLightOutputComponent
|
||||||
|
|
||||||
|
CONF_STROBE = 'strobe'
|
||||||
|
CONF_FLICKER = 'flicker'
|
||||||
|
CONF_FASTLED_LAMBDA = 'fastled_lambda'
|
||||||
|
CONF_FASTLED_RAINBOW = 'fastled_rainbow'
|
||||||
|
CONF_FASTLED_COLOR_WIPE = 'fastled_color_wipe'
|
||||||
|
CONF_FASTLED_SCAN = 'fastled_scan'
|
||||||
|
CONF_FASTLED_TWINKLE = 'fastled_twinkle'
|
||||||
|
CONF_FASTLED_RANDOM_TWINKLE = 'fastled_random_twinkle'
|
||||||
|
CONF_FASTLED_FIREWORKS = 'fastled_fireworks'
|
||||||
|
CONF_FASTLED_FLICKER = 'fastled_flicker'
|
||||||
|
|
||||||
|
CONF_ADD_LED_INTERVAL = 'add_led_interval'
|
||||||
|
CONF_REVERSE = 'reverse'
|
||||||
|
CONF_MOVE_INTERVAL = 'move_interval'
|
||||||
|
CONF_TWINKLE_PROBABILITY = 'twinkle_probability'
|
||||||
|
CONF_PROGRESS_INTERVAL = 'progress_interval'
|
||||||
|
CONF_SPARK_PROBABILITY = 'spark_probability'
|
||||||
|
CONF_USE_RANDOM_COLOR = 'use_random_color'
|
||||||
|
CONF_FADE_OUT_RATE = 'fade_out_rate'
|
||||||
|
CONF_INTENSITY = 'intensity'
|
||||||
|
|
||||||
|
BINARY_EFFECTS = [CONF_LAMBDA, CONF_STROBE]
|
||||||
|
MONOCHROMATIC_EFFECTS = BINARY_EFFECTS + [CONF_FLICKER]
|
||||||
|
RGB_EFFECTS = MONOCHROMATIC_EFFECTS + [CONF_RANDOM]
|
||||||
|
FASTLED_EFFECTS = RGB_EFFECTS + [CONF_FASTLED_LAMBDA, CONF_FASTLED_RAINBOW, CONF_FASTLED_COLOR_WIPE,
|
||||||
|
CONF_FASTLED_SCAN, CONF_FASTLED_TWINKLE,
|
||||||
|
CONF_FASTLED_RANDOM_TWINKLE, CONF_FASTLED_FIREWORKS,
|
||||||
|
CONF_FASTLED_FLICKER]
|
||||||
|
|
||||||
|
EFFECTS_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(CONF_LAMBDA): vol.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({
|
||||||
|
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({
|
||||||
|
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.All(vol.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,
|
||||||
|
vol.Optional(CONF_GREEN, default=1.0): cv.percentage,
|
||||||
|
vol.Optional(CONF_BLUE, default=1.0): cv.percentage,
|
||||||
|
vol.Optional(CONF_WHITE, default=1.0): cv.percentage,
|
||||||
|
vol.Required(CONF_DURATION): cv.positive_time_period_milliseconds,
|
||||||
|
}), 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({
|
||||||
|
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_FASTLED_LAMBDA): vol.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_FASTLED_RAINBOW): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDRainbowLightEffect),
|
||||||
|
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_FASTLED_COLOR_WIPE): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDColorWipeEffect),
|
||||||
|
vol.Optional(CONF_NAME, default="Color Wipe"): cv.string,
|
||||||
|
vol.Optional(CONF_COLORS): vol.All(cv.ensure_list, [vol.Schema({
|
||||||
|
vol.Optional(CONF_RED, default=1.0): cv.percentage,
|
||||||
|
vol.Optional(CONF_GREEN, default=1.0): cv.percentage,
|
||||||
|
vol.Optional(CONF_BLUE, default=1.0): cv.percentage,
|
||||||
|
vol.Optional(CONF_RANDOM, default=False): cv.boolean,
|
||||||
|
vol.Required(CONF_NUM_LEDS): vol.All(cv.uint32_t, vol.Range(min=1)),
|
||||||
|
})]),
|
||||||
|
vol.Optional(CONF_ADD_LED_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_REVERSE): cv.boolean,
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_FASTLED_SCAN): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDScanEffect),
|
||||||
|
vol.Optional(CONF_NAME, default="Scan"): cv.string,
|
||||||
|
vol.Optional(CONF_MOVE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_FASTLED_TWINKLE): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDTwinkleEffect),
|
||||||
|
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_FASTLED_RANDOM_TWINKLE): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDRandomTwinkleEffect),
|
||||||
|
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_FASTLED_FIREWORKS): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDFireworksEffect),
|
||||||
|
vol.Optional(CONF_NAME, default="Fireworks"): cv.string,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_SPARK_PROBABILITY): cv.percentage,
|
||||||
|
vol.Optional(CONF_USE_RANDOM_COLOR): cv.boolean,
|
||||||
|
vol.Optional(CONF_FADE_OUT_RATE): cv.uint8_t,
|
||||||
|
}),
|
||||||
|
vol.Optional(CONF_FASTLED_FLICKER): vol.Schema({
|
||||||
|
cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDFlickerEffect),
|
||||||
|
vol.Optional(CONF_NAME, default="FastLED Flicker"): cv.string,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_INTENSITY): cv.percentage,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def validate_effects(allowed_effects):
|
||||||
|
def validator(value):
|
||||||
|
value = cv.ensure_list(value)
|
||||||
|
names = set()
|
||||||
|
ret = []
|
||||||
|
for i, effect in enumerate(value):
|
||||||
|
if not isinstance(effect, dict):
|
||||||
|
raise vol.Invalid("Each effect must be a dictionary, not {}".format(type(value)))
|
||||||
|
if len(effect) > 1:
|
||||||
|
raise vol.Invalid("Each entry in the 'effects:' option must be a single effect.")
|
||||||
|
if not effect:
|
||||||
|
raise vol.Invalid("Found no effect for the {}th entry in 'effects:'!".format(i))
|
||||||
|
key = next(iter(effect.keys()))
|
||||||
|
if key not in allowed_effects:
|
||||||
|
raise vol.Invalid("The effect '{}' does not exist or is not allowed for this "
|
||||||
|
"light type".format(key))
|
||||||
|
effect[key] = effect[key] or {}
|
||||||
|
conf = EFFECTS_SCHEMA(effect)
|
||||||
|
name = conf[key][CONF_NAME]
|
||||||
|
if name in names:
|
||||||
|
raise vol.Invalid(u"Found the effect name '{}' twice. All effects must have "
|
||||||
|
u"unique names".format(name))
|
||||||
|
names.add(name)
|
||||||
|
ret.append(conf)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return validator
|
||||||
|
|
||||||
|
|
||||||
|
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(LightState),
|
||||||
|
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTJSONLightComponent),
|
||||||
|
})
|
||||||
|
|
||||||
|
LIGHT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(LIGHT_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
|
def build_effect(full_config):
|
||||||
|
key, config = next(iter(full_config.items()))
|
||||||
|
if key == CONF_LAMBDA:
|
||||||
|
lambda_ = None
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], []):
|
||||||
|
yield None
|
||||||
|
yield LambdaLightEffect.new(config[CONF_NAME], lambda_, config[CONF_UPDATE_INTERVAL])
|
||||||
|
elif key == CONF_RANDOM:
|
||||||
|
rhs = RandomLightEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_TRANSITION_LENGTH in config:
|
||||||
|
add(effect.set_transition_length(config[CONF_TRANSITION_LENGTH]))
|
||||||
|
if CONF_UPDATE_INTERVAL in config:
|
||||||
|
add(effect.set_update_interval(config[CONF_UPDATE_INTERVAL]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_STROBE:
|
||||||
|
rhs = StrobeLightEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
colors = []
|
||||||
|
for color in config.get(CONF_COLORS, []):
|
||||||
|
colors.append(StructInitializer(
|
||||||
|
StrobeLightEffectColor,
|
||||||
|
('color', LightColorValues(color[CONF_STATE], color[CONF_BRIGHTNESS],
|
||||||
|
color[CONF_RED], color[CONF_GREEN], color[CONF_BLUE],
|
||||||
|
color[CONF_WHITE])),
|
||||||
|
('duration', color[CONF_DURATION]),
|
||||||
|
))
|
||||||
|
if colors:
|
||||||
|
add(effect.set_colors(ArrayInitializer(*colors)))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FLICKER:
|
||||||
|
rhs = FlickerLightEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_ALPHA in config:
|
||||||
|
add(effect.set_alpha(config[CONF_ALPHA]))
|
||||||
|
if CONF_INTENSITY in config:
|
||||||
|
add(effect.set_intensity(config[CONF_INTENSITY]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_LAMBDA:
|
||||||
|
lambda_ = None
|
||||||
|
args = [(RawExpression('FastLEDLightOutputComponent &'), 'it')]
|
||||||
|
for lambda_ in process_lambda(config[CONF_LAMBDA], args):
|
||||||
|
yield None
|
||||||
|
yield FastLEDLambdaLightEffect.new(config[CONF_NAME], lambda_, config[CONF_UPDATE_INTERVAL])
|
||||||
|
elif key == CONF_FASTLED_RAINBOW:
|
||||||
|
rhs = FastLEDRainbowLightEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_SPEED in config:
|
||||||
|
add(effect.set_speed(config[CONF_SPEED]))
|
||||||
|
if CONF_WIDTH in config:
|
||||||
|
add(effect.set_width(config[CONF_WIDTH]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_COLOR_WIPE:
|
||||||
|
rhs = FastLEDColorWipeEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_ADD_LED_INTERVAL in config:
|
||||||
|
add(effect.set_add_led_interval(config[CONF_ADD_LED_INTERVAL]))
|
||||||
|
if CONF_REVERSE in config:
|
||||||
|
add(effect.set_reverse(config[CONF_REVERSE]))
|
||||||
|
colors = []
|
||||||
|
for color in config.get(CONF_COLORS, []):
|
||||||
|
colors.append(StructInitializer(
|
||||||
|
FastLEDColorWipeEffectColor,
|
||||||
|
('r', color[CONF_RED]),
|
||||||
|
('g', color[CONF_GREEN]),
|
||||||
|
('b', color[CONF_BLUE]),
|
||||||
|
('random', color[CONF_RANDOM]),
|
||||||
|
('num_leds', color[CONF_NUM_LEDS]),
|
||||||
|
))
|
||||||
|
if colors:
|
||||||
|
add(effect.set_colors(ArrayInitializer(*colors)))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_SCAN:
|
||||||
|
rhs = FastLEDScanEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_MOVE_INTERVAL in config:
|
||||||
|
add(effect.set_move_interval(config[CONF_MOVE_INTERVAL]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_TWINKLE:
|
||||||
|
rhs = FastLEDTwinkleEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_TWINKLE_PROBABILITY in config:
|
||||||
|
add(effect.set_twinkle_probability(config[CONF_TWINKLE_PROBABILITY]))
|
||||||
|
if CONF_PROGRESS_INTERVAL in config:
|
||||||
|
add(effect.set_progress_interval(config[CONF_PROGRESS_INTERVAL]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_RANDOM_TWINKLE:
|
||||||
|
rhs = FastLEDRandomTwinkleEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_TWINKLE_PROBABILITY in config:
|
||||||
|
add(effect.set_twinkle_probability(config[CONF_TWINKLE_PROBABILITY]))
|
||||||
|
if CONF_PROGRESS_INTERVAL in config:
|
||||||
|
add(effect.set_progress_interval(config[CONF_PROGRESS_INTERVAL]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_FIREWORKS:
|
||||||
|
rhs = FastLEDFireworksEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_UPDATE_INTERVAL in config:
|
||||||
|
add(effect.set_update_interval(config[CONF_UPDATE_INTERVAL]))
|
||||||
|
if CONF_SPARK_PROBABILITY in config:
|
||||||
|
add(effect.set_spark_probability(config[CONF_SPARK_PROBABILITY]))
|
||||||
|
if CONF_USE_RANDOM_COLOR in config:
|
||||||
|
add(effect.set_spark_probability(config[CONF_USE_RANDOM_COLOR]))
|
||||||
|
if CONF_FADE_OUT_RATE in config:
|
||||||
|
add(effect.set_spark_probability(config[CONF_FADE_OUT_RATE]))
|
||||||
|
yield effect
|
||||||
|
elif key == CONF_FASTLED_FLICKER:
|
||||||
|
rhs = FastLEDFlickerEffect.new(config[CONF_NAME])
|
||||||
|
effect = Pvariable(config[CONF_EFFECT_ID], rhs)
|
||||||
|
if CONF_UPDATE_INTERVAL in config:
|
||||||
|
add(effect.set_update_interval(config[CONF_UPDATE_INTERVAL]))
|
||||||
|
if CONF_INTENSITY in config:
|
||||||
|
add(effect.set_intensity(config[CONF_INTENSITY]))
|
||||||
|
yield effect
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Effect {} not implemented".format(next(config.keys())))
|
||||||
|
|
||||||
|
|
||||||
def setup_light_core_(light_var, mqtt_var, config):
|
def setup_light_core_(light_var, mqtt_var, config):
|
||||||
|
if CONF_INTERNAL in config:
|
||||||
|
add(light_var.set_internal(config[CONF_INTERNAL]))
|
||||||
if CONF_DEFAULT_TRANSITION_LENGTH in config:
|
if CONF_DEFAULT_TRANSITION_LENGTH in config:
|
||||||
add(light_var.set_default_transition_length(config[CONF_DEFAULT_TRANSITION_LENGTH]))
|
add(light_var.set_default_transition_length(config[CONF_DEFAULT_TRANSITION_LENGTH]))
|
||||||
if CONF_GAMMA_CORRECT in config:
|
if CONF_GAMMA_CORRECT in config:
|
||||||
add(light_var.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
|
add(light_var.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
|
||||||
|
effects = []
|
||||||
|
for conf in config.get(CONF_EFFECTS, []):
|
||||||
|
for effect in build_effect(conf):
|
||||||
|
yield
|
||||||
|
effects.append(effect)
|
||||||
|
if effects:
|
||||||
|
add(light_var.add_effects(ArrayInitializer(*effects)))
|
||||||
|
|
||||||
setup_mqtt_component(mqtt_var, config)
|
setup_mqtt_component(mqtt_var, config)
|
||||||
|
|
||||||
|
|
||||||
def setup_light(light_obj, mqtt_obj, config):
|
def setup_light(light_obj, mqtt_obj, config):
|
||||||
light_var = Pvariable(LightState, config[CONF_ID], light_obj, has_side_effects=False)
|
light_var = Pvariable(config[CONF_ID], light_obj, has_side_effects=False)
|
||||||
mqtt_var = Pvariable(MQTTJSONLightComponent, config[CONF_MQTT_ID], mqtt_obj,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||||
has_side_effects=False)
|
add_job(setup_light_core_, light_var, mqtt_var, config)
|
||||||
setup_light_core_(light_var, mqtt_var, config)
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_LIGHT'
|
BUILD_FLAGS = '-DUSE_LIGHT'
|
||||||
|
|||||||
@@ -2,17 +2,20 @@ import voluptuous as vol
|
|||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
|
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, get_variable, variable
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('binary_light', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||||
}).extend(light.LIGHT_SCHEMA.schema)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.BINARY_EFFECTS),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
output = get_variable(config[CONF_OUTPUT])
|
output = None
|
||||||
|
for output in get_variable(config[CONF_OUTPUT]):
|
||||||
|
yield
|
||||||
rhs = App.make_binary_light(config[CONF_NAME], output)
|
rhs = App.make_binary_light(config[CONF_NAME], output)
|
||||||
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
|
|||||||
34
esphomeyaml/components/light/cwww.py
Normal file
34
esphomeyaml/components/light/cwww.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import light
|
||||||
|
from esphomeyaml.components.light.rgbww import validate_cold_white_colder, \
|
||||||
|
validate_color_temperature
|
||||||
|
from esphomeyaml.const import CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \
|
||||||
|
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
|
||||||
|
CONF_NAME, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE
|
||||||
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
|
vol.Required(CONF_COLD_WHITE): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_WARM_WHITE): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): validate_color_temperature,
|
||||||
|
vol.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): validate_color_temperature,
|
||||||
|
|
||||||
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.MONOCHROMATIC_EFFECTS),
|
||||||
|
}), validate_cold_white_colder)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for cold_white in get_variable(config[CONF_COLD_WHITE]):
|
||||||
|
yield
|
||||||
|
for warm_white in get_variable(config[CONF_WARM_WHITE]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_cwww_light(config[CONF_NAME], config[CONF_COLD_WHITE_COLOR_TEMPERATURE],
|
||||||
|
config[CONF_WARM_WHITE_COLOR_TEMPERATURE],
|
||||||
|
cold_white, warm_white)
|
||||||
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
@@ -3,9 +3,10 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml import pins
|
from esphomeyaml import pins
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
|
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||||
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||||
CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, \
|
CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, \
|
||||||
CONF_RGB_ORDER
|
CONF_RGB_ORDER, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
||||||
get_variable, variable
|
get_variable, variable
|
||||||
|
|
||||||
@@ -52,8 +53,10 @@ def validate(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
|
MakeFastLEDLight = Application.MakeFastLEDLight
|
||||||
cv.GenerateID('fast_led_clockless_light', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight),
|
||||||
|
|
||||||
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*TYPES)),
|
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*TYPES)),
|
||||||
vol.Required(CONF_PIN): pins.output_pin,
|
vol.Required(CONF_PIN): pins.output_pin,
|
||||||
@@ -64,15 +67,14 @@ PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
|
|||||||
|
|
||||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
|
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||||
}).extend(light.LIGHT_SCHEMA.schema), validate)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.FASTLED_EFFECTS),
|
||||||
|
}), validate)
|
||||||
MakeFastLEDLight = Application.MakeFastLEDLight
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_fast_led_light(config[CONF_NAME])
|
rhs = App.make_fast_led_light(config[CONF_NAME])
|
||||||
make = variable(MakeFastLEDLight, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
fast_led = make.Pfast_led
|
fast_led = make.Pfast_led
|
||||||
|
|
||||||
rgb_order = None
|
rgb_order = None
|
||||||
@@ -86,7 +88,9 @@ def to_code(config):
|
|||||||
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
||||||
|
|
||||||
if CONF_POWER_SUPPLY in config:
|
if CONF_POWER_SUPPLY in config:
|
||||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
power_supply = None
|
||||||
|
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||||
|
yield
|
||||||
add(fast_led.set_power_supply(power_supply))
|
add(fast_led.set_power_supply(power_supply))
|
||||||
|
|
||||||
light.setup_light(make.Pstate, make.Pmqtt, config)
|
light.setup_light(make.Pstate, make.Pmqtt, config)
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml import pins
|
from esphomeyaml import pins
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
|
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||||
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \
|
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \
|
||||||
CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, \
|
CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, \
|
||||||
CONF_NAME, CONF_NUM_LEDS, CONF_POWER_SUPPLY, CONF_RGB_ORDER
|
CONF_NAME, CONF_NUM_LEDS, CONF_POWER_SUPPLY, CONF_RGB_ORDER, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
||||||
get_variable, variable
|
get_variable, variable
|
||||||
|
|
||||||
@@ -29,8 +30,10 @@ RGB_ORDERS = [
|
|||||||
'BGR',
|
'BGR',
|
||||||
]
|
]
|
||||||
|
|
||||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
MakeFastLEDLight = Application.MakeFastLEDLight
|
||||||
cv.GenerateID('fast_led_spi_light', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight),
|
||||||
|
|
||||||
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*CHIPSETS)),
|
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*CHIPSETS)),
|
||||||
vol.Required(CONF_DATA_PIN): pins.output_pin,
|
vol.Required(CONF_DATA_PIN): pins.output_pin,
|
||||||
@@ -42,15 +45,14 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
|||||||
|
|
||||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
|
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||||
}).extend(light.LIGHT_SCHEMA.schema)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.FASTLED_EFFECTS),
|
||||||
|
}))
|
||||||
MakeFastLEDLight = Application.MakeFastLEDLight
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_fast_led_light(config[CONF_NAME])
|
rhs = App.make_fast_led_light(config[CONF_NAME])
|
||||||
make = variable(MakeFastLEDLight, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
fast_led = make.Pfast_led
|
fast_led = make.Pfast_led
|
||||||
|
|
||||||
rgb_order = None
|
rgb_order = None
|
||||||
@@ -66,7 +68,9 @@ def to_code(config):
|
|||||||
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
||||||
|
|
||||||
if CONF_POWER_SUPPLY in config:
|
if CONF_POWER_SUPPLY in config:
|
||||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
power_supply = None
|
||||||
|
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||||
|
yield
|
||||||
add(fast_led.set_power_supply(power_supply))
|
add(fast_led.set_power_supply(power_supply))
|
||||||
|
|
||||||
light.setup_light(make.Pstate, make.Pmqtt, config)
|
light.setup_light(make.Pstate, make.Pmqtt, config)
|
||||||
|
|||||||
@@ -3,19 +3,22 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
|
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
|
||||||
CONF_NAME, CONF_OUTPUT
|
CONF_NAME, CONF_OUTPUT, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, get_variable, variable
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('monochromatic_light', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
}).extend(light.LIGHT_SCHEMA.schema)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.MONOCHROMATIC_EFFECTS),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
output = get_variable(config[CONF_OUTPUT])
|
output = None
|
||||||
|
for output in get_variable(config[CONF_OUTPUT]):
|
||||||
|
yield
|
||||||
rhs = App.make_monochromatic_light(config[CONF_NAME], output)
|
rhs = App.make_monochromatic_light(config[CONF_NAME], output)
|
||||||
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
|
|||||||
@@ -3,23 +3,30 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||||
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED
|
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, get_variable, variable
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('rgb_light', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
vol.Required(CONF_RED): cv.variable_id,
|
vol.Required(CONF_RED): cv.use_variable_id(None),
|
||||||
vol.Required(CONF_GREEN): cv.variable_id,
|
vol.Required(CONF_GREEN): cv.use_variable_id(None),
|
||||||
vol.Required(CONF_BLUE): cv.variable_id,
|
vol.Required(CONF_BLUE): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
}).extend(light.LIGHT_SCHEMA.schema)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.RGB_EFFECTS),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
red = get_variable(config[CONF_RED])
|
red = None
|
||||||
green = get_variable(config[CONF_GREEN])
|
for red in get_variable(config[CONF_RED]):
|
||||||
blue = get_variable(config[CONF_BLUE])
|
yield
|
||||||
|
green = None
|
||||||
|
for green in get_variable(config[CONF_GREEN]):
|
||||||
|
yield
|
||||||
|
blue = None
|
||||||
|
for blue in get_variable(config[CONF_BLUE]):
|
||||||
|
yield
|
||||||
rhs = App.make_rgb_light(config[CONF_NAME], red, green, blue)
|
rhs = App.make_rgb_light(config[CONF_NAME], red, green, blue)
|
||||||
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
|
|||||||
@@ -3,25 +3,34 @@ import voluptuous as vol
|
|||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import light
|
from esphomeyaml.components import light
|
||||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||||
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE
|
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE, CONF_EFFECTS
|
||||||
from esphomeyaml.helpers import App, get_variable, variable
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('rgbw_light', CONF_MAKE_ID): cv.register_variable_id,
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
vol.Required(CONF_RED): cv.variable_id,
|
vol.Required(CONF_RED): cv.use_variable_id(None),
|
||||||
vol.Required(CONF_GREEN): cv.variable_id,
|
vol.Required(CONF_GREEN): cv.use_variable_id(None),
|
||||||
vol.Required(CONF_BLUE): cv.variable_id,
|
vol.Required(CONF_BLUE): cv.use_variable_id(None),
|
||||||
vol.Required(CONF_WHITE): cv.variable_id,
|
vol.Required(CONF_WHITE): cv.use_variable_id(None),
|
||||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
}).extend(light.LIGHT_SCHEMA.schema)
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.RGB_EFFECTS),
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
red = get_variable(config[CONF_RED])
|
red = None
|
||||||
green = get_variable(config[CONF_GREEN])
|
for red in get_variable(config[CONF_RED]):
|
||||||
blue = get_variable(config[CONF_BLUE])
|
yield
|
||||||
white = get_variable(config[CONF_WHITE])
|
green = None
|
||||||
|
for green in get_variable(config[CONF_GREEN]):
|
||||||
|
yield
|
||||||
|
blue = None
|
||||||
|
for blue in get_variable(config[CONF_BLUE]):
|
||||||
|
yield
|
||||||
|
white = None
|
||||||
|
for white in get_variable(config[CONF_WHITE]):
|
||||||
|
yield
|
||||||
rhs = App.make_rgbw_light(config[CONF_NAME], red, green, blue, white)
|
rhs = App.make_rgbw_light(config[CONF_NAME], red, green, blue, white)
|
||||||
light_struct = variable(light.MakeLight, config[CONF_MAKE_ID], rhs)
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
|
|||||||
62
esphomeyaml/components/light/rgbww.py
Normal file
62
esphomeyaml/components/light/rgbww.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import light
|
||||||
|
from esphomeyaml.const import CONF_BLUE, CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \
|
||||||
|
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_GREEN, CONF_MAKE_ID, \
|
||||||
|
CONF_NAME, CONF_RED, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE
|
||||||
|
from esphomeyaml.helpers import App, get_variable, variable
|
||||||
|
|
||||||
|
|
||||||
|
def validate_color_temperature(value):
|
||||||
|
try:
|
||||||
|
val = cv.float_with_unit('Color Temperature', 'mireds')(value)
|
||||||
|
except vol.Invalid:
|
||||||
|
val = 1000000.0 / cv.float_with_unit('Color Temperature', 'K')(value)
|
||||||
|
if val < 0:
|
||||||
|
raise vol.Invalid("Color temperature cannot be negative")
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def validate_cold_white_colder(value):
|
||||||
|
cw = value[CONF_COLD_WHITE_COLOR_TEMPERATURE]
|
||||||
|
ww = value[CONF_WARM_WHITE_COLOR_TEMPERATURE]
|
||||||
|
if cw > ww:
|
||||||
|
raise vol.Invalid("Cold white color temperature cannot be higher than warm white")
|
||||||
|
if cw == ww:
|
||||||
|
raise vol.Invalid("Cold white color temperature cannot be the same as warm white")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||||
|
vol.Required(CONF_RED): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_GREEN): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_BLUE): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_COLD_WHITE): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_WARM_WHITE): cv.use_variable_id(None),
|
||||||
|
vol.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): validate_color_temperature,
|
||||||
|
vol.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): validate_color_temperature,
|
||||||
|
|
||||||
|
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||||
|
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_EFFECTS): light.validate_effects(light.RGB_EFFECTS),
|
||||||
|
}), validate_cold_white_colder)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for red in get_variable(config[CONF_RED]):
|
||||||
|
yield
|
||||||
|
for green in get_variable(config[CONF_GREEN]):
|
||||||
|
yield
|
||||||
|
for blue in get_variable(config[CONF_BLUE]):
|
||||||
|
yield
|
||||||
|
for cold_white in get_variable(config[CONF_COLD_WHITE]):
|
||||||
|
yield
|
||||||
|
for warm_white in get_variable(config[CONF_WARM_WHITE]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_rgbww_light(config[CONF_NAME], config[CONF_COLD_WHITE_COLOR_TEMPERATURE],
|
||||||
|
config[CONF_WARM_WHITE_COLOR_TEMPERATURE],
|
||||||
|
red, green, blue, cold_white, warm_white)
|
||||||
|
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGGER, CONF_LOGS, \
|
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGS, \
|
||||||
CONF_TX_BUFFER_SIZE
|
CONF_TX_BUFFER_SIZE
|
||||||
from esphomeyaml.core import ESPHomeYAMLError
|
from esphomeyaml.core import ESPHomeYAMLError
|
||||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, global_ns
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, global_ns
|
||||||
@@ -31,22 +31,22 @@ def validate_local_no_higher_than_global(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
LogComponent = esphomelib_ns.LogComponent
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||||
cv.GenerateID(CONF_LOGGER): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(LogComponent),
|
||||||
vol.Optional(CONF_BAUD_RATE): cv.positive_int,
|
vol.Optional(CONF_BAUD_RATE): cv.positive_int,
|
||||||
vol.Optional(CONF_TX_BUFFER_SIZE): cv.positive_int,
|
vol.Optional(CONF_TX_BUFFER_SIZE): cv.validate_bytes,
|
||||||
vol.Optional(CONF_LEVEL): is_log_level,
|
vol.Optional(CONF_LEVEL): is_log_level,
|
||||||
vol.Optional(CONF_LOGS): vol.Schema({
|
vol.Optional(CONF_LOGS): vol.Schema({
|
||||||
cv.string: is_log_level,
|
cv.string: is_log_level,
|
||||||
})
|
})
|
||||||
}), validate_local_no_higher_than_global)
|
}), validate_local_no_higher_than_global)
|
||||||
|
|
||||||
LogComponent = esphomelib_ns.LogComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.init_log(config.get(CONF_BAUD_RATE))
|
rhs = App.init_log(config.get(CONF_BAUD_RATE))
|
||||||
log = Pvariable(LogComponent, config[CONF_ID], rhs)
|
log = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_TX_BUFFER_SIZE in config:
|
if CONF_TX_BUFFER_SIZE in config:
|
||||||
add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE]))
|
add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE]))
|
||||||
if CONF_LEVEL in config:
|
if CONF_LEVEL in config:
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml import automation
|
from esphomeyaml import automation
|
||||||
from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, CONF_DISCOVERY, \
|
from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, CONF_DISCOVERY, \
|
||||||
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LOG_TOPIC, \
|
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LOG_TOPIC, \
|
||||||
CONF_MQTT, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, \
|
CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, \
|
||||||
CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \
|
CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \
|
||||||
CONF_WILL_MESSAGE
|
CONF_WILL_MESSAGE, CONF_REBOOT_TIMEOUT, CONF_SHUTDOWN_MESSAGE
|
||||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, StructInitializer, \
|
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, RawExpression, \
|
||||||
TemplateArguments, add, esphomelib_ns, optional, std_string, RawExpression
|
StructInitializer, \
|
||||||
|
TemplateArguments, add, esphomelib_ns, optional, std_string
|
||||||
|
|
||||||
|
|
||||||
def validate_message_just_topic(value):
|
def validate_message_just_topic(value):
|
||||||
value = cv.publish_topic(value)
|
value = cv.publish_topic(value)
|
||||||
return {CONF_TOPIC: value}
|
return MQTT_MESSAGE_BASE({CONF_TOPIC: value})
|
||||||
|
|
||||||
|
|
||||||
MQTT_MESSAGE_BASE = vol.Schema({
|
MQTT_MESSAGE_BASE = vol.Schema({
|
||||||
@@ -54,7 +55,7 @@ def validate_fingerprint(value):
|
|||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID(CONF_MQTT): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
|
||||||
vol.Required(CONF_BROKER): validate_broker,
|
vol.Required(CONF_BROKER): validate_broker,
|
||||||
vol.Optional(CONF_PORT, default=1883): cv.port,
|
vol.Optional(CONF_PORT, default=1883): cv.port,
|
||||||
vol.Optional(CONF_USERNAME, default=''): cv.string,
|
vol.Optional(CONF_USERNAME, default=''): cv.string,
|
||||||
@@ -65,14 +66,17 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
vol.Optional(CONF_DISCOVERY_PREFIX): cv.publish_topic,
|
vol.Optional(CONF_DISCOVERY_PREFIX): cv.publish_topic,
|
||||||
vol.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA,
|
vol.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA,
|
||||||
vol.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA,
|
vol.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA,
|
||||||
|
vol.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA,
|
||||||
vol.Optional(CONF_TOPIC_PREFIX): cv.publish_topic,
|
vol.Optional(CONF_TOPIC_PREFIX): cv.publish_topic,
|
||||||
vol.Optional(CONF_LOG_TOPIC): MQTT_MESSAGE_TEMPLATE_SCHEMA,
|
vol.Optional(CONF_LOG_TOPIC): MQTT_MESSAGE_TEMPLATE_SCHEMA,
|
||||||
vol.Optional(CONF_SSL_FINGERPRINTS): vol.All(cv.only_on_esp8266,
|
vol.Optional(CONF_SSL_FINGERPRINTS): vol.All(cv.only_on_esp8266,
|
||||||
cv.ensure_list, [validate_fingerprint]),
|
cv.ensure_list, [validate_fingerprint]),
|
||||||
vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds,
|
vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds,
|
||||||
vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA.extend({
|
vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds,
|
||||||
|
vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger),
|
||||||
vol.Required(CONF_TOPIC): cv.publish_topic,
|
vol.Required(CONF_TOPIC): cv.publish_topic,
|
||||||
vol.Optional(CONF_QOS, 0): cv.mqtt_qos,
|
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
|
||||||
})])
|
})])
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ def exp_mqtt_message(config):
|
|||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.init_mqtt(config[CONF_BROKER], config[CONF_PORT],
|
rhs = App.init_mqtt(config[CONF_BROKER], config[CONF_PORT],
|
||||||
config[CONF_USERNAME], config[CONF_PASSWORD])
|
config[CONF_USERNAME], config[CONF_PASSWORD])
|
||||||
mqtt = Pvariable(MQTTClientComponent, config[CONF_ID], rhs)
|
mqtt = Pvariable(config[CONF_ID], rhs)
|
||||||
if not config.get(CONF_DISCOVERY, True):
|
if not config.get(CONF_DISCOVERY, True):
|
||||||
add(mqtt.disable_discovery())
|
add(mqtt.disable_discovery())
|
||||||
if CONF_DISCOVERY_RETAIN in config or CONF_DISCOVERY_PREFIX in config:
|
if CONF_DISCOVERY_RETAIN in config or CONF_DISCOVERY_PREFIX in config:
|
||||||
@@ -104,34 +108,42 @@ def to_code(config):
|
|||||||
add(mqtt.set_topic_prefix(config[CONF_TOPIC_PREFIX]))
|
add(mqtt.set_topic_prefix(config[CONF_TOPIC_PREFIX]))
|
||||||
if CONF_BIRTH_MESSAGE in config:
|
if CONF_BIRTH_MESSAGE in config:
|
||||||
birth_message = config[CONF_BIRTH_MESSAGE]
|
birth_message = config[CONF_BIRTH_MESSAGE]
|
||||||
if birth_message is None:
|
if not birth_message:
|
||||||
add(mqtt.disable_birth_message())
|
add(mqtt.disable_birth_message())
|
||||||
else:
|
else:
|
||||||
add(mqtt.set_birth_message(exp_mqtt_message(birth_message)))
|
add(mqtt.set_birth_message(exp_mqtt_message(birth_message)))
|
||||||
if CONF_WILL_MESSAGE in config:
|
if CONF_WILL_MESSAGE in config:
|
||||||
will_message = config[CONF_WILL_MESSAGE]
|
will_message = config[CONF_WILL_MESSAGE]
|
||||||
if will_message is None:
|
if not will_message:
|
||||||
add(mqtt.disable_last_will())
|
add(mqtt.disable_last_will())
|
||||||
else:
|
else:
|
||||||
add(mqtt.set_last_will(exp_mqtt_message(will_message)))
|
add(mqtt.set_last_will(exp_mqtt_message(will_message)))
|
||||||
|
if CONF_SHUTDOWN_MESSAGE in config:
|
||||||
|
shutdown_message = config[CONF_SHUTDOWN_MESSAGE]
|
||||||
|
if not shutdown_message:
|
||||||
|
add(mqtt.disable_shutdown_message())
|
||||||
|
else:
|
||||||
|
add(mqtt.set_shutdown_message(exp_mqtt_message(shutdown_message)))
|
||||||
if CONF_CLIENT_ID in config:
|
if CONF_CLIENT_ID in config:
|
||||||
add(mqtt.set_client_id(config[CONF_CLIENT_ID]))
|
add(mqtt.set_client_id(config[CONF_CLIENT_ID]))
|
||||||
if CONF_LOG_TOPIC in config:
|
if CONF_LOG_TOPIC in config:
|
||||||
log_topic = config[CONF_LOG_TOPIC]
|
log_topic = config[CONF_LOG_TOPIC]
|
||||||
if log_topic is None:
|
if not log_topic:
|
||||||
add(mqtt.disable_log_message())
|
add(mqtt.disable_log_message())
|
||||||
else:
|
else:
|
||||||
add(mqtt.set_log_topic(exp_mqtt_message(log_topic)))
|
add(mqtt.set_log_message_template(exp_mqtt_message(log_topic)))
|
||||||
if CONF_SSL_FINGERPRINTS in config:
|
if CONF_SSL_FINGERPRINTS in config:
|
||||||
for fingerprint in config[CONF_SSL_FINGERPRINTS]:
|
for fingerprint in config[CONF_SSL_FINGERPRINTS]:
|
||||||
arr = [RawExpression("0x{}".format(fingerprint[i:i + 2])) for i in range(0, 40, 2)]
|
arr = [RawExpression("0x{}".format(fingerprint[i:i + 2])) for i in range(0, 40, 2)]
|
||||||
add(mqtt.add_ssl_fingerprint(ArrayInitializer(*arr, multiline=False)))
|
add(mqtt.add_ssl_fingerprint(ArrayInitializer(*arr, multiline=False)))
|
||||||
if CONF_KEEPALIVE in config:
|
if CONF_KEEPALIVE in config:
|
||||||
add(mqtt.set_keep_alive(config[CONF_KEEPALIVE]))
|
add(mqtt.set_keep_alive(config[CONF_KEEPALIVE]))
|
||||||
|
if CONF_REBOOT_TIMEOUT in config:
|
||||||
|
add(mqtt.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_MESSAGE, []):
|
for conf in config.get(CONF_ON_MESSAGE, []):
|
||||||
rhs = mqtt.make_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS])
|
rhs = mqtt.make_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS])
|
||||||
trigger = Pvariable(MQTTMessageTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, std_string, conf)
|
automation.build_automation(trigger, std_string, conf)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,23 +12,25 @@ from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
OTAComponent = esphomelib_ns.OTAComponent
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID(CONF_OTA): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(OTAComponent),
|
||||||
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
|
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
|
||||||
# TODO Num attempts + wait time
|
# TODO Num attempts + wait time
|
||||||
vol.Optional(CONF_PORT): cv.port,
|
vol.Optional(CONF_PORT): cv.port,
|
||||||
vol.Optional(CONF_PASSWORD): cv.string,
|
vol.Optional(CONF_PASSWORD): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
OTAComponent = esphomelib_ns.OTAComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.init_ota()
|
rhs = App.init_ota()
|
||||||
ota = Pvariable(OTAComponent, config[CONF_ID], rhs)
|
ota = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_PASSWORD in config:
|
if CONF_PASSWORD in config:
|
||||||
hash_ = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest()
|
hash_ = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest()
|
||||||
add(ota.set_auth_password_hash(hash_))
|
add(ota.set_auth_password_hash(hash_))
|
||||||
|
if CONF_PORT in config:
|
||||||
|
add(ota.set_port(config[CONF_PORT]))
|
||||||
if config[CONF_SAFE_MODE]:
|
if config[CONF_SAFE_MODE]:
|
||||||
add(ota.start_safe_mode())
|
add(ota.start_safe_mode())
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||||
from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY
|
from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY
|
||||||
from esphomeyaml.helpers import add, esphomelib_ns, get_variable
|
from esphomeyaml.helpers import add, esphomelib_ns, get_variable
|
||||||
|
|
||||||
@@ -8,26 +9,40 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
BINARY_OUTPUT_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
|
BINARY_OUTPUT_SCHEMA = vol.Schema({
|
||||||
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
|
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
BINARY_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_OUTPUT_SCHEMA.schema)
|
||||||
|
|
||||||
FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({
|
FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({
|
||||||
vol.Optional(CONF_MAX_POWER): cv.percentage,
|
vol.Optional(CONF_MAX_POWER): cv.percentage,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema)
|
||||||
|
|
||||||
output_ns = esphomelib_ns.namespace('output')
|
output_ns = esphomelib_ns.namespace('output')
|
||||||
|
TurnOffAction = output_ns.TurnOffAction
|
||||||
|
TurnOnAction = output_ns.TurnOnAction
|
||||||
|
SetLevelAction = output_ns.SetLevelAction
|
||||||
|
|
||||||
|
|
||||||
def setup_output_platform(obj, config, skip_power_supply=False):
|
def setup_output_platform_(obj, config, skip_power_supply=False):
|
||||||
if CONF_INVERTED in config:
|
if CONF_INVERTED in config:
|
||||||
add(obj.set_inverted(config[CONF_INVERTED]))
|
add(obj.set_inverted(config[CONF_INVERTED]))
|
||||||
if not skip_power_supply and CONF_POWER_SUPPLY in config:
|
if not skip_power_supply and CONF_POWER_SUPPLY in config:
|
||||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
power_supply = None
|
||||||
|
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||||
|
yield
|
||||||
add(obj.set_power_supply(power_supply))
|
add(obj.set_power_supply(power_supply))
|
||||||
if CONF_MAX_POWER in config:
|
if CONF_MAX_POWER in config:
|
||||||
add(obj.set_max_power(config[CONF_MAX_POWER]))
|
add(obj.set_max_power(config[CONF_MAX_POWER]))
|
||||||
|
|
||||||
|
|
||||||
|
def setup_output_platform(obj, config, skip_power_supply=False):
|
||||||
|
for _ in setup_output_platform_(obj, config, skip_power_supply):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_OUTPUT'
|
BUILD_FLAGS = '-DUSE_OUTPUT'
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from esphomeyaml import pins
|
from esphomeyaml import pins
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import output
|
from esphomeyaml.components import output
|
||||||
from esphomeyaml.const import CONF_ID, CONF_PIN, ESP_PLATFORM_ESP8266, CONF_NUMBER
|
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266
|
||||||
from esphomeyaml.core import ESPHomeYAMLError
|
from esphomeyaml.core import ESPHomeYAMLError
|
||||||
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
||||||
|
|
||||||
@@ -10,22 +11,25 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP8266]
|
|||||||
|
|
||||||
|
|
||||||
def valid_pwm_pin(value):
|
def valid_pwm_pin(value):
|
||||||
if value[CONF_NUMBER] >= 16:
|
if value[CONF_NUMBER] > 16:
|
||||||
raise ESPHomeYAMLError(u"ESP8266: Only pins 0-16 support PWM.")
|
raise ESPHomeYAMLError(u"ESP8266: Only pins 0-16 support PWM.")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
|
|
||||||
vol.Required(CONF_PIN): vol.All(pins.GPIO_INTERNAL_OUTPUT_PIN_SCHEMA, valid_pwm_pin),
|
|
||||||
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema)
|
|
||||||
|
|
||||||
ESP8266PWMOutput = output.output_ns.ESP8266PWMOutput
|
ESP8266PWMOutput = output.output_ns.ESP8266PWMOutput
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(ESP8266PWMOutput),
|
||||||
|
vol.Required(CONF_PIN): vol.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
pin = gpio_output_pin_expression(config[CONF_PIN])
|
pin = None
|
||||||
|
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||||
|
yield
|
||||||
rhs = App.make_esp8266_pwm_output(pin)
|
rhs = App.make_esp8266_pwm_output(pin)
|
||||||
gpio = Pvariable(ESP8266PWMOutput, config[CONF_ID], rhs)
|
gpio = Pvariable(config[CONF_ID], rhs)
|
||||||
output.setup_output_platform(gpio, config)
|
output.setup_output_platform(gpio, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from esphomeyaml import pins
|
from esphomeyaml import pins
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
from esphomeyaml.components import output
|
from esphomeyaml.components import output
|
||||||
from esphomeyaml.const import CONF_ID, CONF_PIN
|
from esphomeyaml.const import CONF_ID, CONF_PIN
|
||||||
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
||||||
|
|
||||||
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
|
|
||||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
|
||||||
}).extend(output.BINARY_OUTPUT_SCHEMA.schema)
|
|
||||||
|
|
||||||
GPIOBinaryOutputComponent = output.output_ns.GPIOBinaryOutputComponent
|
GPIOBinaryOutputComponent = output.output_ns.GPIOBinaryOutputComponent
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = output.BINARY_OUTPUT_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(GPIOBinaryOutputComponent),
|
||||||
|
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
pin = gpio_output_pin_expression(config[CONF_PIN])
|
pin = None
|
||||||
|
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||||
|
yield
|
||||||
rhs = App.make_gpio_output(pin)
|
rhs = App.make_gpio_output(pin)
|
||||||
gpio = Pvariable(GPIOBinaryOutputComponent, config[CONF_ID], rhs)
|
gpio = Pvariable(config[CONF_ID], rhs)
|
||||||
output.setup_output_platform(gpio, config)
|
output.setup_output_platform(gpio, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,19 +15,19 @@ def validate_frequency_bit_depth(obj):
|
|||||||
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
|
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
|
||||||
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
|
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
|
||||||
if frequency > max_freq:
|
if frequency > max_freq:
|
||||||
raise vol.Invalid('Maximum frequency for bit depth {} is {}'.format(bit_depth, max_freq))
|
raise vol.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, max_freq))
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.All(output.PLATFORM_SCHEMA.extend({
|
LEDCOutputComponent = output.output_ns.LEDCOutputComponent
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.All(output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(LEDCOutputComponent),
|
||||||
vol.Required(CONF_PIN): pins.output_pin,
|
vol.Required(CONF_PIN): pins.output_pin,
|
||||||
vol.Optional(CONF_FREQUENCY): cv.frequency,
|
vol.Optional(CONF_FREQUENCY): cv.frequency,
|
||||||
vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)),
|
vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)),
|
||||||
vol.Optional(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15))
|
vol.Optional(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15))
|
||||||
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema), validate_frequency_bit_depth)
|
}), validate_frequency_bit_depth)
|
||||||
|
|
||||||
|
|
||||||
LEDCOutputComponent = output.output_ns.LEDCOutputComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
@@ -35,7 +35,7 @@ def to_code(config):
|
|||||||
if frequency is None and CONF_BIT_DEPTH in config:
|
if frequency is None and CONF_BIT_DEPTH in config:
|
||||||
frequency = 1000
|
frequency = 1000
|
||||||
rhs = App.make_ledc_output(config[CONF_PIN], frequency, config.get(CONF_BIT_DEPTH))
|
rhs = App.make_ledc_output(config[CONF_PIN], frequency, config.get(CONF_BIT_DEPTH))
|
||||||
ledc = Pvariable(LEDCOutputComponent, config[CONF_ID], rhs)
|
ledc = Pvariable(config[CONF_ID], rhs)
|
||||||
if CONF_CHANNEL in config:
|
if CONF_CHANNEL in config:
|
||||||
add(ledc.set_channel(config[CONF_CHANNEL]))
|
add(ledc.set_channel(config[CONF_CHANNEL]))
|
||||||
output.setup_output_platform(ledc, config)
|
output.setup_output_platform(ledc, config)
|
||||||
|
|||||||
@@ -8,22 +8,26 @@ from esphomeyaml.helpers import Pvariable, get_variable
|
|||||||
|
|
||||||
DEPENDENCIES = ['pca9685']
|
DEPENDENCIES = ['pca9685']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
|
Channel = PCA9685OutputComponent.Channel
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(Channel),
|
||||||
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int),
|
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int),
|
||||||
vol.Range(min=0, max=15)),
|
vol.Range(min=0, max=15)),
|
||||||
vol.Optional(CONF_PCA9685_ID): cv.variable_id,
|
cv.GenerateID(CONF_PCA9685_ID): cv.use_variable_id(PCA9685OutputComponent),
|
||||||
}).extend(output.FLOAT_OUTPUT_SCHEMA.schema)
|
})
|
||||||
|
|
||||||
Channel = PCA9685OutputComponent.Channel
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
power_supply = None
|
power_supply = None
|
||||||
if CONF_POWER_SUPPLY in config:
|
if CONF_POWER_SUPPLY in config:
|
||||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||||
pca9685 = get_variable(config.get(CONF_PCA9685_ID), PCA9685OutputComponent)
|
yield
|
||||||
|
pca9685 = None
|
||||||
|
for pca9685 in get_variable(config[CONF_PCA9685_ID]):
|
||||||
|
yield
|
||||||
rhs = pca9685.create_channel(config[CONF_CHANNEL], power_supply)
|
rhs = pca9685.create_channel(config[CONF_CHANNEL], power_supply)
|
||||||
out = Pvariable(Channel, config[CONF_ID], rhs)
|
out = Pvariable(config[CONF_ID], rhs)
|
||||||
output.setup_output_platform(out, config, skip_power_supply=True)
|
output.setup_output_platform(out, config, skip_power_supply=True)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ PHASE_BALANCER_MESSAGE = ("The phase_balancer option has been removed in version
|
|||||||
"esphomelib will now automatically choose a suitable phase balancer.")
|
"esphomelib will now automatically choose a suitable phase balancer.")
|
||||||
|
|
||||||
PCA9685_SCHEMA = vol.Schema({
|
PCA9685_SCHEMA = vol.Schema({
|
||||||
cv.GenerateID('pca9685'): cv.register_variable_id,
|
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
|
||||||
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
|
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
|
||||||
vol.Range(min=23.84, max=1525.88)),
|
vol.Range(min=23.84, max=1525.88)),
|
||||||
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||||
@@ -27,7 +27,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCA9685_SCHEMA])
|
|||||||
def to_code(config):
|
def to_code(config):
|
||||||
for conf in config:
|
for conf in config:
|
||||||
rhs = App.make_pca9685_component(conf.get(CONF_FREQUENCY))
|
rhs = App.make_pca9685_component(conf.get(CONF_FREQUENCY))
|
||||||
pca9685 = Pvariable(PCA9685OutputComponent, conf[CONF_ID], rhs)
|
pca9685 = Pvariable(conf[CONF_ID], rhs)
|
||||||
if CONF_ADDRESS in conf:
|
if CONF_ADDRESS in conf:
|
||||||
add(pca9685.set_address(HexIntLiteral(conf[CONF_ADDRESS])))
|
add(pca9685.set_address(HexIntLiteral(conf[CONF_ADDRESS])))
|
||||||
|
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ from esphomeyaml.helpers import App, Pvariable, esphomelib_ns
|
|||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
io_ns = esphomelib_ns.namespace('io')
|
||||||
|
PCF8574Component = io_ns.PCF8574Component
|
||||||
|
|
||||||
PCF8574_SCHEMA = vol.Schema({
|
PCF8574_SCHEMA = vol.Schema({
|
||||||
vol.Required(CONF_ID): cv.register_variable_id,
|
vol.Required(CONF_ID): cv.declare_variable_id(PCF8574Component),
|
||||||
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
|
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
|
||||||
vol.Optional(CONF_PCF8575, default=False): cv.boolean,
|
vol.Optional(CONF_PCF8575, default=False): cv.boolean,
|
||||||
})
|
})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCF8574_SCHEMA])
|
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCF8574_SCHEMA])
|
||||||
|
|
||||||
io_ns = esphomelib_ns.namespace('io')
|
|
||||||
PCF8574Component = io_ns.PCF8574Component
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
for conf in config:
|
for conf in config:
|
||||||
rhs = App.make_pcf8574_component(conf[CONF_ADDRESS], conf[CONF_PCF8575])
|
rhs = App.make_pcf8574_component(conf[CONF_ADDRESS], conf[CONF_PCF8575])
|
||||||
Pvariable(PCF8574Component, conf[CONF_ID], rhs)
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_PCF8574'
|
BUILD_FLAGS = '-DUSE_PCF8574'
|
||||||
|
|||||||
34
esphomeyaml/components/pn532.py
Normal file
34
esphomeyaml/components/pn532.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.spi import SPIComponent
|
||||||
|
from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_SPI_ID, CONF_UPDATE_INTERVAL
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, get_variable, gpio_output_pin_expression
|
||||||
|
|
||||||
|
DEPENDENCIES = ['spi']
|
||||||
|
|
||||||
|
PN532Component = binary_sensor.binary_sensor_ns.PN532Component
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.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,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})])
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for conf in config:
|
||||||
|
spi = None
|
||||||
|
for spi in get_variable(conf[CONF_SPI_ID]):
|
||||||
|
yield
|
||||||
|
cs = None
|
||||||
|
for cs in gpio_output_pin_expression(conf[CONF_CS_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_pn532_component(spi, cs, conf.get(CONF_UPDATE_INTERVAL))
|
||||||
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_PN532'
|
||||||
@@ -5,21 +5,25 @@ from esphomeyaml import pins
|
|||||||
from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
|
from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
|
||||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
|
||||||
|
|
||||||
POWER_SUPPLY_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
|
PowerSupplyComponent = esphomelib_ns.PowerSupplyComponent
|
||||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
|
||||||
|
POWER_SUPPLY_SCHEMA = vol.Schema({
|
||||||
|
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
|
||||||
|
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||||
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
|
||||||
})
|
})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
|
CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
|
||||||
|
|
||||||
PowerSupplyComponent = esphomelib_ns.PowerSupplyComponent
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
for conf in config:
|
for conf in config:
|
||||||
rhs = App.make_power_supply(gpio_output_pin_expression(conf[CONF_PIN]))
|
pin = None
|
||||||
psu = Pvariable(PowerSupplyComponent, conf[CONF_ID], rhs)
|
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_power_supply(pin)
|
||||||
|
psu = Pvariable(conf[CONF_ID], rhs)
|
||||||
if CONF_ENABLE_TIME in conf:
|
if CONF_ENABLE_TIME in conf:
|
||||||
add(psu.set_enable_time(conf[CONF_ENABLE_TIME]))
|
add(psu.set_enable_time(conf[CONF_ENABLE_TIME]))
|
||||||
if CONF_KEEP_ON_TIME in conf:
|
if CONF_KEEP_ON_TIME in conf:
|
||||||
|
|||||||
28
esphomeyaml/components/rdm6300.py
Normal file
28
esphomeyaml/components/rdm6300.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import binary_sensor
|
||||||
|
from esphomeyaml.components.uart import UARTComponent
|
||||||
|
from esphomeyaml.const import CONF_ID, CONF_UART_ID
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['uart']
|
||||||
|
|
||||||
|
RDM6300Component = binary_sensor.binary_sensor_ns.RDM6300Component
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.All(cv.ensure_list_not_empty, [vol.Schema({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(RDM6300Component),
|
||||||
|
cv.GenerateID(CONF_UART_ID): cv.use_variable_id(UARTComponent),
|
||||||
|
})])
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for conf in config:
|
||||||
|
uart = None
|
||||||
|
for uart in get_variable(conf[CONF_UART_ID]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_rdm6300_component(uart)
|
||||||
|
Pvariable(conf[CONF_ID], rhs)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_RDM6300'
|
||||||
63
esphomeyaml/components/remote_receiver.py
Normal file
63
esphomeyaml/components/remote_receiver.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID, CONF_IDLE, \
|
||||||
|
CONF_PIN, CONF_TOLERANCE
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_input_pin_expression
|
||||||
|
|
||||||
|
remote_ns = esphomelib_ns.namespace('remote')
|
||||||
|
|
||||||
|
RemoteReceiverComponent = remote_ns.RemoteReceiverComponent
|
||||||
|
|
||||||
|
DUMPERS = {
|
||||||
|
'lg': remote_ns.LGDumper,
|
||||||
|
'nec': remote_ns.NECDumper,
|
||||||
|
'panasonic': remote_ns.PanasonicDumper,
|
||||||
|
'raw': remote_ns.RawDumper,
|
||||||
|
'sony': remote_ns.SonyDumper,
|
||||||
|
'rc_switch': remote_ns.RCSwitchDumper,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_dumpers_all(value):
|
||||||
|
if not isinstance(value, (str, unicode)):
|
||||||
|
raise vol.Invalid("Not valid dumpers")
|
||||||
|
if value.upper() == "ALL":
|
||||||
|
return list(sorted(list(DUMPERS)))
|
||||||
|
raise vol.Invalid("Not valid dumpers")
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent),
|
||||||
|
vol.Required(CONF_PIN): pins.gpio_input_pin_schema,
|
||||||
|
vol.Optional(CONF_DUMP, default=[]):
|
||||||
|
vol.Any(validate_dumpers_all,
|
||||||
|
vol.All(cv.ensure_list, [vol.All(vol.Lower, cv.one_of(*DUMPERS))])),
|
||||||
|
vol.Optional(CONF_TOLERANCE): vol.All(cv.percentage_int, vol.Range(min=0)),
|
||||||
|
vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes,
|
||||||
|
vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds,
|
||||||
|
vol.Optional(CONF_IDLE): cv.positive_time_period_microseconds,
|
||||||
|
})])
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for conf in config:
|
||||||
|
pin = None
|
||||||
|
for pin in gpio_input_pin_expression(conf[CONF_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_remote_receiver_component(pin)
|
||||||
|
receiver = Pvariable(conf[CONF_ID], rhs)
|
||||||
|
for dumper in conf[CONF_DUMP]:
|
||||||
|
add(receiver.add_dumper(DUMPERS[dumper].new()))
|
||||||
|
if CONF_TOLERANCE in conf:
|
||||||
|
add(receiver.set_tolerance(conf[CONF_TOLERANCE]))
|
||||||
|
if CONF_BUFFER_SIZE in conf:
|
||||||
|
add(receiver.set_buffer_size(conf[CONF_BUFFER_SIZE]))
|
||||||
|
if CONF_FILTER in conf:
|
||||||
|
add(receiver.set_filter_us(conf[CONF_FILTER]))
|
||||||
|
if CONF_IDLE in conf:
|
||||||
|
add(receiver.set_idle_us(conf[CONF_IDLE]))
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER'
|
||||||
116
esphomeyaml/components/remote_transmitter.py
Normal file
116
esphomeyaml/components/remote_transmitter.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_DUTY_PERCENT, CONF_CHANNEL, CONF_CODE, \
|
||||||
|
CONF_DEVICE, CONF_FAMILY, CONF_GROUP, CONF_ID, CONF_INVERTED, CONF_ONE, CONF_PIN, \
|
||||||
|
CONF_PROTOCOL, CONF_PULSE_LENGTH, CONF_STATE, CONF_SYNC, CONF_ZERO
|
||||||
|
from esphomeyaml.core import HexInt
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
|
||||||
|
|
||||||
|
remote_ns = esphomelib_ns.namespace('remote')
|
||||||
|
|
||||||
|
RemoteTransmitterComponent = remote_ns.RemoteTransmitterComponent
|
||||||
|
RCSwitchProtocol = remote_ns.RCSwitchProtocol
|
||||||
|
rc_switch_protocols = remote_ns.rc_switch_protocols
|
||||||
|
|
||||||
|
|
||||||
|
def validate_rc_switch_code(value):
|
||||||
|
if not isinstance(value, (str, unicode)):
|
||||||
|
raise vol.Invalid("All RCSwitch codes must be in quotes ('')")
|
||||||
|
for c in value:
|
||||||
|
if c not in ('0', '1'):
|
||||||
|
raise vol.Invalid(u"Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed"
|
||||||
|
u"".format(c))
|
||||||
|
if len(value) > 32:
|
||||||
|
raise vol.Invalid("Maximum length for RCSwitch codes is 32, code '{}' has length {}"
|
||||||
|
"".format(value, len(value)))
|
||||||
|
if not value:
|
||||||
|
raise vol.Invalid("RCSwitch code must not be empty")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
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({
|
||||||
|
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,
|
||||||
|
vol.Optional(CONF_ONE, default=[3, 1]): RC_SWITCH_TIMING_SCHEMA,
|
||||||
|
vol.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
RC_SWITCH_RAW_SCHEMA = vol.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({
|
||||||
|
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({
|
||||||
|
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({
|
||||||
|
vol.Required(CONF_FAMILY): vol.All(
|
||||||
|
cv.string, vol.Lower,
|
||||||
|
cv.one_of('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||||
|
'p')),
|
||||||
|
vol.Required(CONF_GROUP): vol.All(cv.uint8_t, vol.Range(min=1, max=4)),
|
||||||
|
vol.Required(CONF_DEVICE): 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_D_SCHEMA = vol.Schema({
|
||||||
|
vol.Required(CONF_GROUP): vol.All(cv.string, vol.Lower, cv.one_of('a', 'b', 'c', 'd')),
|
||||||
|
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.All(cv.ensure_list, [vol.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,
|
||||||
|
vol.Range(min=1, max=100)),
|
||||||
|
})])
|
||||||
|
|
||||||
|
|
||||||
|
def build_rc_switch_protocol(config):
|
||||||
|
if isinstance(config, int):
|
||||||
|
return rc_switch_protocols[config]
|
||||||
|
pl = config[CONF_PULSE_LENGTH]
|
||||||
|
return RCSwitchProtocol(config[CONF_SYNC][0] * pl, config[CONF_SYNC][1] * pl,
|
||||||
|
config[CONF_ZERO][0] * pl, config[CONF_ZERO][1] * pl,
|
||||||
|
config[CONF_ONE][0] * pl, config[CONF_ONE][1] * pl,
|
||||||
|
config[CONF_INVERTED])
|
||||||
|
|
||||||
|
|
||||||
|
def binary_code(value):
|
||||||
|
code = 0
|
||||||
|
for val in value:
|
||||||
|
code <<= 1
|
||||||
|
code |= val == '1'
|
||||||
|
return HexInt(code)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
for conf in config:
|
||||||
|
pin = None
|
||||||
|
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_remote_transmitter_component(pin)
|
||||||
|
transmitter = Pvariable(conf[CONF_ID], rhs)
|
||||||
|
if CONF_CARRIER_DUTY_PERCENT in conf:
|
||||||
|
add(transmitter.set_carrier_duty_percent(conf[CONF_CARRIER_DUTY_PERCENT]))
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER'
|
||||||
@@ -4,12 +4,12 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml import automation
|
from esphomeyaml import automation
|
||||||
from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \
|
from esphomeyaml.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_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_LAMBDA, \
|
CONF_FILTER_NAN, CONF_FILTER_OUT, CONF_HEARTBEAT, CONF_ICON, CONF_ID, CONF_INTERNAL, \
|
||||||
CONF_MQTT_ID, CONF_MULTIPLY, CONF_NAME, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE,\
|
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_SLIDING_WINDOW_MOVING_AVERAGE, \
|
CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SLIDING_WINDOW_MOVING_AVERAGE, \
|
||||||
CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
|
CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
|
||||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, esphomelib_ns, float_, \
|
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, add_job, esphomelib_ns, \
|
||||||
process_lambda, setup_mqtt_component, templatable
|
float_, process_lambda, setup_mqtt_component, templatable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
@@ -44,25 +44,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
|||||||
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
|
||||||
vol.Optional(CONF_OR): validate_recursive_filter,
|
vol.Optional(CONF_OR): validate_recursive_filter,
|
||||||
}, cv.has_at_exactly_one_key(*FILTER_KEYS))])
|
}, cv.has_exactly_one_key(*FILTER_KEYS))])
|
||||||
|
|
||||||
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
|
||||||
cv.GenerateID('mqtt_sensor', CONF_MQTT_ID): cv.register_variable_id,
|
|
||||||
cv.GenerateID('sensor'): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_NAME): cv.string,
|
|
||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict,
|
|
||||||
vol.Optional(CONF_ICON): cv.icon,
|
|
||||||
vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int),
|
|
||||||
vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds),
|
|
||||||
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
|
|
||||||
vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
|
|
||||||
vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.AUTOMATION_SCHEMA]),
|
|
||||||
vol.Optional(CONF_ON_VALUE_RANGE): vol.All(cv.ensure_list, [vol.All(
|
|
||||||
automation.AUTOMATION_SCHEMA.extend({
|
|
||||||
vol.Optional(CONF_ABOVE): vol.Coerce(float),
|
|
||||||
vol.Optional(CONF_BELOW): vol.Coerce(float),
|
|
||||||
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))]),
|
|
||||||
})
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
sensor_ns = esphomelib_ns.namespace('sensor')
|
sensor_ns = esphomelib_ns.namespace('sensor')
|
||||||
@@ -86,44 +68,81 @@ SensorValueTrigger = sensor_ns.SensorValueTrigger
|
|||||||
RawSensorValueTrigger = sensor_ns.RawSensorValueTrigger
|
RawSensorValueTrigger = sensor_ns.RawSensorValueTrigger
|
||||||
ValueRangeTrigger = sensor_ns.ValueRangeTrigger
|
ValueRangeTrigger = sensor_ns.ValueRangeTrigger
|
||||||
|
|
||||||
|
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent),
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(Sensor),
|
||||||
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict,
|
||||||
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
|
vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int),
|
||||||
|
vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds),
|
||||||
|
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
|
||||||
|
vol.Optional(CONF_ON_VALUE): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(SensorValueTrigger),
|
||||||
|
})]),
|
||||||
|
vol.Optional(CONF_ON_RAW_VALUE): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(RawSensorValueTrigger),
|
||||||
|
})]),
|
||||||
|
vol.Optional(CONF_ON_VALUE_RANGE): vol.All(cv.ensure_list, [vol.All(
|
||||||
|
automation.validate_automation({
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ValueRangeTrigger),
|
||||||
|
vol.Optional(CONF_ABOVE): vol.Coerce(float),
|
||||||
|
vol.Optional(CONF_BELOW): vol.Coerce(float),
|
||||||
|
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))]),
|
||||||
|
})
|
||||||
|
|
||||||
|
SENSOR_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(SENSOR_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
def setup_filter(config):
|
def setup_filter(config):
|
||||||
if CONF_OFFSET in config:
|
if CONF_OFFSET in config:
|
||||||
return OffsetFilter.new(config[CONF_OFFSET])
|
yield OffsetFilter.new(config[CONF_OFFSET])
|
||||||
if CONF_MULTIPLY in config:
|
elif CONF_MULTIPLY in config:
|
||||||
return MultiplyFilter.new(config[CONF_MULTIPLY])
|
yield MultiplyFilter.new(config[CONF_MULTIPLY])
|
||||||
if CONF_FILTER_OUT in config:
|
elif CONF_FILTER_OUT in config:
|
||||||
return FilterOutValueFilter.new(config[CONF_FILTER_OUT])
|
yield FilterOutValueFilter.new(config[CONF_FILTER_OUT])
|
||||||
if CONF_FILTER_NAN in config:
|
elif CONF_FILTER_NAN in config:
|
||||||
return FilterOutNANFilter()
|
yield FilterOutNANFilter.new()
|
||||||
if CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
|
elif CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
|
||||||
conf = config[CONF_SLIDING_WINDOW_MOVING_AVERAGE]
|
conf = config[CONF_SLIDING_WINDOW_MOVING_AVERAGE]
|
||||||
return SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
|
yield SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
|
||||||
if CONF_EXPONENTIAL_MOVING_AVERAGE in config:
|
elif CONF_EXPONENTIAL_MOVING_AVERAGE in config:
|
||||||
conf = config[CONF_EXPONENTIAL_MOVING_AVERAGE]
|
conf = config[CONF_EXPONENTIAL_MOVING_AVERAGE]
|
||||||
return ExponentialMovingAverageFilter.new(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
|
yield ExponentialMovingAverageFilter.new(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
|
||||||
if CONF_LAMBDA in config:
|
elif CONF_LAMBDA in config:
|
||||||
return LambdaFilter.new(process_lambda(config[CONF_LAMBDA], [(float_, 'x')]))
|
lambda_ = None
|
||||||
if CONF_THROTTLE in config:
|
for lambda_ in process_lambda(config[CONF_LAMBDA], [(float_, 'x')]):
|
||||||
return ThrottleFilter.new(config[CONF_THROTTLE])
|
yield None
|
||||||
if CONF_DELTA in config:
|
yield LambdaFilter.new(lambda_)
|
||||||
return DeltaFilter.new(config[CONF_DELTA])
|
elif CONF_THROTTLE in config:
|
||||||
if CONF_OR in config:
|
yield ThrottleFilter.new(config[CONF_THROTTLE])
|
||||||
return OrFilter.new(setup_filters(config[CONF_OR]))
|
elif CONF_DELTA in config:
|
||||||
if CONF_HEARTBEAT in config:
|
yield DeltaFilter.new(config[CONF_DELTA])
|
||||||
return App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
|
elif CONF_OR in config:
|
||||||
if CONF_DEBOUNCE in config:
|
filters = None
|
||||||
return App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
|
for filters in setup_filters(config[CONF_OR]):
|
||||||
if CONF_UNIQUE in config:
|
yield None
|
||||||
return UniqueFilter.new()
|
yield OrFilter.new(filters)
|
||||||
raise ValueError(u"Filter unsupported: {}".format(config))
|
elif CONF_HEARTBEAT in config:
|
||||||
|
yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
|
||||||
|
elif CONF_DEBOUNCE in config:
|
||||||
|
yield App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
|
||||||
|
elif CONF_UNIQUE in config:
|
||||||
|
yield UniqueFilter.new()
|
||||||
|
|
||||||
|
|
||||||
def setup_filters(config):
|
def setup_filters(config):
|
||||||
return ArrayInitializer(*[setup_filter(x) for x in config])
|
filters = []
|
||||||
|
for conf in config:
|
||||||
|
filter = None
|
||||||
|
for filter in setup_filter(conf):
|
||||||
|
yield None
|
||||||
|
filters.append(filter)
|
||||||
|
yield ArrayInitializer(*filters)
|
||||||
|
|
||||||
|
|
||||||
def setup_sensor_core_(sensor_var, mqtt_var, config):
|
def setup_sensor_core_(sensor_var, mqtt_var, config):
|
||||||
|
if CONF_INTERNAL in config:
|
||||||
|
add(sensor_var.set_internal(config[CONF_INTERNAL]))
|
||||||
if CONF_UNIT_OF_MEASUREMENT in config:
|
if CONF_UNIT_OF_MEASUREMENT in config:
|
||||||
add(sensor_var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))
|
add(sensor_var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))
|
||||||
if CONF_ICON in config:
|
if CONF_ICON in config:
|
||||||
@@ -131,23 +150,32 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
|
|||||||
if CONF_ACCURACY_DECIMALS in config:
|
if CONF_ACCURACY_DECIMALS in config:
|
||||||
add(sensor_var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS]))
|
add(sensor_var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS]))
|
||||||
if CONF_FILTERS in config:
|
if CONF_FILTERS in config:
|
||||||
add(sensor_var.set_filters(setup_filters(config[CONF_FILTERS])))
|
filters = None
|
||||||
|
for filters in setup_filters(config[CONF_FILTERS]):
|
||||||
|
yield
|
||||||
|
add(sensor_var.set_filters(filters))
|
||||||
|
|
||||||
for conf in config.get(CONF_ON_VALUE, []):
|
for conf in config.get(CONF_ON_VALUE, []):
|
||||||
rhs = sensor_var.make_value_trigger()
|
rhs = sensor_var.make_value_trigger()
|
||||||
trigger = Pvariable(SensorValueTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, float_, conf)
|
automation.build_automation(trigger, float_, conf)
|
||||||
for conf in config.get(CONF_ON_RAW_VALUE, []):
|
for conf in config.get(CONF_ON_RAW_VALUE, []):
|
||||||
rhs = sensor_var.make_raw_value_trigger()
|
rhs = sensor_var.make_raw_value_trigger()
|
||||||
trigger = Pvariable(RawSensorValueTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
automation.build_automation(trigger, float_, conf)
|
automation.build_automation(trigger, float_, conf)
|
||||||
for conf in config.get(CONF_ON_VALUE_RANGE, []):
|
for conf in config.get(CONF_ON_VALUE_RANGE, []):
|
||||||
rhs = sensor_var.make_value_range_trigger()
|
rhs = sensor_var.make_value_range_trigger()
|
||||||
trigger = Pvariable(ValueRangeTrigger, conf[CONF_TRIGGER_ID], rhs)
|
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||||
if CONF_ABOVE in conf:
|
if CONF_ABOVE in conf:
|
||||||
trigger.set_min(templatable(conf[CONF_ABOVE], float_, float_))
|
template_ = None
|
||||||
|
for template_ in templatable(conf[CONF_ABOVE], float_, float_):
|
||||||
|
yield
|
||||||
|
trigger.set_min(template_)
|
||||||
if CONF_BELOW in conf:
|
if CONF_BELOW in conf:
|
||||||
trigger.set_max(templatable(conf[CONF_BELOW], float_, float_))
|
template_ = None
|
||||||
|
for template_ in templatable(conf[CONF_BELOW], float_, float_):
|
||||||
|
yield
|
||||||
|
trigger.set_max(template_)
|
||||||
automation.build_automation(trigger, float_, conf)
|
automation.build_automation(trigger, float_, conf)
|
||||||
|
|
||||||
if CONF_EXPIRE_AFTER in config:
|
if CONF_EXPIRE_AFTER in config:
|
||||||
@@ -159,18 +187,16 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
|
|||||||
|
|
||||||
|
|
||||||
def setup_sensor(sensor_obj, mqtt_obj, config):
|
def setup_sensor(sensor_obj, mqtt_obj, config):
|
||||||
sensor_var = Pvariable(Sensor, config[CONF_ID], sensor_obj, has_side_effects=False)
|
sensor_var = Pvariable(config[CONF_ID], sensor_obj, has_side_effects=False)
|
||||||
mqtt_var = Pvariable(MQTTSensorComponent, config[CONF_MQTT_ID], mqtt_obj,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||||
has_side_effects=False)
|
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
|
||||||
setup_sensor_core_(sensor_var, mqtt_var, config)
|
|
||||||
|
|
||||||
|
|
||||||
def register_sensor(var, config):
|
def register_sensor(var, config):
|
||||||
sensor_var = Pvariable(Sensor, config[CONF_ID], var, has_side_effects=True)
|
sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
|
||||||
rhs = App.register_sensor(sensor_var)
|
rhs = App.register_sensor(sensor_var)
|
||||||
mqtt_var = Pvariable(MQTTSensorComponent, config[CONF_MQTT_ID], rhs,
|
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
|
||||||
has_side_effects=True)
|
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
|
||||||
setup_sensor_core_(sensor_var, mqtt_var, config)
|
|
||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_SENSOR'
|
BUILD_FLAGS = '-DUSE_SENSOR'
|
||||||
|
|||||||
@@ -14,20 +14,31 @@ ATTENUATION_MODES = {
|
|||||||
'11db': global_ns.ADC_11db,
|
'11db': global_ns.ADC_11db,
|
||||||
}
|
}
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('adc', CONF_MAKE_ID): cv.register_variable_id,
|
def validate_adc_pin(value):
|
||||||
vol.Required(CONF_PIN): pins.analog_pin,
|
vcc = str(value).upper()
|
||||||
vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES)),
|
if vcc == 'VCC':
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
return cv.only_on_esp8266(vcc)
|
||||||
}).extend(sensor.SENSOR_SCHEMA.schema)
|
return pins.analog_pin(value)
|
||||||
|
|
||||||
|
|
||||||
MakeADCSensor = Application.MakeADCSensor
|
MakeADCSensor = Application.MakeADCSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeADCSensor),
|
||||||
|
vol.Required(CONF_PIN): validate_adc_pin,
|
||||||
|
vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES)),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_adc_sensor(config[CONF_NAME], config[CONF_PIN],
|
pin = config[CONF_PIN]
|
||||||
|
if pin == 'VCC':
|
||||||
|
pin = 0
|
||||||
|
rhs = App.make_adc_sensor(config[CONF_NAME], pin,
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
make = variable(MakeADCSensor, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
adc = make.Padc
|
adc = make.Padc
|
||||||
if CONF_ATTENUATION in config:
|
if CONF_ATTENUATION in config:
|
||||||
add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]]))
|
add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]]))
|
||||||
@@ -35,3 +46,9 @@ def to_code(config):
|
|||||||
|
|
||||||
|
|
||||||
BUILD_FLAGS = '-DUSE_ADC_SENSOR'
|
BUILD_FLAGS = '-DUSE_ADC_SENSOR'
|
||||||
|
|
||||||
|
|
||||||
|
def required_build_flags(config):
|
||||||
|
if config[CONF_PIN] == 'VCC':
|
||||||
|
return '-DUSE_ADC_SENSOR_VCC'
|
||||||
|
return None
|
||||||
|
|||||||
@@ -45,17 +45,18 @@ def validate_mux(value):
|
|||||||
return cv.one_of(*MUX)(value)
|
return cv.one_of(*MUX)(value)
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
cv.GenerateID('ads1115_sensor'): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_MULTIPLEXER): validate_mux,
|
vol.Required(CONF_MULTIPLEXER): validate_mux,
|
||||||
vol.Required(CONF_GAIN): validate_gain,
|
vol.Required(CONF_GAIN): validate_gain,
|
||||||
vol.Optional(CONF_ADS1115_ID): cv.variable_id,
|
cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component),
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
}).extend(sensor.SENSOR_SCHEMA.schema)
|
}))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
hub = get_variable(config.get(CONF_ADS1115_ID), ADS1115Component)
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_ADS1115_ID]):
|
||||||
|
yield
|
||||||
|
|
||||||
mux = MUX[config[CONF_MULTIPLEXER]]
|
mux = MUX[config[CONF_MULTIPLEXER]]
|
||||||
gain = GAIN[config[CONF_GAIN]]
|
gain = GAIN[config[CONF_GAIN]]
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ BH1750_RESOLUTIONS = {
|
|||||||
0.5: sensor.sensor_ns.BH1750_RESOLUTION_0P5_LX,
|
0.5: sensor.sensor_ns.BH1750_RESOLUTION_0P5_LX,
|
||||||
}
|
}
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
MakeBH1750Sensor = Application.MakeBH1750Sensor
|
||||||
cv.GenerateID('bh1750_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBH1750Sensor),
|
||||||
vol.Optional(CONF_ADDRESS, default=0x23): cv.i2c_address,
|
vol.Optional(CONF_ADDRESS, default=0x23): cv.i2c_address,
|
||||||
vol.Optional(CONF_RESOLUTION): vol.All(cv.positive_float, cv.one_of(*BH1750_RESOLUTIONS)),
|
vol.Optional(CONF_RESOLUTION): vol.All(cv.positive_float, cv.one_of(*BH1750_RESOLUTIONS)),
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
}).extend(sensor.SENSOR_SCHEMA.schema)
|
}))
|
||||||
|
|
||||||
MakeBH1750Sensor = Application.MakeBH1750Sensor
|
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_bh1750_sensor(config[CONF_NAME], config[CONF_ADDRESS],
|
rhs = App.make_bh1750_sensor(config[CONF_NAME], config[CONF_ADDRESS],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
make_bh1750 = variable(MakeBH1750Sensor, config[CONF_MAKE_ID], rhs)
|
make_bh1750 = variable(config[CONF_MAKE_ID], rhs)
|
||||||
bh1750 = make_bh1750.Pbh1750
|
bh1750 = make_bh1750.Pbh1750
|
||||||
if CONF_RESOLUTION in config:
|
if CONF_RESOLUTION in config:
|
||||||
add(bh1750.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]))
|
add(bh1750.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]))
|
||||||
|
|||||||
23
esphomeyaml/components/sensor/ble_rssi.py
Normal file
23
esphomeyaml/components/sensor/ble_rssi.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \
|
||||||
|
make_address_array
|
||||||
|
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME
|
||||||
|
from esphomeyaml.helpers import get_variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['esp32_ble_tracker']
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_MAC_ADDRESS): cv.mac_address,
|
||||||
|
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker)
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = None
|
||||||
|
for hub in get_variable(config[CONF_ESP32_BLE_ID]):
|
||||||
|
yield
|
||||||
|
rhs = hub.make_rssi_sensor(config[CONF_NAME], make_address_array(config[CONF_MAC_ADDRESS]))
|
||||||
|
sensor.register_sensor(rhs, config)
|
||||||
@@ -29,18 +29,18 @@ BME280_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
||||||
})
|
})
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('bme280', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address,
|
|
||||||
vol.Required(CONF_TEMPERATURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_PRESSURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)),
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeBME280Sensor = Application.MakeBME280Sensor
|
MakeBME280Sensor = Application.MakeBME280Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME280Sensor),
|
||||||
|
vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address,
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_PRESSURE): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_bme280_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_bme280_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
@@ -48,7 +48,7 @@ def to_code(config):
|
|||||||
config[CONF_HUMIDITY][CONF_NAME],
|
config[CONF_HUMIDITY][CONF_NAME],
|
||||||
config[CONF_ADDRESS],
|
config[CONF_ADDRESS],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
make = variable(MakeBME280Sensor, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
bme280 = make.Pbme280
|
bme280 = make.Pbme280
|
||||||
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
||||||
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import esphomeyaml.config_validation as cv
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import core
|
||||||
from esphomeyaml.components import sensor
|
from esphomeyaml.components import sensor
|
||||||
from esphomeyaml.const import CONF_ADDRESS, CONF_GAS_RESISTANCE, CONF_HUMIDITY, CONF_IIR_FILTER, \
|
from esphomeyaml.const import CONF_ADDRESS, CONF_GAS_RESISTANCE, CONF_HUMIDITY, CONF_IIR_FILTER, \
|
||||||
CONF_MAKE_ID, CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, \
|
CONF_MAKE_ID, CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, \
|
||||||
CONF_UPDATE_INTERVAL
|
CONF_UPDATE_INTERVAL, CONF_HEATER, CONF_DURATION
|
||||||
from esphomeyaml.helpers import App, Application, add, variable
|
from esphomeyaml.helpers import App, Application, add, variable
|
||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
@@ -33,20 +34,24 @@ BME680_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
||||||
})
|
})
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('bme680', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Optional(CONF_ADDRESS, default=0x76): cv.i2c_address,
|
|
||||||
vol.Required(CONF_TEMPERATURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_PRESSURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_GAS_RESISTANCE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)),
|
|
||||||
# TODO: Heater
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeBME680Sensor = Application.MakeBME680Sensor
|
MakeBME680Sensor = Application.MakeBME680Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME680Sensor),
|
||||||
|
vol.Optional(CONF_ADDRESS, default=0x76): cv.i2c_address,
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_PRESSURE): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_GAS_RESISTANCE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)),
|
||||||
|
vol.Optional(CONF_HEATER): vol.Any(None, vol.All(vol.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)))
|
||||||
|
}, cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION)))),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_bme680_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_bme680_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
@@ -55,7 +60,7 @@ def to_code(config):
|
|||||||
config[CONF_GAS_RESISTANCE][CONF_NAME],
|
config[CONF_GAS_RESISTANCE][CONF_NAME],
|
||||||
config[CONF_ADDRESS],
|
config[CONF_ADDRESS],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
make = variable(MakeBME680Sensor, config[CONF_MAKE_ID], rhs)
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
bme680 = make.Pbme680
|
bme680 = make.Pbme680
|
||||||
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
||||||
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
||||||
@@ -69,6 +74,12 @@ def to_code(config):
|
|||||||
if CONF_IIR_FILTER in config:
|
if CONF_IIR_FILTER in config:
|
||||||
constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
|
constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
|
||||||
add(bme680.set_iir_filter(constant))
|
add(bme680.set_iir_filter(constant))
|
||||||
|
if CONF_HEATER in config:
|
||||||
|
conf = config[CONF_HEATER]
|
||||||
|
if not conf:
|
||||||
|
add(bme680.set_heater(0, 0))
|
||||||
|
else:
|
||||||
|
add(bme680.set_heater(conf[CONF_TEMPERATURE], conf[CONF_DURATION]))
|
||||||
|
|
||||||
sensor.setup_sensor(bme680.Pget_temperature_sensor(), make.Pmqtt_temperature,
|
sensor.setup_sensor(bme680.Pget_temperature_sensor(), make.Pmqtt_temperature,
|
||||||
config[CONF_TEMPERATURE])
|
config[CONF_TEMPERATURE])
|
||||||
|
|||||||
@@ -4,26 +4,26 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml.components import sensor
|
from esphomeyaml.components import sensor
|
||||||
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \
|
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \
|
||||||
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||||
from esphomeyaml.helpers import App, HexIntLiteral, add, variable, Application
|
from esphomeyaml.helpers import App, Application, HexIntLiteral, add, variable
|
||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('bmp085_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_PRESSURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeBMP085Sensor = Application.MakeBMP085Sensor
|
MakeBMP085Sensor = Application.MakeBMP085Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBMP085Sensor),
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_PRESSURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_bmp085_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_bmp085_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
config[CONF_PRESSURE][CONF_NAME],
|
config[CONF_PRESSURE][CONF_NAME],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
bmp = variable(MakeBMP085Sensor, config[CONF_MAKE_ID], rhs)
|
bmp = variable(config[CONF_MAKE_ID], rhs)
|
||||||
if CONF_ADDRESS in config:
|
if CONF_ADDRESS in config:
|
||||||
add(bmp.Pbmp.set_address(HexIntLiteral(config[CONF_ADDRESS])))
|
add(bmp.Pbmp.set_address(HexIntLiteral(config[CONF_ADDRESS])))
|
||||||
|
|
||||||
|
|||||||
67
esphomeyaml/components/sensor/bmp280.py
Normal file
67
esphomeyaml/components/sensor/bmp280.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_IIR_FILTER, CONF_MAKE_ID, \
|
||||||
|
CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||||
|
from esphomeyaml.helpers import App, Application, add, variable
|
||||||
|
|
||||||
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
OVERSAMPLING_OPTIONS = {
|
||||||
|
'NONE': sensor.sensor_ns.BMP280_OVERSAMPLING_NONE,
|
||||||
|
'1X': sensor.sensor_ns.BMP280_OVERSAMPLING_1X,
|
||||||
|
'2X': sensor.sensor_ns.BMP280_OVERSAMPLING_2X,
|
||||||
|
'4X': sensor.sensor_ns.BMP280_OVERSAMPLING_4X,
|
||||||
|
'8X': sensor.sensor_ns.BMP280_OVERSAMPLING_8X,
|
||||||
|
'16X': sensor.sensor_ns.BMP280_OVERSAMPLING_16X,
|
||||||
|
}
|
||||||
|
|
||||||
|
IIR_FILTER_OPTIONS = {
|
||||||
|
'OFF': sensor.sensor_ns.BMP280_IIR_FILTER_OFF,
|
||||||
|
'2X': sensor.sensor_ns.BMP280_IIR_FILTER_2X,
|
||||||
|
'4X': sensor.sensor_ns.BMP280_IIR_FILTER_4X,
|
||||||
|
'8X': sensor.sensor_ns.BMP280_IIR_FILTER_8X,
|
||||||
|
'16X': sensor.sensor_ns.BMP280_IIR_FILTER_16X,
|
||||||
|
}
|
||||||
|
|
||||||
|
BMP280_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
||||||
|
})
|
||||||
|
|
||||||
|
MakeBMP280Sensor = Application.MakeBMP280Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBMP280Sensor),
|
||||||
|
vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address,
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(BMP280_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_PRESSURE): cv.nameable(BMP280_OVERSAMPLING_SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_bmp280_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
|
config[CONF_PRESSURE][CONF_NAME],
|
||||||
|
config[CONF_ADDRESS],
|
||||||
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
bmp280 = make.Pbmp280
|
||||||
|
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
||||||
|
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
||||||
|
add(bmp280.set_temperature_oversampling(constant))
|
||||||
|
if CONF_OVERSAMPLING in config[CONF_PRESSURE]:
|
||||||
|
constant = OVERSAMPLING_OPTIONS[config[CONF_PRESSURE][CONF_OVERSAMPLING]]
|
||||||
|
add(bmp280.set_pressure_oversampling(constant))
|
||||||
|
if CONF_IIR_FILTER in config:
|
||||||
|
constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
|
||||||
|
add(bmp280.set_iir_filter(constant))
|
||||||
|
|
||||||
|
sensor.setup_sensor(bmp280.Pget_temperature_sensor(), make.Pmqtt_temperature,
|
||||||
|
config[CONF_TEMPERATURE])
|
||||||
|
sensor.setup_sensor(bmp280.Pget_pressure_sensor(), make.Pmqtt_pressure,
|
||||||
|
config[CONF_PRESSURE])
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_BMP280'
|
||||||
@@ -4,30 +4,27 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml.components import sensor
|
from esphomeyaml.components import sensor
|
||||||
from esphomeyaml.components.dallas import DallasComponent
|
from esphomeyaml.components.dallas import DallasComponent
|
||||||
from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \
|
from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \
|
||||||
CONF_RESOLUTION, CONF_UPDATE_INTERVAL
|
CONF_RESOLUTION
|
||||||
from esphomeyaml.helpers import HexIntLiteral, get_variable
|
from esphomeyaml.helpers import HexIntLiteral, get_variable
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int,
|
vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int,
|
||||||
vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int,
|
vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int,
|
||||||
vol.Optional(CONF_DALLAS_ID): cv.variable_id,
|
cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent),
|
||||||
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=8, max=12)),
|
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=9, max=12)),
|
||||||
}).extend(sensor.SENSOR_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
|
}), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
hub = get_variable(config.get(CONF_DALLAS_ID), DallasComponent)
|
hub = None
|
||||||
update_interval = config.get(CONF_UPDATE_INTERVAL)
|
for hub in get_variable(config[CONF_DALLAS_ID]):
|
||||||
if CONF_RESOLUTION in config and update_interval is None:
|
yield
|
||||||
update_interval = 10000
|
|
||||||
|
|
||||||
if CONF_ADDRESS in config:
|
if CONF_ADDRESS in config:
|
||||||
address = HexIntLiteral(config[CONF_ADDRESS])
|
address = HexIntLiteral(config[CONF_ADDRESS])
|
||||||
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, update_interval,
|
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, config.get(CONF_RESOLUTION))
|
||||||
config.get(CONF_RESOLUTION))
|
|
||||||
else:
|
else:
|
||||||
rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX],
|
rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX],
|
||||||
update_interval, config.get(CONF_RESOLUTION))
|
config.get(CONF_RESOLUTION))
|
||||||
sensor.register_sensor(rhs, config)
|
sensor.register_sensor(rhs, config)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from esphomeyaml.components import sensor
|
|||||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_MODEL, CONF_NAME, CONF_PIN, \
|
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_MODEL, CONF_NAME, CONF_PIN, \
|
||||||
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||||
from esphomeyaml.helpers import App, Application, add, gpio_output_pin_expression, variable
|
from esphomeyaml.helpers import App, Application, add, gpio_output_pin_expression, variable
|
||||||
from esphomeyaml.pins import GPIO_OUTPUT_PIN_SCHEMA
|
from esphomeyaml.pins import gpio_output_pin_schema
|
||||||
|
|
||||||
DHT_MODELS = {
|
DHT_MODELS = {
|
||||||
'AUTO_DETECT': sensor.sensor_ns.DHT_MODEL_AUTO_DETECT,
|
'AUTO_DETECT': sensor.sensor_ns.DHT_MODEL_AUTO_DETECT,
|
||||||
@@ -15,24 +15,26 @@ DHT_MODELS = {
|
|||||||
'RHT03': sensor.sensor_ns.DHT_MODEL_RHT03,
|
'RHT03': sensor.sensor_ns.DHT_MODEL_RHT03,
|
||||||
}
|
}
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('dht_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_PIN): GPIO_OUTPUT_PIN_SCHEMA,
|
|
||||||
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_MODEL): vol.All(vol.Upper, cv.one_of(*DHT_MODELS)),
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeDHTSensor = Application.MakeDHTSensor
|
MakeDHTSensor = Application.MakeDHTSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHTSensor),
|
||||||
|
vol.Required(CONF_PIN): gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_MODEL): vol.All(vol.Upper, cv.one_of(*DHT_MODELS)),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
pin = gpio_output_pin_expression(config[CONF_PIN])
|
pin = None
|
||||||
|
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||||
|
yield
|
||||||
rhs = App.make_dht_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_dht_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
config[CONF_HUMIDITY][CONF_NAME],
|
config[CONF_HUMIDITY][CONF_NAME],
|
||||||
pin, config.get(CONF_UPDATE_INTERVAL))
|
pin, config.get(CONF_UPDATE_INTERVAL))
|
||||||
dht = variable(MakeDHTSensor, config[CONF_MAKE_ID], rhs)
|
dht = variable(config[CONF_MAKE_ID], rhs)
|
||||||
if CONF_MODEL in config:
|
if CONF_MODEL in config:
|
||||||
constant = DHT_MODELS[config[CONF_MODEL]]
|
constant = DHT_MODELS[config[CONF_MODEL]]
|
||||||
add(dht.Pdht.set_dht_model(constant))
|
add(dht.Pdht.set_dht_model(constant))
|
||||||
|
|||||||
@@ -8,25 +8,25 @@ from esphomeyaml.helpers import App, Application, variable
|
|||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('dht_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeDHT12Sensor = Application.MakeDHT12Sensor
|
MakeDHT12Sensor = Application.MakeDHT12Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHT12Sensor),
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_dht12_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_dht12_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
config[CONF_HUMIDITY][CONF_NAME],
|
config[CONF_HUMIDITY][CONF_NAME],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
dht = variable(MakeDHT12Sensor, config[CONF_MAKE_ID], rhs)
|
dht = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
|
||||||
sensor.setup_sensor(dht.Pdht.Pget_temperature_sensor(), dht.Pmqtt_temperature,
|
sensor.setup_sensor(dht.Pdht12.Pget_temperature_sensor(), dht.Pmqtt_temperature,
|
||||||
config[CONF_TEMPERATURE])
|
config[CONF_TEMPERATURE])
|
||||||
sensor.setup_sensor(dht.Pdht.Pget_humidity_sensor(), dht.Pmqtt_humidity,
|
sensor.setup_sensor(dht.Pdht12.Pget_humidity_sensor(), dht.Pmqtt_humidity,
|
||||||
config[CONF_HUMIDITY])
|
config[CONF_HUMIDITY])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
28
esphomeyaml/components/sensor/duty_cycle.py
Normal file
28
esphomeyaml/components/sensor/duty_cycle.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL
|
||||||
|
from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, variable
|
||||||
|
|
||||||
|
MakeDutyCycleSensor = Application.MakeDutyCycleSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDutyCycleSensor),
|
||||||
|
vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
pin = None
|
||||||
|
for pin in gpio_input_pin_expression(config[CONF_PIN]):
|
||||||
|
yield
|
||||||
|
rhs = App.make_duty_cycle_sensor(config[CONF_NAME], pin,
|
||||||
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
sensor.setup_sensor(make.Pduty, make.Pmqtt, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_DUTY_CYCLE_SENSOR'
|
||||||
24
esphomeyaml/components/sensor/esp32_hall.py
Normal file
24
esphomeyaml/components/sensor/esp32_hall.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32
|
||||||
|
from esphomeyaml.helpers import App, Application, variable
|
||||||
|
|
||||||
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
|
|
||||||
|
MakeESP32HallSensor = Application.MakeESP32HallSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeESP32HallSensor),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_esp32_hall_sensor(config[CONF_NAME], config.get(CONF_UPDATE_INTERVAL))
|
||||||
|
make = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
sensor.setup_sensor(make.Phall, make.Pmqtt, config)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_ESP32_HALL_SENSOR'
|
||||||
@@ -4,27 +4,28 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml.components import sensor
|
from esphomeyaml.components import sensor
|
||||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||||
CONF_UPDATE_INTERVAL
|
CONF_UPDATE_INTERVAL
|
||||||
from esphomeyaml.helpers import App, variable, Application
|
from esphomeyaml.helpers import App, Application, variable
|
||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('hdc1080_sensor', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeHDC1080Sensor = Application.MakeHDC1080Sensor
|
MakeHDC1080Sensor = Application.MakeHDC1080Sensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHDC1080Sensor),
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_hdc1080_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_hdc1080_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
config[CONF_HUMIDITY][CONF_NAME],
|
config[CONF_HUMIDITY][CONF_NAME],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
hdc1080 = variable(MakeHDC1080Sensor, config[CONF_MAKE_ID], rhs)
|
hdc1080 = variable(config[CONF_MAKE_ID], rhs)
|
||||||
|
|
||||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(), hdc1080.Pmqtt_temperature,
|
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(),
|
||||||
|
hdc1080.Pmqtt_temperature,
|
||||||
config[CONF_TEMPERATURE])
|
config[CONF_TEMPERATURE])
|
||||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_humidity_sensor(), hdc1080.Pmqtt_humidity,
|
sensor.setup_sensor(hdc1080.Phdc1080.Pget_humidity_sensor(), hdc1080.Pmqtt_humidity,
|
||||||
config[CONF_HUMIDITY])
|
config[CONF_HUMIDITY])
|
||||||
|
|||||||
57
esphomeyaml/components/sensor/hlw8012.py
Normal file
57
esphomeyaml/components/sensor/hlw8012.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml import pins
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.const import CONF_CF1_PIN, CONF_CF_PIN, CONF_CHANGE_MODE_EVERY, CONF_CURRENT, \
|
||||||
|
CONF_CURRENT_RESISTOR, CONF_ID, CONF_NAME, CONF_POWER, CONF_SEL_PIN, CONF_UPDATE_INTERVAL, \
|
||||||
|
CONF_VOLTAGE, CONF_VOLTAGE_DIVIDER
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add, gpio_output_pin_expression
|
||||||
|
|
||||||
|
HLW8012Component = sensor.sensor_ns.HLW8012Component
|
||||||
|
HLW8012VoltageSensor = sensor.sensor_ns.HLW8012VoltageSensor
|
||||||
|
HLW8012CurrentSensor = sensor.sensor_ns.HLW8012CurrentSensor
|
||||||
|
HLW8012PowerSensor = sensor.sensor_ns.HLW8012PowerSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(HLW8012Component),
|
||||||
|
vol.Required(CONF_SEL_PIN): pins.gpio_output_pin_schema,
|
||||||
|
vol.Required(CONF_CF_PIN): pins.input_pin,
|
||||||
|
vol.Required(CONF_CF1_PIN): pins.input_pin,
|
||||||
|
|
||||||
|
vol.Optional(CONF_VOLTAGE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_CURRENT): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_POWER): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
|
||||||
|
vol.Optional(CONF_CURRENT_RESISTOR): cv.resistance,
|
||||||
|
vol.Optional(CONF_VOLTAGE_DIVIDER): cv.positive_float,
|
||||||
|
vol.Optional(CONF_CHANGE_MODE_EVERY): vol.All(cv.uint32_t, vol.Range(min=1)),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
}), cv.has_at_least_one_key(CONF_VOLTAGE, CONF_CURRENT, CONF_POWER))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
sel = None
|
||||||
|
for sel in gpio_output_pin_expression(config[CONF_SEL_PIN]):
|
||||||
|
yield
|
||||||
|
|
||||||
|
rhs = App.make_hlw8012(sel, config[CONF_CF_PIN], config[CONF_CF1_PIN],
|
||||||
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
|
hlw = Pvariable(config[CONF_ID], rhs)
|
||||||
|
|
||||||
|
if CONF_VOLTAGE in config:
|
||||||
|
conf = config[CONF_VOLTAGE]
|
||||||
|
sensor.register_sensor(hlw.make_voltage_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_CURRENT in config:
|
||||||
|
conf = config[CONF_CURRENT]
|
||||||
|
sensor.register_sensor(hlw.make_current_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_POWER in config:
|
||||||
|
conf = config[CONF_POWER]
|
||||||
|
sensor.register_sensor(hlw.make_power_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_CURRENT_RESISTOR in config:
|
||||||
|
add(hlw.set_current_resistor(config[CONF_CURRENT_RESISTOR]))
|
||||||
|
if CONF_CHANGE_MODE_EVERY in config:
|
||||||
|
add(hlw.set_change_mode_every(config[CONF_CHANGE_MODE_EVERY]))
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_HLW8012'
|
||||||
73
esphomeyaml/components/sensor/hmc5883l.py
Normal file
73
esphomeyaml/components/sensor/hmc5883l.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import esphomeyaml.config_validation as cv
|
||||||
|
from esphomeyaml.components import sensor
|
||||||
|
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, CONF_RANGE
|
||||||
|
from esphomeyaml.helpers import App, Pvariable, add
|
||||||
|
|
||||||
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
CONF_FIELD_STRENGTH_X = 'field_strength_x'
|
||||||
|
CONF_FIELD_STRENGTH_Y = 'field_strength_y'
|
||||||
|
CONF_FIELD_STRENGTH_Z = 'field_strength_z'
|
||||||
|
CONF_HEADING = 'heading'
|
||||||
|
|
||||||
|
HMC5883LComponent = sensor.sensor_ns.HMC5883LComponent
|
||||||
|
HMC5883LFieldStrengthSensor = sensor.sensor_ns.HMC5883LFieldStrengthSensor
|
||||||
|
HMC5883LHeadingSensor = sensor.sensor_ns.HMC5883LHeadingSensor
|
||||||
|
|
||||||
|
HMC5883L_RANGES = {
|
||||||
|
88: sensor.sensor_ns.HMC5883L_RANGE_88_UT,
|
||||||
|
130: sensor.sensor_ns.HMC5883L_RANGE_130_UT,
|
||||||
|
190: sensor.sensor_ns.HMC5883L_RANGE_190_UT,
|
||||||
|
250: sensor.sensor_ns.HMC5883L_RANGE_250_UT,
|
||||||
|
400: sensor.sensor_ns.HMC5883L_RANGE_400_UT,
|
||||||
|
470: sensor.sensor_ns.HMC5883L_RANGE_470_UT,
|
||||||
|
560: sensor.sensor_ns.HMC5883L_RANGE_560_UT,
|
||||||
|
810: sensor.sensor_ns.HMC5883L_RANGE_810_UT,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_range(value):
|
||||||
|
value = cv.string(value)
|
||||||
|
if value.endswith(u'µT') or value.endswith('uT'):
|
||||||
|
value = value[:-2]
|
||||||
|
return cv.one_of(*HMC5883L_RANGES)(int(value))
|
||||||
|
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_variable_id(HMC5883LComponent),
|
||||||
|
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
vol.Optional(CONF_FIELD_STRENGTH_X): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_FIELD_STRENGTH_Y): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_FIELD_STRENGTH_Z): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_HEADING): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
vol.Optional(CONF_RANGE): validate_range,
|
||||||
|
}), cv.has_at_least_one_key(CONF_FIELD_STRENGTH_X, CONF_FIELD_STRENGTH_Y, CONF_FIELD_STRENGTH_Z,
|
||||||
|
CONF_HEADING))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
rhs = App.make_hmc5883l(config.get(CONF_UPDATE_INTERVAL))
|
||||||
|
hmc = Pvariable(config[CONF_ID], rhs)
|
||||||
|
if CONF_ADDRESS in config:
|
||||||
|
add(hmc.set_address(config[CONF_ADDRESS]))
|
||||||
|
if CONF_RANGE in config:
|
||||||
|
add(hmc.set_range(HMC5883L_RANGES[config[CONF_RANGE]]))
|
||||||
|
if CONF_FIELD_STRENGTH_X in config:
|
||||||
|
conf = config[CONF_FIELD_STRENGTH_X]
|
||||||
|
sensor.register_sensor(hmc.Pmake_x_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_FIELD_STRENGTH_Y in config:
|
||||||
|
conf = config[CONF_FIELD_STRENGTH_Y]
|
||||||
|
sensor.register_sensor(hmc.Pmake_y_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_FIELD_STRENGTH_Z in config:
|
||||||
|
conf = config[CONF_FIELD_STRENGTH_Z]
|
||||||
|
sensor.register_sensor(hmc.Pmake_z_sensor(conf[CONF_NAME]), conf)
|
||||||
|
if CONF_HEADING in config:
|
||||||
|
conf = config[CONF_HEADING]
|
||||||
|
sensor.register_sensor(hmc.Pmake_heading_sensor(conf[CONF_NAME]), conf)
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_FLAGS = '-DUSE_HMC5883L'
|
||||||
@@ -4,25 +4,25 @@ import esphomeyaml.config_validation as cv
|
|||||||
from esphomeyaml.components import sensor
|
from esphomeyaml.components import sensor
|
||||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||||
CONF_UPDATE_INTERVAL
|
CONF_UPDATE_INTERVAL
|
||||||
from esphomeyaml.helpers import App, variable, Application
|
from esphomeyaml.helpers import App, Application, variable
|
||||||
|
|
||||||
DEPENDENCIES = ['i2c']
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
|
||||||
cv.GenerateID('htu21d', CONF_MAKE_ID): cv.register_variable_id,
|
|
||||||
vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA,
|
|
||||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
|
||||||
})
|
|
||||||
|
|
||||||
MakeHTU21DSensor = Application.MakeHTU21DSensor
|
MakeHTU21DSensor = Application.MakeHTU21DSensor
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||||
|
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHTU21DSensor),
|
||||||
|
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
rhs = App.make_htu21d_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
rhs = App.make_htu21d_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||||
config[CONF_HUMIDITY][CONF_NAME],
|
config[CONF_HUMIDITY][CONF_NAME],
|
||||||
config.get(CONF_UPDATE_INTERVAL))
|
config.get(CONF_UPDATE_INTERVAL))
|
||||||
htu21d = variable(MakeHTU21DSensor, config[CONF_MAKE_ID], rhs)
|
htu21d = variable(config[CONF_MAKE_ID], rhs)
|
||||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_temperature_sensor(), htu21d.Pmqtt_temperature,
|
sensor.setup_sensor(htu21d.Phtu21d.Pget_temperature_sensor(), htu21d.Pmqtt_temperature,
|
||||||
config[CONF_TEMPERATURE])
|
config[CONF_TEMPERATURE])
|
||||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_humidity_sensor(), htu21d.Pmqtt_humidity,
|
sensor.setup_sensor(htu21d.Phtu21d.Pget_humidity_sensor(), htu21d.Pmqtt_humidity,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user