mirror of
https://github.com/esphome/esphome.git
synced 2025-11-01 15:41:52 +00:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
d88634b196 | ||
|
|
976627eb38 | ||
|
|
5b995c0692 | ||
|
|
2d4b475951 | ||
|
|
93d962dd43 | ||
|
|
2e7d8540fb | ||
|
|
677fe8bacf | ||
|
|
94d7ac4ef0 | ||
|
|
ebb6d0d464 | ||
|
|
e8fe653140 | ||
|
|
374ea7044c | ||
|
|
061798839d | ||
|
|
b9b09a1763 | ||
|
|
61b3ead2df | ||
|
|
48e42cf478 | ||
|
|
1a9ff55a61 | ||
|
|
e04285581c | ||
|
|
9af30061cb | ||
|
|
19929fafa5 | ||
|
|
3a9febaf85 | ||
|
|
ebb5991889 | ||
|
|
f18f8444c7 | ||
|
|
10607f2a51 |
@@ -106,3 +106,4 @@ venv.bak/
|
||||
config/
|
||||
examples/
|
||||
Dockerfile
|
||||
.git/
|
||||
|
||||
131
.gitlab-ci.yml
Normal file
131
.gitlab-ci.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
# Based on https://gitlab.com/hassio-addons/addon-node-red/blob/master/.gitlab-ci.yml
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- build
|
||||
- deploy
|
||||
|
||||
.lint: &lint
|
||||
stage: lint
|
||||
tags:
|
||||
- python2.7
|
||||
- esphomeyaml-lint
|
||||
|
||||
.hassio-builder: &hassio-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
|
||||
|
||||
.build: &build
|
||||
<<: *hassio-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"
|
||||
|
||||
# Generic deploy template
|
||||
.deploy: &deploy
|
||||
<<: *hassio-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}" \
|
||||
"ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${version}"
|
||||
- |
|
||||
docker tag \
|
||||
"ottowinter/esphomeyaml-hassio-${ADDON_ARCH}:${version}" \
|
||||
"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:armhf:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: armhf
|
||||
|
||||
#build:aarch64:
|
||||
# <<: *build
|
||||
# variables:
|
||||
# ADDON_ARCH: aarch64
|
||||
|
||||
build:i386:
|
||||
<<: *build
|
||||
variables:
|
||||
ADDON_ARCH: i386
|
||||
|
||||
build:amd64:
|
||||
<<: *build
|
||||
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).+@/
|
||||
|
||||
@@ -4,7 +4,7 @@ python:
|
||||
- "2.7"
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install flake8==3.5.0 pylint==1.8.4
|
||||
- pip install tornado esptool flake8==3.5.0 pylint==1.8.4
|
||||
script:
|
||||
- flake8 esphomeyaml
|
||||
- pylint esphomeyaml
|
||||
|
||||
@@ -7,7 +7,8 @@ VOLUME /config
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY requirements.txt /usr/src/app/
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install --no-cache-dir -r requirements.txt && \
|
||||
pip install --no-cache-dir tornado esptool
|
||||
|
||||
COPY docker/platformio.ini /usr/src/app/
|
||||
RUN platformio settings set enable_telemetry No && \
|
||||
|
||||
4
MANIFEST.in
Normal file
4
MANIFEST.in
Normal file
@@ -0,0 +1,4 @@
|
||||
include README.md
|
||||
include esphomeyaml/dashboard/templates/index.html
|
||||
include esphomeyaml/dashboard/static/materialize-stepper.min.css
|
||||
include esphomeyaml/dashboard/static/materialize-stepper.min.js
|
||||
20
docker/Dockerfile.aarch64
Normal file
20
docker/Dockerfile.aarch64
Normal file
@@ -0,0 +1,20 @@
|
||||
# Dockerfile for aarch64 version of HassIO add-on
|
||||
FROM homeassistant/aarch64-base:latest
|
||||
|
||||
RUN apk add --no-cache \
|
||||
python2 \
|
||||
py2-pip \
|
||||
git \
|
||||
openssh \
|
||||
libc6-compat \
|
||||
&& \
|
||||
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 .
|
||||
|
||||
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||
19
docker/Dockerfile.amd64
Normal file
19
docker/Dockerfile.amd64
Normal file
@@ -0,0 +1,19 @@
|
||||
# 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 \
|
||||
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 .
|
||||
|
||||
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||
20
docker/Dockerfile.armhf
Normal file
20
docker/Dockerfile.armhf
Normal file
@@ -0,0 +1,20 @@
|
||||
# Dockerfile for armhf version of HassIO add-on
|
||||
FROM homeassistant/armhf-base:latest
|
||||
|
||||
RUN apk add --no-cache \
|
||||
python2 \
|
||||
py2-pip \
|
||||
git \
|
||||
openssh \
|
||||
libc6-compat \
|
||||
&& \
|
||||
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 .
|
||||
|
||||
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 hassio-builder.sh /usr/bin/
|
||||
|
||||
WORKDIR /data
|
||||
19
docker/Dockerfile.i386
Normal file
19
docker/Dockerfile.i386
Normal file
@@ -0,0 +1,19 @@
|
||||
# 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 \
|
||||
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 .
|
||||
|
||||
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||
4
docker/Dockerfile.lint
Normal file
4
docker/Dockerfile.lint
Normal file
@@ -0,0 +1,4 @@
|
||||
FROM python:2.7
|
||||
|
||||
RUN pip install -r requirements.txt && \
|
||||
pip install flake8==3.5.0 pylint==1.8.4
|
||||
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
|
||||
; platforms
|
||||
|
||||
[env:espressif32]
|
||||
platform = espressif32
|
||||
board = nodemcu-32s
|
||||
framework = arduino
|
||||
|
||||
[env:espressif8266]
|
||||
platform = espressif8266
|
||||
board = nodemcuv2
|
||||
framework = arduino
|
||||
|
||||
[env:espressif32]
|
||||
platform = espressif32
|
||||
board = nodemcu-32s
|
||||
framework = arduino
|
||||
|
||||
43
esphomeyaml-edge/Dockerfile
Normal file
43
esphomeyaml-edge/Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
||||
# Dockerfile for HassIO add-on
|
||||
ARG BUILD_FROM=ubuntu:bionic
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
# Re-declare BUILD_FROM to fix weird docker issue
|
||||
ARG BUILD_FROM
|
||||
|
||||
# On amd64 and alike, using ubuntu as the base is better as building
|
||||
# for the ESP32 only works with glibc (and ubuntu). However, on armhf
|
||||
# the build toolchain frequently procudes segfaults under ubuntu.
|
||||
# -> Use ubuntu for most architectures, except alpine for armhf
|
||||
#
|
||||
# * python and related required because this is a python project
|
||||
# * git required for platformio library dependencies downloads
|
||||
# * libc6-compat and openssh required on alpine for weird reasons
|
||||
# * disable platformio telemetry on install
|
||||
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
python python-pip python-setuptools git && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/*; \
|
||||
else \
|
||||
apk add --no-cache python2 py2-pip git openssh libc6-compat; \
|
||||
fi" && \
|
||||
pip install --no-cache-dir platformio && \
|
||||
platformio settings set enable_telemetry No
|
||||
|
||||
|
||||
# Create fake project to make platformio install all depdencies.
|
||||
# * Ignore build errors from platformio - empty project
|
||||
# * On alpine, only install ESP8266 toolchain
|
||||
COPY platformio.ini /pio/platformio.ini
|
||||
RUN /bin/bash -c "if [[ '$BUILD_FROM' = *\"ubuntu\"* ]]; then \
|
||||
platformio run -e espressif32 -e espressif8266 -d /pio; exit 0; \
|
||||
else \
|
||||
echo \"\$(head -8 /pio/platformio.ini)\" >/pio/platformio.ini; \
|
||||
platformio run -e espressif8266 -d /pio; exit 0; \
|
||||
fi"
|
||||
|
||||
# Install latest esphomeyaml from git
|
||||
RUN pip install --no-cache-dir \
|
||||
git+git://github.com/OttoWinter/esphomeyaml.git
|
||||
|
||||
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"]
|
||||
10
esphomeyaml-edge/build.json
Normal file
10
esphomeyaml-edge/build.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"squash": false,
|
||||
"build_from": {
|
||||
"aarch64": "homeassistant/aarch64-base:latest",
|
||||
"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
|
||||
@@ -5,13 +5,16 @@ import logging
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from esphomeyaml import core, mqtt, wizard, writer, yaml_util, const
|
||||
from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util
|
||||
from esphomeyaml.config import core_to_code, get_component, iter_components, read_config
|
||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ESPHOMEYAML, CONF_HOSTNAME, CONF_LOGGER, \
|
||||
CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI
|
||||
from esphomeyaml.helpers import AssignmentExpression, RawStatement, _EXPRESSIONS, add, add_task, \
|
||||
color, get_variable, indent, quote, statement, Expression
|
||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_BUILD_PATH, CONF_DOMAIN, CONF_ESPHOMEYAML, \
|
||||
CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, \
|
||||
ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
|
||||
add_job, color, flush_tasks, indent, quote, statement
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -23,31 +26,31 @@ def get_name(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 discover_serial_ports():
|
||||
def get_serial_ports():
|
||||
# from https://github.com/pyserial/pyserial/blob/master/serial/tools/list_ports.py
|
||||
try:
|
||||
from serial.tools.list_ports import comports
|
||||
except ImportError:
|
||||
return None
|
||||
|
||||
from serial.tools.list_ports import comports
|
||||
result = []
|
||||
descs = []
|
||||
for port, desc, info in comports():
|
||||
if not port:
|
||||
continue
|
||||
if "VID:PID" in info:
|
||||
result.append(port)
|
||||
descs.append(desc)
|
||||
result.append((port, desc))
|
||||
return result
|
||||
|
||||
|
||||
def choose_serial_port(config):
|
||||
result = get_serial_ports()
|
||||
|
||||
if not result:
|
||||
return None
|
||||
return 'OTA'
|
||||
print(u"Found multiple serial port options, please choose one:")
|
||||
for i, (res, desc) in enumerate(zip(result, descs)):
|
||||
for i, (res, desc) in enumerate(result):
|
||||
print(u" [{}] {} ({})".format(i, res, desc))
|
||||
print(u" [{}] Over The Air".format(len(result)))
|
||||
print(u" [{}] Over The Air ({})".format(len(result), get_upload_host(config)))
|
||||
print()
|
||||
while True:
|
||||
opt = raw_input('(number): ')
|
||||
@@ -62,11 +65,11 @@ def discover_serial_ports():
|
||||
except ValueError:
|
||||
print(color('red', u"Invalid option: '{}'".format(opt)))
|
||||
if opt == len(result):
|
||||
return None
|
||||
return result[opt]
|
||||
return 'OTA'
|
||||
return result[opt][0]
|
||||
|
||||
|
||||
def run_platformio(*cmd):
|
||||
def run_platformio(*cmd, **kwargs):
|
||||
def mock_exit(return_code):
|
||||
raise SystemExit(return_code)
|
||||
|
||||
@@ -75,10 +78,13 @@ def run_platformio(*cmd):
|
||||
full_cmd = u' '.join(quote(x) for x in cmd)
|
||||
_LOGGER.info(u"Running: %s", full_cmd)
|
||||
try:
|
||||
import platformio.__main__
|
||||
func = kwargs.get('main')
|
||||
if func is None:
|
||||
import platformio.__main__
|
||||
func = platformio.__main__.main
|
||||
sys.argv = list(cmd)
|
||||
sys.exit = mock_exit
|
||||
return platformio.__main__.main()
|
||||
return func() or 0
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
except SystemExit as err:
|
||||
@@ -91,53 +97,53 @@ def run_platformio(*cmd):
|
||||
sys.exit = orig_exit
|
||||
|
||||
|
||||
def run_miniterm(config, port):
|
||||
from serial.tools import miniterm
|
||||
def run_miniterm(config, port, escape=False):
|
||||
import serial
|
||||
baud_rate = config.get(CONF_LOGGER, {}).get(CONF_BAUD_RATE, 115200)
|
||||
sys.argv = ['miniterm', '--raw', '--exit-char', '3']
|
||||
miniterm.main(
|
||||
default_port=port,
|
||||
default_baudrate=baud_rate)
|
||||
_LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate)
|
||||
|
||||
with serial.Serial(port, baudrate=baud_rate) as ser:
|
||||
while True:
|
||||
line = ser.readline().replace('\r', '').replace('\n', '')
|
||||
time = datetime.now().time().strftime('[%H:%M:%S]')
|
||||
message = time + line
|
||||
if escape:
|
||||
message = message.replace('\033', '\\033')
|
||||
try:
|
||||
print(message)
|
||||
except UnicodeEncodeError:
|
||||
print(message.encode('ascii', 'backslashreplace'))
|
||||
|
||||
|
||||
def write_cpp(config):
|
||||
_LOGGER.info("Generating C++ source...")
|
||||
|
||||
add_task(core_to_code, config[CONF_ESPHOMEYAML])
|
||||
add_job(core_to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml')
|
||||
for domain in PRE_INITIALIZE:
|
||||
if domain == CONF_ESPHOMEYAML:
|
||||
if domain == CONF_ESPHOMEYAML or domain not in config:
|
||||
continue
|
||||
if domain in config:
|
||||
add_task(get_component(domain).to_code, config[domain])
|
||||
|
||||
# Clear queue
|
||||
get_variable(None)
|
||||
add(RawStatement(''))
|
||||
add_job(get_component(domain).to_code, config[domain], domain=domain)
|
||||
|
||||
for domain, component, conf in iter_components(config):
|
||||
if domain in PRE_INITIALIZE:
|
||||
if domain in PRE_INITIALIZE or not hasattr(component, 'to_code'):
|
||||
continue
|
||||
if not hasattr(component, 'to_code'):
|
||||
continue
|
||||
add_task(component.to_code, conf)
|
||||
add_job(component.to_code, conf, domain=domain)
|
||||
|
||||
# Clear queue
|
||||
get_variable(None)
|
||||
flush_tasks()
|
||||
add(RawStatement(''))
|
||||
add(RawStatement(''))
|
||||
|
||||
all_code = []
|
||||
for exp in _EXPRESSIONS:
|
||||
if core.SIMPLIFY:
|
||||
if isinstance(exp, Expression) and not exp.required:
|
||||
continue
|
||||
if isinstance(exp, AssignmentExpression) and not exp.obj.required:
|
||||
if not exp.has_side_effects():
|
||||
continue
|
||||
exp = exp.rhs
|
||||
all_code.append(unicode(statement(exp)))
|
||||
|
||||
platformio_ini_s = writer.get_ini_content(config)
|
||||
ini_path = os.path.join(get_base_path(config), 'platformio.ini')
|
||||
writer.write_platformio_ini(platformio_ini_s, ini_path)
|
||||
writer.write_platformio_project(config, get_base_path(config))
|
||||
|
||||
code_s = indent('\n'.join(line.rstrip() for line in all_code))
|
||||
cpp_path = os.path.join(get_base_path(config), 'src', 'main.cpp')
|
||||
@@ -145,27 +151,59 @@ def write_cpp(config):
|
||||
return 0
|
||||
|
||||
|
||||
def compile_program(config):
|
||||
def compile_program(args, config):
|
||||
_LOGGER.info("Compiling app...")
|
||||
return run_platformio('platformio', 'run', '-d', get_base_path(config))
|
||||
command = ['platformio', 'run', '-d', get_base_path(config)]
|
||||
if args.verbose:
|
||||
command.append('-v')
|
||||
return run_platformio(*command)
|
||||
|
||||
|
||||
def get_upload_host(config):
|
||||
if CONF_MANUAL_IP in config[CONF_WIFI]:
|
||||
host = str(config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP])
|
||||
elif CONF_HOSTNAME in config[CONF_WIFI]:
|
||||
host = config[CONF_WIFI][CONF_HOSTNAME] + config[CONF_WIFI][CONF_DOMAIN]
|
||||
else:
|
||||
host = config[CONF_ESPHOMEYAML][CONF_NAME] + config[CONF_WIFI][CONF_DOMAIN]
|
||||
return host
|
||||
|
||||
|
||||
def upload_using_esptool(config, port):
|
||||
import esptool
|
||||
|
||||
name = get_name(config)
|
||||
path = os.path.join(get_base_path(config), '.pioenvs', name, 'firmware.bin')
|
||||
# pylint: disable=protected-access
|
||||
return run_platformio('esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
|
||||
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0',
|
||||
path, main=esptool._main)
|
||||
|
||||
|
||||
def upload_program(config, args, port):
|
||||
_LOGGER.info("Uploading binary...")
|
||||
if port is not None:
|
||||
return run_platformio('platformio', 'run', '-d', get_base_path(config),
|
||||
'-t', 'upload', '--upload-port', port)
|
||||
|
||||
# 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:
|
||||
return upload_using_esptool(config, port)
|
||||
command = ['platformio', 'run', '-d', get_base_path(config),
|
||||
'-t', 'upload', '--upload-port', port]
|
||||
if args.verbose:
|
||||
command.append('-v')
|
||||
return run_platformio(*command)
|
||||
|
||||
if 'ota' not in config:
|
||||
_LOGGER.error("No serial port found and OTA not enabled. Can't upload!")
|
||||
return -1
|
||||
|
||||
if CONF_MANUAL_IP in config[CONF_WIFI]:
|
||||
host = str(config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP])
|
||||
elif CONF_HOSTNAME in config[CONF_WIFI]:
|
||||
host = config[CONF_WIFI][CONF_HOSTNAME] + u'.local'
|
||||
# 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 = config[CONF_ESPHOMEYAML][CONF_NAME] + u'.local'
|
||||
host = get_upload_host(config)
|
||||
|
||||
from esphomeyaml.components import ota
|
||||
from esphomeyaml import espota
|
||||
@@ -178,22 +216,27 @@ def upload_program(config, args, port):
|
||||
espota_args = ['espota.py', '--debug', '--progress', '-i', host,
|
||||
'-p', str(ota.get_port(config)), '-f', bin_file,
|
||||
'-a', ota.get_auth(config), '-P', str(host_port)]
|
||||
if args.verbose:
|
||||
espota_args.append('-d')
|
||||
return espota.main(espota_args)
|
||||
|
||||
|
||||
def show_logs(config, args, port):
|
||||
if port is not None and port != 'OTA':
|
||||
run_miniterm(config, port)
|
||||
def show_logs(config, args, port, escape=False):
|
||||
serial_port = port.startswith('/') or port.startswith('COM')
|
||||
if port != 'OTA' and serial_port:
|
||||
run_miniterm(config, port, escape=escape)
|
||||
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,
|
||||
escape=escape)
|
||||
|
||||
|
||||
def clean_mqtt(config, args):
|
||||
return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id)
|
||||
|
||||
|
||||
def setup_log():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
def setup_log(debug=False):
|
||||
log_level = logging.DEBUG if debug else logging.INFO
|
||||
logging.basicConfig(level=log_level)
|
||||
fmt = "%(levelname)s [%(name)s] %(message)s"
|
||||
colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
|
||||
datefmt = '%H:%M:%S'
|
||||
@@ -218,11 +261,121 @@ def setup_log():
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
setup_log()
|
||||
def command_wizard(args):
|
||||
return wizard.wizard(args.configuration)
|
||||
|
||||
|
||||
def strip_default_ids(config):
|
||||
value = config
|
||||
if isinstance(config, list):
|
||||
value = type(config)()
|
||||
for x in config:
|
||||
if isinstance(x, core.ID) and not x.is_manual:
|
||||
continue
|
||||
value.append(strip_default_ids(x))
|
||||
return value
|
||||
elif isinstance(config, dict):
|
||||
value = type(config)()
|
||||
for k, v in config.iteritems():
|
||||
if isinstance(v, core.ID) and not v.is_manual:
|
||||
continue
|
||||
value[k] = strip_default_ids(v)
|
||||
return value
|
||||
return value
|
||||
|
||||
|
||||
def command_config(args, config):
|
||||
if not args.verbose:
|
||||
config = strip_default_ids(config)
|
||||
print(yaml_util.dump(config))
|
||||
return 0
|
||||
|
||||
|
||||
def command_compile(args, config):
|
||||
exit_code = write_cpp(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
exit_code = compile_program(args, config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
return 0
|
||||
|
||||
|
||||
def command_upload(args, config):
|
||||
port = args.upload_port or choose_serial_port(config)
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
return 0
|
||||
|
||||
|
||||
def command_logs(args, config):
|
||||
port = args.serial_port or choose_serial_port(config)
|
||||
return show_logs(config, args, port, escape=args.escape)
|
||||
|
||||
|
||||
def command_run(args, config):
|
||||
exit_code = write_cpp(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
exit_code = compile_program(args, config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
port = args.upload_port or choose_serial_port(config)
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
if args.no_logs:
|
||||
return 0
|
||||
return show_logs(config, args, port, escape=args.escape)
|
||||
|
||||
|
||||
def command_clean_mqtt(args, config):
|
||||
return clean_mqtt(config, args)
|
||||
|
||||
|
||||
def command_mqtt_fingerprint(args, config):
|
||||
return mqtt.get_fingerprint(config)
|
||||
|
||||
|
||||
def command_version(args):
|
||||
print(u"Version: {}".format(const.__version__))
|
||||
return 0
|
||||
|
||||
|
||||
def command_dashboard(args):
|
||||
from esphomeyaml.dashboard import dashboard
|
||||
|
||||
return dashboard.start_web_server(args)
|
||||
|
||||
|
||||
PRE_CONFIG_ACTIONS = {
|
||||
'wizard': command_wizard,
|
||||
'version': command_version,
|
||||
'dashboard': command_dashboard
|
||||
}
|
||||
|
||||
POST_CONFIG_ACTIONS = {
|
||||
'config': command_config,
|
||||
'compile': command_compile,
|
||||
'upload': command_upload,
|
||||
'logs': command_logs,
|
||||
'run': command_run,
|
||||
'clean-mqtt': command_clean_mqtt,
|
||||
'mqtt-fingerprint': command_mqtt_fingerprint,
|
||||
}
|
||||
|
||||
|
||||
def parse_args(argv):
|
||||
parser = argparse.ArgumentParser(prog='esphomeyaml')
|
||||
parser.add_argument('-v', '--verbose', help="Enable verbose esphomeyaml logs.",
|
||||
action='store_true')
|
||||
parser.add_argument('configuration', help='Your YAML configuration file.')
|
||||
|
||||
subparsers = parser.add_subparsers(help='Commands', dest='command')
|
||||
subparsers.required = True
|
||||
subparsers.add_parser('config', help='Validate the configuration and spit it out.')
|
||||
@@ -234,6 +387,9 @@ def main():
|
||||
parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. "
|
||||
"For example /dev/cu.SLAB_USBtoUART.")
|
||||
parser_upload.add_argument('--host-port', help="Specify the host port.", type=int)
|
||||
parser_upload.add_argument('--use-esptoolpy',
|
||||
help="Use esptool.py for the uploading (only for ESP8266)",
|
||||
action='store_true')
|
||||
|
||||
parser_logs = subparsers.add_parser('logs', help='Validate the configuration '
|
||||
'and show all MQTT logs.')
|
||||
@@ -243,10 +399,12 @@ def main():
|
||||
parser_logs.add_argument('--client-id', help='Manually set the client id.')
|
||||
parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use"
|
||||
"For example /dev/cu.SLAB_USBtoUART.")
|
||||
parser_logs.add_argument('--escape', help="Escape ANSI color codes for running in dashboard",
|
||||
action='store_true')
|
||||
|
||||
parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, '
|
||||
'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.")
|
||||
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.',
|
||||
@@ -255,6 +413,11 @@ def main():
|
||||
parser_run.add_argument('--username', help='Manually set the MQTT username for logs.')
|
||||
parser_run.add_argument('--password', help='Manually set the MQTT password for logs.')
|
||||
parser_run.add_argument('--client-id', help='Manually set the client id for logs.')
|
||||
parser_run.add_argument('--escape', help="Escape ANSI color codes for running in dashboard",
|
||||
action='store_true')
|
||||
parser_run.add_argument('--use-esptoolpy',
|
||||
help="Use esptool.py for the uploading (only for ESP8266)",
|
||||
action='store_true')
|
||||
|
||||
parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from "
|
||||
"retain messages.")
|
||||
@@ -267,12 +430,28 @@ def main():
|
||||
"you through setting up esphomeyaml.")
|
||||
|
||||
subparsers.add_parser('mqtt-fingerprint', help="Get the SSL fingerprint from a MQTT broker.")
|
||||
|
||||
subparsers.add_parser('version', help="Print the esphomeyaml version and exit.")
|
||||
|
||||
args = parser.parse_args()
|
||||
dashboard = subparsers.add_parser('dashboard',
|
||||
help="Create a simple webserver for a dashboard.")
|
||||
dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int,
|
||||
default=6052)
|
||||
dashboard.add_argument("--password", help="The optional password to require for all requests.",
|
||||
type=str, default='')
|
||||
|
||||
if args.command == 'wizard':
|
||||
return wizard.wizard(args.configuration)
|
||||
return parser.parse_args(argv[1:])
|
||||
|
||||
|
||||
def run_esphomeyaml(argv):
|
||||
args = parse_args(argv)
|
||||
setup_log(args.verbose)
|
||||
if args.command in PRE_CONFIG_ACTIONS:
|
||||
try:
|
||||
return PRE_CONFIG_ACTIONS[args.command](args)
|
||||
except ESPHomeYAMLError as e:
|
||||
_LOGGER.error(e)
|
||||
return 1
|
||||
|
||||
core.CONFIG_PATH = args.configuration
|
||||
|
||||
@@ -280,54 +459,25 @@ def main():
|
||||
if config is None:
|
||||
return 1
|
||||
|
||||
if args.command == 'config':
|
||||
print(yaml_util.dump(config))
|
||||
return 0
|
||||
elif args.command == 'compile':
|
||||
exit_code = write_cpp(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
exit_code = compile_program(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
return 0
|
||||
elif args.command == 'upload':
|
||||
port = args.upload_port or discover_serial_ports()
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
return 0
|
||||
elif args.command == 'logs':
|
||||
port = args.serial_port or discover_serial_ports()
|
||||
return show_logs(config, args, port)
|
||||
elif args.command == 'clean-mqtt':
|
||||
return clean_mqtt(config, args)
|
||||
elif args.command == 'mqtt-fingerprint':
|
||||
return mqtt.get_fingerprint(config)
|
||||
elif args.command == 'run':
|
||||
exit_code = write_cpp(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
exit_code = compile_program(config)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully compiled program.")
|
||||
port = args.upload_port or discover_serial_ports()
|
||||
exit_code = upload_program(config, args, port)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
_LOGGER.info(u"Successfully uploaded program.")
|
||||
if args.no_logs:
|
||||
return 0
|
||||
return show_logs(config, args, port)
|
||||
elif args.command == 'version':
|
||||
print(u"Version: {}".format(const.__version__))
|
||||
return 0
|
||||
if args.command in POST_CONFIG_ACTIONS:
|
||||
try:
|
||||
return POST_CONFIG_ACTIONS[args.command](args, config)
|
||||
except ESPHomeYAMLError as e:
|
||||
_LOGGER.error(e)
|
||||
return 1
|
||||
print(u"Unknown command {}".format(args.command))
|
||||
return 1
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
return run_esphomeyaml(sys.argv)
|
||||
except ESPHomeYAMLError as e:
|
||||
_LOGGER.error(e)
|
||||
return 1
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
||||
426
esphomeyaml/automation.py
Normal file
426
esphomeyaml/automation.py
Normal file
@@ -0,0 +1,426 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import cover, fan
|
||||
from esphomeyaml.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \
|
||||
CONF_BELOW, \
|
||||
CONF_BLUE, CONF_BRIGHTNESS, CONF_CONDITION_ID, CONF_DELAY, CONF_EFFECT, CONF_FLASH_LENGTH, \
|
||||
CONF_GREEN, CONF_ID, CONF_IF, CONF_LAMBDA, CONF_OR, CONF_OSCILLATING, CONF_PAYLOAD, CONF_QOS, \
|
||||
CONF_RANGE, CONF_RED, CONF_RETAIN, CONF_SPEED, CONF_THEN, CONF_TOPIC, CONF_TRANSITION_LENGTH, \
|
||||
CONF_TRIGGER_ID, CONF_WHITE
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, TemplateArguments, add, \
|
||||
bool_, esphomelib_ns, float_, get_variable, process_lambda, std_string, templatable, uint32, \
|
||||
uint8, add_job
|
||||
|
||||
CONF_MQTT_PUBLISH = 'mqtt.publish'
|
||||
CONF_LIGHT_TOGGLE = 'light.toggle'
|
||||
CONF_LIGHT_TURN_OFF = 'light.turn_off'
|
||||
CONF_LIGHT_TURN_ON = 'light.turn_on'
|
||||
CONF_SWITCH_TOGGLE = 'switch.toggle'
|
||||
CONF_SWITCH_TURN_OFF = 'switch.turn_off'
|
||||
CONF_SWITCH_TURN_ON = 'switch.turn_on'
|
||||
CONF_COVER_OPEN = 'cover.open'
|
||||
CONF_COVER_CLOSE = 'cover.close'
|
||||
CONF_COVER_STOP = 'cover.stop'
|
||||
CONF_FAN_TOGGLE = 'fan.toggle'
|
||||
CONF_FAN_TURN_OFF = 'fan.turn_off'
|
||||
CONF_FAN_TURN_ON = 'fan.turn_on'
|
||||
|
||||
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_LAMBDA, CONF_COVER_OPEN, CONF_COVER_CLOSE, CONF_COVER_STOP, CONF_FAN_TOGGLE,
|
||||
CONF_FAN_TURN_OFF, CONF_FAN_TURN_ON]
|
||||
|
||||
ACTIONS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
||||
cv.GenerateID(CONF_ACTION_ID): cv.declare_variable_id(None),
|
||||
vol.Optional(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds),
|
||||
vol.Optional(CONF_MQTT_PUBLISH): vol.Schema({
|
||||
vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic),
|
||||
vol.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload),
|
||||
vol.Optional(CONF_QOS): cv.templatable(cv.mqtt_qos),
|
||||
vol.Optional(CONF_RETAIN): cv.templatable(cv.boolean),
|
||||
}),
|
||||
vol.Optional(CONF_LIGHT_TOGGLE): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
||||
}),
|
||||
vol.Optional(CONF_LIGHT_TURN_OFF): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds),
|
||||
}),
|
||||
vol.Optional(CONF_LIGHT_TURN_ON): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
vol.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'):
|
||||
cv.templatable(cv.positive_time_period_milliseconds),
|
||||
vol.Exclusive(CONF_FLASH_LENGTH, 'transformer'):
|
||||
cv.templatable(cv.positive_time_period_milliseconds),
|
||||
vol.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage),
|
||||
vol.Optional(CONF_RED): cv.templatable(cv.percentage),
|
||||
vol.Optional(CONF_GREEN): cv.templatable(cv.percentage),
|
||||
vol.Optional(CONF_BLUE): cv.templatable(cv.percentage),
|
||||
vol.Optional(CONF_WHITE): cv.templatable(cv.percentage),
|
||||
vol.Optional(CONF_EFFECT): cv.templatable(cv.string),
|
||||
}),
|
||||
vol.Optional(CONF_SWITCH_TOGGLE): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_SWITCH_TURN_OFF): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_SWITCH_TURN_ON): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_OPEN): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_STOP): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_OPEN): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_CLOSE): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_COVER_STOP): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_FAN_TOGGLE): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_FAN_TURN_OFF): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
}),
|
||||
vol.Optional(CONF_FAN_TURN_ON): vol.Schema({
|
||||
vol.Required(CONF_ID): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean),
|
||||
vol.Optional(CONF_SPEED): cv.templatable(fan.validate_fan_speed),
|
||||
}),
|
||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
}, cv.has_exactly_one_key(*ACTION_KEYS))])
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
DelayAction = esphomelib_ns.DelayAction
|
||||
LambdaAction = esphomelib_ns.LambdaAction
|
||||
Automation = esphomelib_ns.Automation
|
||||
|
||||
|
||||
def validate_recursive_condition(value):
|
||||
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(CONF_CONDITION_ID): cv.declare_variable_id(None),
|
||||
vol.Optional(CONF_AND): validate_recursive_condition,
|
||||
vol.Optional(CONF_OR): validate_recursive_condition,
|
||||
vol.Optional(CONF_RANGE): vol.All(vol.Schema({
|
||||
vol.Optional(CONF_ABOVE): vol.Coerce(float),
|
||||
vol.Optional(CONF_BELOW): vol.Coerce(float),
|
||||
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)),
|
||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
}), cv.has_exactly_one_key(*CONDITION_KEYS)])
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
AndCondition = esphomelib_ns.AndCondition
|
||||
OrCondition = esphomelib_ns.OrCondition
|
||||
RangeCondition = esphomelib_ns.RangeCondition
|
||||
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({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(None),
|
||||
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(None),
|
||||
vol.Optional(CONF_IF): CONDITIONS_SCHEMA,
|
||||
vol.Required(CONF_THEN): ACTIONS_SCHEMA,
|
||||
})
|
||||
|
||||
|
||||
def build_condition(config, arg_type):
|
||||
template_arg = TemplateArguments(arg_type)
|
||||
if CONF_AND in config:
|
||||
yield AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg))
|
||||
elif CONF_OR in config:
|
||||
yield OrCondition.new(template_arg, build_conditions(config[CONF_OR], template_arg))
|
||||
elif CONF_LAMBDA in config:
|
||||
lambda_ = None
|
||||
for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]):
|
||||
yield
|
||||
yield LambdaCondition.new(template_arg, lambda_)
|
||||
elif CONF_RANGE in config:
|
||||
conf = config[CONF_RANGE]
|
||||
rhs = RangeCondition.new(template_arg)
|
||||
type = RangeCondition.template(template_arg)
|
||||
condition = Pvariable(config[CONF_CONDITION_ID], rhs, type=type)
|
||||
if CONF_ABOVE in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_ABOVE], arg_type, float_):
|
||||
yield
|
||||
condition.set_min(template_)
|
||||
if CONF_BELOW in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_BELOW], arg_type, float_):
|
||||
yield
|
||||
condition.set_max(template_)
|
||||
yield condition
|
||||
else:
|
||||
raise ESPHomeYAMLError(u"Unsupported condition {}".format(config))
|
||||
|
||||
|
||||
def build_conditions(config, arg_type):
|
||||
conditions = []
|
||||
for conf in config:
|
||||
condition = None
|
||||
for condition in build_condition(conf, arg_type):
|
||||
yield None
|
||||
conditions.append(condition)
|
||||
yield ArrayInitializer(*conditions)
|
||||
|
||||
|
||||
def build_action(config, arg_type):
|
||||
from esphomeyaml.components import light, mqtt, switch
|
||||
|
||||
template_arg = TemplateArguments(arg_type)
|
||||
# Keep pylint from freaking out
|
||||
var = None
|
||||
if CONF_DELAY in config:
|
||||
rhs = App.register_component(DelayAction.new(template_arg))
|
||||
type = DelayAction.template(template_arg)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
template_ = None
|
||||
for template_ in templatable(config[CONF_DELAY], arg_type, uint32):
|
||||
yield
|
||||
add(action.set_delay(template_))
|
||||
yield action
|
||||
elif CONF_LAMBDA in config:
|
||||
lambda_ = None
|
||||
for lambda_ in process_lambda(config[CONF_LAMBDA], [(arg_type, 'x')]):
|
||||
yield None
|
||||
rhs = LambdaAction.new(template_arg, lambda_)
|
||||
type = LambdaAction.template(template_arg)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_MQTT_PUBLISH in config:
|
||||
conf = config[CONF_MQTT_PUBLISH]
|
||||
rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg)
|
||||
type = mqtt.MQTTPublishAction.template(template_arg)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_TOPIC], arg_type, std_string):
|
||||
yield None
|
||||
add(action.set_topic(template_))
|
||||
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_PAYLOAD], arg_type, std_string):
|
||||
yield None
|
||||
add(action.set_payload(template_))
|
||||
if CONF_QOS in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_QOS], arg_type, uint8):
|
||||
yield
|
||||
add(action.set_qos(template_))
|
||||
if CONF_RETAIN in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_RETAIN], arg_type, bool_):
|
||||
yield None
|
||||
add(action.set_retain(template_))
|
||||
yield action
|
||||
elif CONF_LIGHT_TOGGLE in config:
|
||||
conf = config[CONF_LIGHT_TOGGLE]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_toggle_action(template_arg)
|
||||
type = light.ToggleAction.template(template_arg)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
if CONF_TRANSITION_LENGTH in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||
yield None
|
||||
add(action.set_transition_length(template_))
|
||||
yield action
|
||||
elif CONF_LIGHT_TURN_OFF in config:
|
||||
conf = config[CONF_LIGHT_TURN_OFF]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_off_action(template_arg)
|
||||
type = light.TurnOffAction.template(template_arg)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
if CONF_TRANSITION_LENGTH in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||
yield None
|
||||
add(action.set_transition_length(template_))
|
||||
yield action
|
||||
elif CONF_LIGHT_TURN_ON in config:
|
||||
conf = config[CONF_LIGHT_TURN_ON]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_on_action(template_arg)
|
||||
type = light.TurnOnAction.template(template_arg)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
if CONF_TRANSITION_LENGTH in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_TRANSITION_LENGTH], arg_type, uint32):
|
||||
yield None
|
||||
add(action.set_transition_length(template_))
|
||||
if CONF_FLASH_LENGTH in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_FLASH_LENGTH], arg_type, uint32):
|
||||
yield None
|
||||
add(action.set_flash_length(template_))
|
||||
if CONF_BRIGHTNESS in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_BRIGHTNESS], arg_type, float_):
|
||||
yield None
|
||||
add(action.set_brightness(template_))
|
||||
if CONF_RED in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_RED], arg_type, float_):
|
||||
yield None
|
||||
add(action.set_red(template_))
|
||||
if CONF_GREEN in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_GREEN], arg_type, float_):
|
||||
yield None
|
||||
add(action.set_green(template_))
|
||||
if CONF_BLUE in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_BLUE], arg_type, float_):
|
||||
yield None
|
||||
add(action.set_blue(template_))
|
||||
if CONF_WHITE in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_WHITE], arg_type, float_):
|
||||
yield None
|
||||
add(action.set_white(template_))
|
||||
if CONF_EFFECT in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_EFFECT], arg_type, std_string):
|
||||
yield None
|
||||
add(action.set_effect(template_))
|
||||
yield action
|
||||
elif CONF_SWITCH_TOGGLE in config:
|
||||
conf = config[CONF_SWITCH_TOGGLE]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_toggle_action(template_arg)
|
||||
type = switch.ToggleAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_SWITCH_TURN_OFF in config:
|
||||
conf = config[CONF_SWITCH_TURN_OFF]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_off_action(template_arg)
|
||||
type = switch.TurnOffAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_SWITCH_TURN_ON in config:
|
||||
conf = config[CONF_SWITCH_TURN_ON]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_on_action(template_arg)
|
||||
type = switch.TurnOnAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_COVER_OPEN in config:
|
||||
conf = config[CONF_COVER_OPEN]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_open_action(template_arg)
|
||||
type = cover.OpenAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_COVER_CLOSE in config:
|
||||
conf = config[CONF_COVER_CLOSE]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_close_action(template_arg)
|
||||
type = cover.CloseAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_COVER_STOP in config:
|
||||
conf = config[CONF_COVER_STOP]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_stop_action(template_arg)
|
||||
type = cover.StopAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_FAN_TOGGLE in config:
|
||||
conf = config[CONF_FAN_TOGGLE]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_toggle_action(template_arg)
|
||||
type = fan.ToggleAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_FAN_TURN_OFF in config:
|
||||
conf = config[CONF_FAN_TURN_OFF]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_off_action(template_arg)
|
||||
type = fan.TurnOffAction.template(arg_type)
|
||||
yield Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
elif CONF_FAN_TURN_ON in config:
|
||||
conf = config[CONF_FAN_TURN_ON]
|
||||
for var in get_variable(conf[CONF_ID]):
|
||||
yield None
|
||||
rhs = var.make_turn_on_action(template_arg)
|
||||
type = fan.TurnOnAction.template(arg_type)
|
||||
action = Pvariable(config[CONF_ACTION_ID], rhs, type=type)
|
||||
if CONF_OSCILLATING in config:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_OSCILLATING], arg_type, bool_):
|
||||
yield None
|
||||
add(action.set_oscillating(template_))
|
||||
if CONF_SPEED in config:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_SPEED], arg_type, fan.FanSpeed):
|
||||
yield None
|
||||
add(action.set_speed(template_))
|
||||
yield action
|
||||
else:
|
||||
raise ESPHomeYAMLError(u"Unsupported action {}".format(config))
|
||||
|
||||
|
||||
def build_actions(config, arg_type):
|
||||
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):
|
||||
add_job(build_automation_, trigger, arg_type, config)
|
||||
@@ -1,17 +1,18 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_RATE
|
||||
from esphomeyaml.helpers import App, Pvariable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
ADS1115_COMPONENT_CLASS = 'sensor::ADS1115Component'
|
||||
ADS1115Component = sensor.sensor_ns.ADS1115Component
|
||||
|
||||
RATE_REMOVE_MESSAGE = """The rate option has been removed in 1.5.0 and is no longer required."""
|
||||
|
||||
ADS1115_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('ads1115'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
|
||||
vol.Required(CONF_ADDRESS): cv.i2c_address,
|
||||
|
||||
vol.Optional(CONF_RATE): cv.invalid(RATE_REMOVE_MESSAGE)
|
||||
@@ -23,7 +24,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
rhs = App.make_ads1115_component(conf[CONF_ADDRESS])
|
||||
Pvariable(ADS1115_COMPONENT_CLASS, conf[CONF_ID], rhs)
|
||||
Pvariable(conf[CONF_ID], rhs)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_INVERTED, CONF_MQTT_ID
|
||||
from esphomeyaml.helpers import add, setup_mqtt_component, App, Pvariable
|
||||
from esphomeyaml import automation
|
||||
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INTERNAL, CONF_INVERTED, \
|
||||
CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, \
|
||||
CONF_ON_PRESS, CONF_ON_RELEASE, CONF_TRIGGER_ID, CONF_FILTERS, CONF_INVERT, CONF_DELAYED_ON, \
|
||||
CONF_DELAYED_OFF, CONF_LAMBDA
|
||||
from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \
|
||||
setup_mqtt_component, bool_, process_lambda, ArrayInitializer
|
||||
|
||||
DEVICE_CLASSES = [
|
||||
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
|
||||
@@ -11,39 +16,139 @@ DEVICE_CLASSES = [
|
||||
'sound', 'vibration', 'window'
|
||||
]
|
||||
|
||||
DEVICE_CLASSES_MSG = "Unknown device class. Must be one of {}".format(', '.join(DEVICE_CLASSES))
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower,
|
||||
vol.Any(*DEVICE_CLASSES, msg=DEVICE_CLASSES_MSG)),
|
||||
})
|
||||
|
||||
MQTT_BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
||||
|
||||
})
|
||||
|
||||
MQTT_BINARY_SENSOR_ID_SCHEMA = MQTT_BINARY_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID('mqtt_binary_sensor', CONF_MQTT_ID): cv.register_variable_id,
|
||||
binary_sensor_ns = esphomelib_ns.namespace('binary_sensor')
|
||||
PressTrigger = binary_sensor_ns.PressTrigger
|
||||
ReleaseTrigger = binary_sensor_ns.ReleaseTrigger
|
||||
ClickTrigger = binary_sensor_ns.ClickTrigger
|
||||
DoubleClickTrigger = binary_sensor_ns.DoubleClickTrigger
|
||||
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
|
||||
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_LAMBDA): cv.lambda_,
|
||||
}, cv.has_exactly_one_key(*FILTER_KEYS))])
|
||||
|
||||
BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTBinarySensorComponent),
|
||||
cv.GenerateID(): cv.declare_variable_id(BinarySensor),
|
||||
|
||||
vol.Optional(CONF_DEVICE_CLASS): vol.All(vol.Lower, cv.one_of(*DEVICE_CLASSES)),
|
||||
vol.Optional(CONF_FILTERS): FILTERS_SCHEMA,
|
||||
vol.Optional(CONF_ON_PRESS): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||
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_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds,
|
||||
})]),
|
||||
vol.Optional(CONF_ON_DOUBLE_CLICK):
|
||||
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_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_binary_sensor(obj, config):
|
||||
|
||||
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_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):
|
||||
if CONF_INTERNAL in config:
|
||||
add(binary_sensor_var.set_internal(CONF_INTERNAL))
|
||||
if CONF_DEVICE_CLASS in config:
|
||||
add(obj.set_device_class(config[CONF_DEVICE_CLASS]))
|
||||
add(binary_sensor_var.set_device_class(config[CONF_DEVICE_CLASS]))
|
||||
if CONF_INVERTED in config:
|
||||
add(obj.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, []):
|
||||
rhs = binary_sensor_var.make_press_trigger()
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, NoArg, conf)
|
||||
|
||||
for conf in config.get(CONF_ON_RELEASE, []):
|
||||
rhs = binary_sensor_var.make_release_trigger()
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, NoArg, conf)
|
||||
|
||||
for conf in config.get(CONF_ON_CLICK, []):
|
||||
rhs = binary_sensor_var.make_click_trigger(conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH])
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, NoArg, conf)
|
||||
|
||||
for conf in config.get(CONF_ON_DOUBLE_CLICK, []):
|
||||
rhs = binary_sensor_var.make_double_click_trigger(conf[CONF_MIN_LENGTH],
|
||||
conf[CONF_MAX_LENGTH])
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, NoArg, conf)
|
||||
|
||||
setup_mqtt_component(mqtt_var, config)
|
||||
|
||||
|
||||
def setup_mqtt_binary_sensor(obj, config):
|
||||
setup_mqtt_component(obj, config)
|
||||
def setup_binary_sensor(binary_sensor_obj, mqtt_obj, config):
|
||||
binary_sensor_var = Pvariable(config[CONF_ID], binary_sensor_obj,
|
||||
has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj,
|
||||
has_side_effects=False)
|
||||
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
|
||||
|
||||
|
||||
def register_binary_sensor(var, config):
|
||||
setup_binary_sensor(var, config)
|
||||
rhs = App.register_binary_sensor(var)
|
||||
mqtt_sensor = Pvariable('binary_sensor::MQTTBinarySensorComponent', config[CONF_MQTT_ID], rhs)
|
||||
setup_mqtt_binary_sensor(mqtt_sensor, config)
|
||||
binary_sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
|
||||
rhs = App.register_binary_sensor(binary_sensor_var)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
|
||||
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_MAC_ADDRESS, CONF_NAME, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.core import HexInt, MACAddress
|
||||
from esphomeyaml.helpers import ArrayInitializer, Pvariable, 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({
|
||||
cv.GenerateID('esp32_ble_device'): cv.register_variable_id,
|
||||
vol.Required(CONF_MAC_ADDRESS): validate_mac,
|
||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_ID_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))
|
||||
device = Pvariable('ESP32BLEDevice', config[CONF_ID], rhs)
|
||||
binary_sensor.register_binary_sensor(device, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
|
||||
30
esphomeyaml/components/binary_sensor/esp32_ble_tracker.py
Normal file
30
esphomeyaml/components/binary_sensor/esp32_ble_tracker.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.components.esp32_ble_tracker import ESP32BLETracker
|
||||
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.core import HexInt
|
||||
from esphomeyaml.helpers import ArrayInitializer, get_variable
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
DEPENDENCIES = ['esp32_ble_tracker']
|
||||
|
||||
CONF_ESP32_BLE_ID = 'esp32_ble_id'
|
||||
|
||||
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
|
||||
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'
|
||||
@@ -2,25 +2,28 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.helpers import Pvariable, RawExpression, get_variable
|
||||
from esphomeyaml.components.esp32_touch import ESP32TouchComponent
|
||||
from esphomeyaml.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.helpers import get_variable, global_ns
|
||||
from esphomeyaml.pins import validate_gpio_pin
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
|
||||
DEPENDENCIES = ['esp32_touch']
|
||||
|
||||
CONF_ESP32_TOUCH_ID = 'esp32_touch_id'
|
||||
|
||||
TOUCH_PADS = {
|
||||
4: 'TOUCH_PAD_NUM0',
|
||||
0: 'TOUCH_PAD_NUM1',
|
||||
2: 'TOUCH_PAD_NUM2',
|
||||
15: 'TOUCH_PAD_NUM3',
|
||||
13: 'TOUCH_PAD_NUM4',
|
||||
12: 'TOUCH_PAD_NUM5',
|
||||
14: 'TOUCH_PAD_NUM6',
|
||||
27: 'TOUCH_PAD_NUM7',
|
||||
33: 'TOUCH_PAD_NUM8',
|
||||
32: 'TOUCH_PAD_NUM9',
|
||||
4: global_ns.TOUCH_PAD_NUM0,
|
||||
0: global_ns.TOUCH_PAD_NUM1,
|
||||
2: global_ns.TOUCH_PAD_NUM2,
|
||||
15: global_ns.TOUCH_PAD_NUM3,
|
||||
13: global_ns.TOUCH_PAD_NUM4,
|
||||
12: global_ns.TOUCH_PAD_NUM5,
|
||||
14: global_ns.TOUCH_PAD_NUM6,
|
||||
27: global_ns.TOUCH_PAD_NUM7,
|
||||
33: global_ns.TOUCH_PAD_NUM8,
|
||||
32: global_ns.TOUCH_PAD_NUM9,
|
||||
}
|
||||
|
||||
|
||||
@@ -31,19 +34,20 @@ def validate_touch_pad(value):
|
||||
return value
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('esp32_touch_pad'): cv.register_variable_id,
|
||||
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_PIN): validate_touch_pad,
|
||||
vol.Required(CONF_THRESHOLD): cv.uint16_t,
|
||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_ID_SCHEMA.schema)
|
||||
cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_variable_id(ESP32TouchComponent),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
hub = get_variable(None, type='binary_sensor::ESP32TouchComponent')
|
||||
touch_pad = RawExpression(TOUCH_PADS[config[CONF_PIN]])
|
||||
hub = None
|
||||
for hub in get_variable(config[CONF_ESP32_TOUCH_ID]):
|
||||
yield
|
||||
touch_pad = TOUCH_PADS[config[CONF_PIN]]
|
||||
rhs = hub.make_touch_pad(config[CONF_NAME], touch_pad, config[CONF_THRESHOLD])
|
||||
device = Pvariable('ESP32TouchBinarySensor', config[CONF_ID], rhs)
|
||||
binary_sensor.register_binary_sensor(device, config)
|
||||
binary_sensor.register_binary_sensor(rhs, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ESP32_TOUCH_BINARY_SENSOR'
|
||||
|
||||
@@ -3,22 +3,24 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_INVERTED, CONF_NAME, CONF_PIN
|
||||
from esphomeyaml.helpers import App, add, exp_gpio_input_pin, variable
|
||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
|
||||
from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application
|
||||
|
||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('gpio_binary_sensor'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): pins.GPIO_INPUT_PIN_SCHEMA
|
||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_SCHEMA.schema)
|
||||
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):
|
||||
rhs = App.make_gpio_binary_sensor(config[CONF_NAME], exp_gpio_input_pin(config[CONF_PIN]))
|
||||
gpio = variable('Application::MakeGPIOBinarySensor', config[CONF_ID], rhs)
|
||||
if CONF_INVERTED in config:
|
||||
add(gpio.Pgpio.set_inverted(config[CONF_INVERTED]))
|
||||
binary_sensor.setup_binary_sensor(gpio.Pgpio, config)
|
||||
binary_sensor.setup_mqtt_binary_sensor(gpio.Pmqtt, config)
|
||||
pin = None
|
||||
for pin in gpio_input_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_gpio_binary_sensor(config[CONF_NAME], pin)
|
||||
gpio = variable(config[CONF_MAKE_ID], rhs)
|
||||
binary_sensor.setup_binary_sensor(gpio.Pgpio, gpio.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_GPIO_BINARY_SENSOR'
|
||||
|
||||
77
esphomeyaml/components/binary_sensor/remote_receiver.py
Normal file
77
esphomeyaml/components/binary_sensor/remote_receiver.py
Normal file
@@ -0,0 +1,77 @@
|
||||
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.const import CONF_ADDRESS, CONF_COMMAND, CONF_DATA, \
|
||||
CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, CONF_PANASONIC, CONF_RAW, CONF_SONY
|
||||
from esphomeyaml.helpers import ArrayInitializer, Pvariable, get_variable
|
||||
|
||||
DEPENDENCIES = ['remote_receiver']
|
||||
|
||||
IR_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW]
|
||||
|
||||
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
|
||||
|
||||
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)],
|
||||
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(*IR_KEYS))
|
||||
|
||||
|
||||
def receiver_base(config):
|
||||
if CONF_LG in config:
|
||||
conf = config[CONF_LG]
|
||||
return LGReceiver.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS])
|
||||
elif CONF_NEC in config:
|
||||
conf = config[CONF_NEC]
|
||||
return NECReceiver.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND])
|
||||
elif CONF_PANASONIC in config:
|
||||
conf = config[CONF_PANASONIC]
|
||||
return PanasonicReceiver.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND])
|
||||
elif CONF_SONY in config:
|
||||
conf = config[CONF_SONY]
|
||||
return SonyReceiver.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS])
|
||||
elif CONF_RAW in config:
|
||||
data = ArrayInitializer(*config[CONF_RAW], multiline=False)
|
||||
return RawReceiver.new(config[CONF_NAME], data)
|
||||
else:
|
||||
raise ValueError("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'
|
||||
@@ -1,20 +1,21 @@
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, variable
|
||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
DEPENDENCIES = ['mqtt']
|
||||
|
||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('status_binary_sensor'): cv.register_variable_id,
|
||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_SCHEMA.schema)
|
||||
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):
|
||||
rhs = App.make_status_binary_sensor(config[CONF_NAME])
|
||||
status = variable('Application::MakeStatusBinarySensor', config[CONF_ID], rhs)
|
||||
binary_sensor.setup_binary_sensor(status.Pstatus, config)
|
||||
binary_sensor.setup_mqtt_binary_sensor(status.Pmqtt, config)
|
||||
status = variable(config[CONF_MAKE_ID], rhs)
|
||||
binary_sensor.setup_binary_sensor(status.Pstatus, status.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_STATUS_BINARY_SENSOR'
|
||||
|
||||
26
esphomeyaml/components/binary_sensor/template.py
Normal file
26
esphomeyaml/components/binary_sensor/template.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.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, Application, process_lambda, variable, optional, bool_
|
||||
|
||||
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):
|
||||
template_ = None
|
||||
for template_ in process_lambda(config[CONF_LAMBDA], [],
|
||||
return_type=optional.template(bool_)):
|
||||
yield
|
||||
rhs = App.make_template_binary_sensor(config[CONF_NAME], template_)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
binary_sensor.setup_binary_sensor(make.Ptemplate_, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_TEMPLATE_BINARY_SENSOR'
|
||||
39
esphomeyaml/components/cover/__init__.py
Normal file
39
esphomeyaml/components/cover/__init__.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_INTERNAL
|
||||
from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component, add
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
})
|
||||
|
||||
cover_ns = esphomelib_ns.namespace('cover')
|
||||
Cover = cover_ns.Cover
|
||||
MQTTCoverComponent = cover_ns.MQTTCoverComponent
|
||||
CoverState = cover_ns.CoverState
|
||||
COVER_OPEN = cover_ns.COVER_OPEN
|
||||
COVER_CLOSED = cover_ns.COVER_CLOSED
|
||||
OpenAction = cover_ns.OpenAction
|
||||
CloseAction = cover_ns.CloseAction
|
||||
StopAction = cover_ns.StopAction
|
||||
|
||||
COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(Cover),
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTCoverComponent),
|
||||
})
|
||||
|
||||
COVER_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(COVER_SCHEMA.schema)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def setup_cover(cover_obj, mqtt_obj, config):
|
||||
cover_var = Pvariable(config[CONF_ID], cover_obj, has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||
setup_cover_core_(cover_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_COVER'
|
||||
47
esphomeyaml/components/cover/template.py
Normal file
47
esphomeyaml/components/cover/template.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import automation
|
||||
from esphomeyaml.components import cover
|
||||
from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \
|
||||
CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC
|
||||
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable, optional
|
||||
|
||||
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):
|
||||
rhs = App.make_template_cover(config[CONF_NAME])
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
|
||||
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]))
|
||||
|
||||
cover.setup_cover(make.Ptemplate_, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_TEMPLATE_COVER'
|
||||
@@ -2,13 +2,14 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_PIN, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Pvariable
|
||||
|
||||
DALLAS_COMPONENT_CLASS = 'sensor::DallasComponent'
|
||||
DallasComponent = sensor.sensor_ns.DallasComponent
|
||||
|
||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
||||
cv.GenerateID('dallas'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(DallasComponent),
|
||||
vol.Required(CONF_PIN): pins.input_output_pin,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
})])
|
||||
@@ -17,7 +18,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
rhs = App.make_dallas_component(conf[CONF_PIN], conf.get(CONF_UPDATE_INTERVAL))
|
||||
Pvariable(DALLAS_COMPONENT_CLASS, conf[CONF_ID], rhs)
|
||||
Pvariable(conf[CONF_ID], rhs)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'
|
||||
|
||||
@@ -1,24 +1,36 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphomeyaml import config_validation as cv, pins
|
||||
from esphomeyaml.const import CONF_ID, CONF_RUN_CYCLES, CONF_RUN_DURATION, CONF_SLEEP_DURATION, \
|
||||
CONF_WAKEUP_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, add, exp_gpio_input_pin
|
||||
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_RUN_CYCLES, CONF_RUN_DURATION, \
|
||||
CONF_SLEEP_DURATION, CONF_WAKEUP_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, add, gpio_input_pin_expression, esphomelib_ns
|
||||
|
||||
|
||||
def validate_pin_number(value):
|
||||
valid_pins = [0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 39]
|
||||
if value not in valid_pins:
|
||||
if value[CONF_NUMBER] not in valid_pins:
|
||||
raise vol.Invalid(u"Only pins {} support wakeup"
|
||||
u"".format(', '.join(str(x) for x in valid_pins)))
|
||||
return value
|
||||
|
||||
|
||||
DeepSleepComponent = esphomelib_ns.DeepSleepComponent
|
||||
|
||||
WAKEUP_PIN_MODES = {
|
||||
'IGNORE': esphomelib_ns.WAKEUP_PIN_MODE_IGNORE,
|
||||
'KEEP_AWAKE': esphomelib_ns.WAKEUP_PIN_MODE_KEEP_AWAKE,
|
||||
'INVERT_WAKEUP': esphomelib_ns.WAKEUP_PIN_MODE_INVERT_WAKEUP,
|
||||
}
|
||||
|
||||
CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('deep_sleep'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent),
|
||||
vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.GPIO_INPUT_PIN_SCHEMA,
|
||||
pins.schema_validate_number(validate_pin_number)),
|
||||
vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema,
|
||||
validate_pin_number),
|
||||
vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32, vol.Upper,
|
||||
cv.one_of(*WAKEUP_PIN_MODES)),
|
||||
vol.Optional(CONF_RUN_CYCLES): cv.positive_int,
|
||||
vol.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
@@ -26,12 +38,16 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_deep_sleep_component()
|
||||
deep_sleep = Pvariable('DeepSleepComponent', config[CONF_ID], rhs)
|
||||
deep_sleep = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_SLEEP_DURATION in config:
|
||||
add(deep_sleep.set_sleep_duration(config[CONF_SLEEP_DURATION]))
|
||||
if CONF_WAKEUP_PIN in config:
|
||||
pin = exp_gpio_input_pin(config[CONF_WAKEUP_PIN])
|
||||
pin = None
|
||||
for pin in gpio_input_pin_expression(config[CONF_WAKEUP_PIN]):
|
||||
yield
|
||||
add(deep_sleep.set_wakeup_pin(pin))
|
||||
if CONF_WAKEUP_PIN_MODE in config:
|
||||
add(deep_sleep.set_wakeup_pin_mode(WAKEUP_PIN_MODES[config[CONF_WAKEUP_PIN_MODE]]))
|
||||
if CONF_RUN_CYCLES in config:
|
||||
add(deep_sleep.set_run_cycles(config[CONF_RUN_CYCLES]))
|
||||
if CONF_RUN_DURATION in config:
|
||||
|
||||
@@ -1,22 +1,5 @@
|
||||
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.helpers import App, Pvariable, add
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('esp32_ble'): cv.register_variable_id,
|
||||
vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
|
||||
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'
|
||||
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' "
|
||||
"component.")
|
||||
|
||||
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]
|
||||
|
||||
ESP32BLETracker = esphomelib_ns.ESP32BLETracker
|
||||
|
||||
CONF_MAJOR = 'major'
|
||||
CONF_MINOR = 'minor'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker),
|
||||
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'
|
||||
24
esphomeyaml/components/esp32_ble_tracker.py
Normal file
24
esphomeyaml/components/esp32_ble_tracker.py
Normal file
@@ -0,0 +1,24 @@
|
||||
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.helpers import App, Pvariable, add, esphomelib_ns
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
|
||||
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 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'
|
||||
@@ -1,11 +1,12 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphomeyaml import config_validation as cv
|
||||
from esphomeyaml.components import binary_sensor
|
||||
from esphomeyaml.const import CONF_ID, CONF_SETUP_MODE, CONF_IIR_FILTER, \
|
||||
CONF_SLEEP_DURATION, CONF_MEASUREMENT_DURATION, CONF_LOW_VOLTAGE_REFERENCE, \
|
||||
CONF_HIGH_VOLTAGE_REFERENCE, CONF_VOLTAGE_ATTENUATION, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.core import TimePeriod
|
||||
from esphomeyaml.helpers import App, Pvariable, add
|
||||
from esphomeyaml.helpers import App, Pvariable, add, global_ns
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
|
||||
@@ -17,33 +18,33 @@ def validate_voltage(values):
|
||||
value = cv.string(value)
|
||||
if not value.endswith('V'):
|
||||
value += 'V'
|
||||
if value not in values:
|
||||
raise vol.Invalid('Must be one of {}'.format(values))
|
||||
return value
|
||||
return cv.one_of(*values)(value)
|
||||
return validator
|
||||
|
||||
|
||||
LOW_VOLTAGE_REFERENCE = {
|
||||
'0.5V': 'TOUCH_LVOLT_0V5',
|
||||
'0.6V': 'TOUCH_LVOLT_0V6',
|
||||
'0.7V': 'TOUCH_LVOLT_0V7',
|
||||
'0.8V': 'TOUCH_LVOLT_0V8',
|
||||
'0.5V': global_ns.TOUCH_LVOLT_0V5,
|
||||
'0.6V': global_ns.TOUCH_LVOLT_0V6,
|
||||
'0.7V': global_ns.TOUCH_LVOLT_0V7,
|
||||
'0.8V': global_ns.TOUCH_LVOLT_0V8,
|
||||
}
|
||||
HIGH_VOLTAGE_REFERENCE = {
|
||||
'2.4V': 'TOUCH_HVOLT_2V4',
|
||||
'2.5V': 'TOUCH_HVOLT_2V5',
|
||||
'2.6V': 'TOUCH_HVOLT_2V6',
|
||||
'2.7V': 'TOUCH_HVOLT_2V7',
|
||||
'2.4V': global_ns.TOUCH_HVOLT_2V4,
|
||||
'2.5V': global_ns.TOUCH_HVOLT_2V5,
|
||||
'2.6V': global_ns.TOUCH_HVOLT_2V6,
|
||||
'2.7V': global_ns.TOUCH_HVOLT_2V7,
|
||||
}
|
||||
VOLTAGE_ATTENUATION = {
|
||||
'1.5V': 'TOUCH_HVOLT_ATTEN_1V5',
|
||||
'1V': 'TOUCH_HVOLT_ATTEN_1V',
|
||||
'0.5V': 'TOUCH_HVOLT_ATTEN_0V5',
|
||||
'0V': 'TOUCH_HVOLT_ATTEN_0V',
|
||||
'1.5V': global_ns.TOUCH_HVOLT_ATTEN_1V5,
|
||||
'1V': global_ns.TOUCH_HVOLT_ATTEN_1V,
|
||||
'0.5V': global_ns.TOUCH_HVOLT_ATTEN_0V5,
|
||||
'0V': global_ns.TOUCH_HVOLT_ATTEN_0V,
|
||||
}
|
||||
|
||||
ESP32TouchComponent = binary_sensor.binary_sensor_ns.ESP32TouchComponent
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('esp32_ble'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent),
|
||||
vol.Optional(CONF_SETUP_MODE): cv.boolean,
|
||||
vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_SLEEP_DURATION):
|
||||
@@ -58,13 +59,13 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_esp32_touch_component()
|
||||
touch = Pvariable('binary_sensor::ESP32TouchComponent', config[CONF_ID], rhs)
|
||||
touch = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_SETUP_MODE in config:
|
||||
add(touch.set_setup_mode(config[CONF_SETUP_MODE]))
|
||||
if CONF_IIR_FILTER in config:
|
||||
add(touch.set_iir_filter(config[CONF_IIR_FILTER]))
|
||||
if CONF_SLEEP_DURATION in config:
|
||||
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 6.6667)
|
||||
sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 0.15)
|
||||
add(touch.set_sleep_duration(sleep_duration))
|
||||
if CONF_MEASUREMENT_DURATION in config:
|
||||
measurement_duration = int(config[CONF_MEASUREMENT_DURATION].total_microseconds * 0.125)
|
||||
|
||||
@@ -1,26 +1,68 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, \
|
||||
CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
|
||||
from esphomeyaml.helpers import add, setup_mqtt_component
|
||||
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_INTERNAL
|
||||
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
})
|
||||
|
||||
fan_ns = esphomelib_ns.namespace('fan')
|
||||
FanState = fan_ns.FanState
|
||||
MQTTFanComponent = fan_ns.MQTTFanComponent
|
||||
MakeFan = Application.MakeFan
|
||||
TurnOnAction = fan_ns.TurnOnAction
|
||||
TurnOffAction = fan_ns.TurnOffAction
|
||||
ToggleAction = fan_ns.ToggleAction
|
||||
FanSpeed = fan_ns.FanSpeed
|
||||
FAN_SPEED_OFF = fan_ns.FAN_SPEED_OFF
|
||||
FAN_SPEED_LOW = fan_ns.FAN_SPEED_LOW
|
||||
FAN_SPEED_MEDIUM = fan_ns.FAN_SPEED_MEDIUM
|
||||
FAN_SPEED_HIGH = fan_ns.FAN_SPEED_HIGH
|
||||
|
||||
FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(FanState),
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTFanComponent),
|
||||
vol.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic,
|
||||
}).extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA.schema)
|
||||
})
|
||||
|
||||
FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema)
|
||||
|
||||
|
||||
def setup_mqtt_fan(obj, config):
|
||||
FAN_SPEEDS = {
|
||||
'OFF': FAN_SPEED_OFF,
|
||||
'LOW': FAN_SPEED_LOW,
|
||||
'MEDIUM': FAN_SPEED_MEDIUM,
|
||||
'HIGH': FAN_SPEED_HIGH,
|
||||
}
|
||||
|
||||
|
||||
def validate_fan_speed(value):
|
||||
return vol.All(vol.Upper, cv.one_of(*FAN_SPEEDS))(value)
|
||||
|
||||
|
||||
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:
|
||||
add(obj.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:
|
||||
add(obj.set_custom_oscillation_command_topic(config[CONF_OSCILLATION_COMMAND_TOPIC]))
|
||||
add(mqtt_var.set_custom_oscillation_command_topic(config[CONF_OSCILLATION_COMMAND_TOPIC]))
|
||||
if CONF_SPEED_STATE_TOPIC in config:
|
||||
add(obj.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC]))
|
||||
add(mqtt_var.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC]))
|
||||
if CONF_SPEED_COMMAND_TOPIC in config:
|
||||
add(obj.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]))
|
||||
setup_mqtt_component(obj, config)
|
||||
add(mqtt_var.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]))
|
||||
setup_mqtt_component(mqtt_var, config)
|
||||
|
||||
|
||||
def setup_fan(fan_obj, mqtt_obj, config):
|
||||
fan_var = Pvariable(config[CONF_ID], fan_obj, has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||
setup_fan_core_(fan_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_FAN'
|
||||
|
||||
@@ -2,22 +2,28 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import fan
|
||||
from esphomeyaml.const import CONF_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
|
||||
|
||||
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('binary_fan'): cv.register_variable_id,
|
||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
|
||||
})
|
||||
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output = get_variable(config[CONF_OUTPUT])
|
||||
output = None
|
||||
for output in get_variable(config[CONF_OUTPUT]):
|
||||
yield
|
||||
|
||||
rhs = App.make_fan(config[CONF_NAME])
|
||||
fan_struct = variable('Application::MakeFan', config[CONF_ID], rhs)
|
||||
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
add(fan_struct.Poutput.set_binary(output))
|
||||
if CONF_OSCILLATION_OUTPUT in config:
|
||||
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
|
||||
oscillation_output = None
|
||||
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
|
||||
yield
|
||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||
fan.setup_mqtt_fan(fan_struct.Pmqtt, config)
|
||||
|
||||
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
||||
|
||||
@@ -2,29 +2,31 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import fan
|
||||
from esphomeyaml.const import CONF_HIGH, CONF_ID, CONF_LOW, \
|
||||
CONF_MEDIUM, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_SPEED, \
|
||||
CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
|
||||
from esphomeyaml.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CONF_NAME, \
|
||||
CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, \
|
||||
CONF_SPEED_STATE_TOPIC
|
||||
from esphomeyaml.helpers import App, add, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('speed_fan'): cv.register_variable_id,
|
||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
||||
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_SPEED_COMMAND_TOPIC): cv.subscribe_topic,
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.variable_id,
|
||||
vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_SPEED): vol.Schema({
|
||||
vol.Required(CONF_LOW): cv.zero_to_one_float,
|
||||
vol.Required(CONF_MEDIUM): cv.zero_to_one_float,
|
||||
vol.Required(CONF_HIGH): cv.zero_to_one_float,
|
||||
vol.Required(CONF_LOW): cv.percentage,
|
||||
vol.Required(CONF_MEDIUM): cv.percentage,
|
||||
vol.Required(CONF_HIGH): cv.percentage,
|
||||
}),
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output = get_variable(config[CONF_OUTPUT])
|
||||
output = None
|
||||
for output in get_variable(config[CONF_OUTPUT]):
|
||||
yield
|
||||
rhs = App.make_fan(config[CONF_NAME])
|
||||
fan_struct = variable('Application::MakeFan', config[CONF_ID], rhs)
|
||||
fan_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
if CONF_SPEED in config:
|
||||
speeds = config[CONF_SPEED]
|
||||
add(fan_struct.Poutput.set_speed(output, 0.0,
|
||||
@@ -35,6 +37,9 @@ def to_code(config):
|
||||
add(fan_struct.Poutput.set_speed(output))
|
||||
|
||||
if CONF_OSCILLATION_OUTPUT in config:
|
||||
oscillation_output = get_variable(config[CONF_OSCILLATION_OUTPUT])
|
||||
oscillation_output = None
|
||||
for oscillation_output in get_variable(config[CONF_OSCILLATION_OUTPUT]):
|
||||
yield
|
||||
add(fan_struct.Poutput.set_oscillation(oscillation_output))
|
||||
fan.setup_mqtt_fan(fan_struct.Pmqtt, config)
|
||||
|
||||
fan.setup_fan(fan_struct.Pstate, fan_struct.Pmqtt, config)
|
||||
|
||||
@@ -4,25 +4,28 @@ import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CONF_ID, \
|
||||
CONF_RECEIVE_TIMEOUT
|
||||
from esphomeyaml.helpers import App, add, Pvariable
|
||||
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
|
||||
|
||||
I2CComponent = esphomelib_ns.I2CComponent
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('i2c'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(I2CComponent),
|
||||
vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin,
|
||||
vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin,
|
||||
vol.Optional(CONF_FREQUENCY): cv.positive_int,
|
||||
vol.Optional(CONF_RECEIVE_TIMEOUT): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)),
|
||||
vol.Optional(CONF_SCAN): cv.boolean,
|
||||
|
||||
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):
|
||||
rhs = App.init_i2c(config[CONF_SDA], config[CONF_SCL], config.get(CONF_SCAN))
|
||||
i2c = Pvariable('I2CComponent', config[CONF_ID], rhs)
|
||||
i2c = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_FREQUENCY in config:
|
||||
add(i2c.set_frequency(config[CONF_FREQUENCY]))
|
||||
if CONF_RECEIVE_TIMEOUT in config:
|
||||
add(i2c.set_receive_timeout(config[CONF_RECEIVE_TIMEOUT]))
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_I2C'
|
||||
|
||||
@@ -1,25 +1,6 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, exp_gpio_output_pin
|
||||
|
||||
IR_TRANSMITTER_COMPONENT_CLASS = 'switch_::IRTransmitterComponent'
|
||||
|
||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
|
||||
cv.GenerateID('ir_transmitter'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int),
|
||||
vol.Range(min=1, max=100)),
|
||||
})])
|
||||
|
||||
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
pin = exp_gpio_output_pin(conf[CONF_PIN])
|
||||
rhs = App.make_ir_transmitter(pin, conf.get(CONF_CARRIER_DUTY_PERCENT))
|
||||
Pvariable(IR_TRANSMITTER_COMPONENT_CLASS, conf[CONF_ID], rhs)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_IR_TRANSMITTER'
|
||||
def CONFIG_SCHEMA(config):
|
||||
raise vol.Invalid("The ir_transmitter component has been renamed to "
|
||||
"remote_transmitter because of 433MHz signal support.")
|
||||
|
||||
@@ -1,17 +1,43 @@
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT
|
||||
from esphomeyaml.helpers import add
|
||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, \
|
||||
CONF_MQTT_ID, CONF_INTERNAL
|
||||
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
}).extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA.schema)
|
||||
})
|
||||
|
||||
light_ns = esphomelib_ns.namespace('light')
|
||||
LightState = light_ns.LightState
|
||||
MQTTJSONLightComponent = light_ns.MQTTJSONLightComponent
|
||||
ToggleAction = light_ns.ToggleAction
|
||||
TurnOffAction = light_ns.TurnOffAction
|
||||
TurnOnAction = light_ns.TurnOnAction
|
||||
MakeLight = Application.MakeLight
|
||||
|
||||
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(LightState),
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTJSONLightComponent),
|
||||
})
|
||||
|
||||
LIGHT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(LIGHT_SCHEMA.schema)
|
||||
|
||||
|
||||
def setup_light_component(obj, 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:
|
||||
add(obj.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:
|
||||
add(obj.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
|
||||
add(light_var.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
|
||||
|
||||
setup_mqtt_component(mqtt_var, config)
|
||||
|
||||
|
||||
def setup_light(light_obj, mqtt_obj, config):
|
||||
light_var = Pvariable(config[CONF_ID], light_obj, has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||
setup_light_core_(light_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_LIGHT'
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME, CONF_OUTPUT
|
||||
from esphomeyaml.helpers import App, get_variable, variable, setup_mqtt_component
|
||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
|
||||
from esphomeyaml.helpers import App, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('binary_light'): cv.register_variable_id,
|
||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
||||
})
|
||||
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output = get_variable(config[CONF_OUTPUT])
|
||||
output = None
|
||||
for output in get_variable(config[CONF_OUTPUT]):
|
||||
yield
|
||||
rhs = App.make_binary_light(config[CONF_NAME], output)
|
||||
light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
|
||||
setup_mqtt_component(light_struct.Pmqtt, config)
|
||||
light.setup_light_component(light_struct.Pstate, config)
|
||||
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||
|
||||
@@ -3,10 +3,12 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||
CONF_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER
|
||||
from esphomeyaml.helpers import App, RawExpression, TemplateArguments, add, setup_mqtt_component, \
|
||||
variable
|
||||
CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, \
|
||||
CONF_RGB_ORDER
|
||||
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
||||
get_variable, variable
|
||||
|
||||
TYPES = [
|
||||
'NEOPIXEL',
|
||||
@@ -51,24 +53,27 @@ def validate(value):
|
||||
return value
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('fast_led_clockless_light'): cv.register_variable_id,
|
||||
MakeFastLEDLight = Application.MakeFastLEDLight
|
||||
|
||||
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, vol.Any(*TYPES)),
|
||||
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_PIN): pins.output_pin,
|
||||
|
||||
vol.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
|
||||
vol.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
|
||||
vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, vol.Any(*RGB_ORDERS)),
|
||||
vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, cv.one_of(*RGB_ORDERS)),
|
||||
|
||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||
}), validate)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_fast_led_light(config[CONF_NAME])
|
||||
make = variable('Application::MakeFastLEDLight', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
fast_led = make.Pfast_led
|
||||
|
||||
rgb_order = None
|
||||
@@ -81,8 +86,13 @@ def to_code(config):
|
||||
if CONF_MAX_REFRESH_RATE in config:
|
||||
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
||||
|
||||
setup_mqtt_component(make.Pmqtt, config)
|
||||
light.setup_light_component(make.Pstate, config)
|
||||
if CONF_POWER_SUPPLY in config:
|
||||
power_supply = None
|
||||
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||
yield
|
||||
add(fast_led.set_power_supply(power_supply))
|
||||
|
||||
light.setup_light(make.Pstate, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
|
||||
|
||||
@@ -3,11 +3,12 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \
|
||||
CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, \
|
||||
CONF_NUM_LEDS, CONF_RGB_ORDER
|
||||
from esphomeyaml.helpers import App, TemplateArguments, add, setup_mqtt_component, variable, \
|
||||
RawExpression
|
||||
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
|
||||
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \
|
||||
get_variable, variable
|
||||
|
||||
CHIPSETS = [
|
||||
'LPD8806',
|
||||
@@ -29,25 +30,28 @@ RGB_ORDERS = [
|
||||
'BGR',
|
||||
]
|
||||
|
||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('fast_led_spi_light'): cv.register_variable_id,
|
||||
MakeFastLEDLight = Application.MakeFastLEDLight
|
||||
|
||||
vol.Required(CONF_CHIPSET): vol.All(vol.Upper, vol.Any(*CHIPSETS)),
|
||||
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_DATA_PIN): pins.output_pin,
|
||||
vol.Required(CONF_CLOCK_PIN): pins.output_pin,
|
||||
|
||||
vol.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
|
||||
vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, vol.Any(*RGB_ORDERS)),
|
||||
vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, cv.one_of(*RGB_ORDERS)),
|
||||
vol.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
|
||||
|
||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_fast_led_light(config[CONF_NAME])
|
||||
make = variable('Application::MakeFastLEDLight', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
fast_led = make.Pfast_led
|
||||
|
||||
rgb_order = None
|
||||
@@ -62,8 +66,13 @@ def to_code(config):
|
||||
if CONF_MAX_REFRESH_RATE in config:
|
||||
add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
|
||||
|
||||
setup_mqtt_component(make.Pmqtt, config)
|
||||
light.setup_light_component(make.Pstate, config)
|
||||
if CONF_POWER_SUPPLY in config:
|
||||
power_supply = None
|
||||
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||
yield
|
||||
add(fast_led.set_power_supply(power_supply))
|
||||
|
||||
light.setup_light(make.Pstate, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
|
||||
|
||||
@@ -2,21 +2,22 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, \
|
||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
|
||||
CONF_NAME, CONF_OUTPUT
|
||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
|
||||
from esphomeyaml.helpers import App, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('monochromatic_light'): cv.register_variable_id,
|
||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
||||
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output = get_variable(config[CONF_OUTPUT])
|
||||
output = None
|
||||
for output in get_variable(config[CONF_OUTPUT]):
|
||||
yield
|
||||
rhs = App.make_monochromatic_light(config[CONF_NAME], output)
|
||||
light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
|
||||
setup_mqtt_component(light_struct.Pmqtt, config)
|
||||
light.setup_light_component(light_struct.Pstate, config)
|
||||
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||
|
||||
@@ -3,24 +3,29 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||
CONF_GREEN, CONF_ID, CONF_NAME, CONF_RED
|
||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
|
||||
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED
|
||||
from esphomeyaml.helpers import App, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('rgb_light'): cv.register_variable_id,
|
||||
vol.Required(CONF_RED): cv.variable_id,
|
||||
vol.Required(CONF_GREEN): cv.variable_id,
|
||||
vol.Required(CONF_BLUE): cv.variable_id,
|
||||
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.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
red = get_variable(config[CONF_RED])
|
||||
green = get_variable(config[CONF_GREEN])
|
||||
blue = get_variable(config[CONF_BLUE])
|
||||
red = None
|
||||
for red in get_variable(config[CONF_RED]):
|
||||
yield
|
||||
green = None
|
||||
for green in get_variable(config[CONF_GREEN]):
|
||||
yield
|
||||
blue = None
|
||||
for blue in get_variable(config[CONF_BLUE]):
|
||||
yield
|
||||
rhs = App.make_rgb_light(config[CONF_NAME], red, green, blue)
|
||||
light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
|
||||
setup_mqtt_component(light_struct.Pmqtt, config)
|
||||
light.setup_light_component(light_struct.Pstate, config)
|
||||
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||
|
||||
@@ -3,26 +3,33 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import light
|
||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
|
||||
CONF_GREEN, CONF_ID, CONF_NAME, CONF_RED, CONF_WHITE
|
||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
|
||||
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE
|
||||
from esphomeyaml.helpers import App, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('rgbw_light'): cv.register_variable_id,
|
||||
vol.Required(CONF_RED): cv.variable_id,
|
||||
vol.Required(CONF_GREEN): cv.variable_id,
|
||||
vol.Required(CONF_BLUE): cv.variable_id,
|
||||
vol.Required(CONF_WHITE): cv.variable_id,
|
||||
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_WHITE): cv.use_variable_id(None),
|
||||
vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
|
||||
vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
red = get_variable(config[CONF_RED])
|
||||
green = get_variable(config[CONF_GREEN])
|
||||
blue = get_variable(config[CONF_BLUE])
|
||||
white = get_variable(config[CONF_WHITE])
|
||||
red = None
|
||||
for red in get_variable(config[CONF_RED]):
|
||||
yield
|
||||
green = None
|
||||
for green in get_variable(config[CONF_GREEN]):
|
||||
yield
|
||||
blue = None
|
||||
for blue in get_variable(config[CONF_BLUE]):
|
||||
yield
|
||||
white = None
|
||||
for white in get_variable(config[CONF_WHITE]):
|
||||
yield
|
||||
rhs = App.make_rgbw_light(config[CONF_NAME], red, green, blue, white)
|
||||
light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
|
||||
setup_mqtt_component(light_struct.Pmqtt, config)
|
||||
light.setup_light_component(light_struct.Pstate, config)
|
||||
light_struct = variable(config[CONF_MAKE_ID], rhs)
|
||||
light.setup_light(light_struct.Pstate, light_struct.Pmqtt, config)
|
||||
|
||||
@@ -1,51 +1,61 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGGER, CONF_LOGS, \
|
||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGS, \
|
||||
CONF_TX_BUFFER_SIZE
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import App, Pvariable, RawExpression, add
|
||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, global_ns
|
||||
|
||||
LOG_LEVELS = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE', 'VERY_VERBOSE']
|
||||
LOG_LEVELS = {
|
||||
'NONE': global_ns.ESPHOMELIB_LOG_LEVEL_NONE,
|
||||
'ERROR': global_ns.ESPHOMELIB_LOG_LEVEL_ERROR,
|
||||
'WARN': global_ns.ESPHOMELIB_LOG_LEVEL_WARN,
|
||||
'INFO': global_ns.ESPHOMELIB_LOG_LEVEL_INFO,
|
||||
'DEBUG': global_ns.ESPHOMELIB_LOG_LEVEL_DEBUG,
|
||||
'VERBOSE': global_ns.ESPHOMELIB_LOG_LEVEL_VERBOSE,
|
||||
'VERY_VERBOSE': global_ns.ESPHOMELIB_LOG_LEVEL_VERY_VERBOSE,
|
||||
}
|
||||
|
||||
LOG_LEVEL_SEVERITY = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE', 'VERY_VERBOSE']
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
is_log_level = vol.All(vol.Upper, vol.Any(*LOG_LEVELS))
|
||||
is_log_level = vol.All(vol.Upper, cv.one_of(*LOG_LEVELS))
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID(CONF_LOGGER): cv.register_variable_id,
|
||||
|
||||
def validate_local_no_higher_than_global(value):
|
||||
global_level = value.get(CONF_LEVEL, 'DEBUG')
|
||||
for tag, level in value.get(CONF_LOGS, {}).iteritems():
|
||||
if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level):
|
||||
raise ESPHomeYAMLError(u"The local log level {} for {} must be less severe than the "
|
||||
u"global log level {}.".format(level, tag, global_level))
|
||||
return value
|
||||
|
||||
|
||||
LogComponent = esphomelib_ns.LogComponent
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(LogComponent),
|
||||
vol.Optional(CONF_BAUD_RATE): cv.positive_int,
|
||||
vol.Optional(CONF_TX_BUFFER_SIZE): cv.positive_int,
|
||||
vol.Optional(CONF_TX_BUFFER_SIZE): cv.validate_bytes,
|
||||
vol.Optional(CONF_LEVEL): is_log_level,
|
||||
vol.Optional(CONF_LOGS): vol.Schema({
|
||||
cv.string: is_log_level,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
def esphomelib_log_level(level):
|
||||
return u'ESPHOMELIB_LOG_LEVEL_{}'.format(level)
|
||||
|
||||
|
||||
def exp_log_level(level):
|
||||
return RawExpression(esphomelib_log_level(level))
|
||||
}), validate_local_no_higher_than_global)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.init_log(config.get(CONF_BAUD_RATE))
|
||||
log = Pvariable(u'LogComponent', config[CONF_ID], rhs)
|
||||
log = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_TX_BUFFER_SIZE in config:
|
||||
add(log.set_tx_buffer_size(config[CONF_TX_BUFFER_SIZE]))
|
||||
if CONF_LEVEL in config:
|
||||
add(log.set_global_log_level(exp_log_level(config[CONF_LEVEL])))
|
||||
add(log.set_global_log_level(LOG_LEVELS[config[CONF_LEVEL]]))
|
||||
for tag, level in config.get(CONF_LOGS, {}).iteritems():
|
||||
global_level = config.get(CONF_LEVEL, 'DEBUG')
|
||||
if LOG_LEVELS.index(level) > LOG_LEVELS.index(global_level):
|
||||
raise ESPHomeYAMLError(u"The local log level {} for {} must be less severe than the "
|
||||
u"global log level {}.".format(level, tag, global_level))
|
||||
add(log.set_log_level(tag, exp_log_level(level)))
|
||||
add(log.set_log_level(tag, LOG_LEVELS[level]))
|
||||
|
||||
|
||||
def required_build_flags(config):
|
||||
if CONF_LEVEL in config:
|
||||
return u'-DESPHOMELIB_LOG_LEVEL={}'.format(esphomelib_log_level(config[CONF_LEVEL]))
|
||||
return u'-DESPHOMELIB_LOG_LEVEL={}'.format(str(LOG_LEVELS[config[CONF_LEVEL]]))
|
||||
return None
|
||||
|
||||
@@ -3,22 +3,25 @@ import re
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import automation
|
||||
from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, CONF_DISCOVERY, \
|
||||
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_SSL_FINGERPRINTS, CONF_ID, CONF_LOG_TOPIC, \
|
||||
CONF_MQTT, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, CONF_TOPIC, \
|
||||
CONF_TOPIC_PREFIX, CONF_USERNAME, CONF_WILL_MESSAGE, CONF_KEEPALIVE
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, StructInitializer, add, \
|
||||
exp_empty_optional, RawExpression
|
||||
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LOG_TOPIC, \
|
||||
CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, CONF_RETAIN, \
|
||||
CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \
|
||||
CONF_WILL_MESSAGE, CONF_REBOOT_TIMEOUT
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, RawExpression, \
|
||||
StructInitializer, \
|
||||
TemplateArguments, add, esphomelib_ns, optional, std_string
|
||||
|
||||
|
||||
def validate_message_just_topic(value):
|
||||
value = cv.publish_topic(value)
|
||||
return {CONF_TOPIC: value}
|
||||
return MQTT_MESSAGE_BASE({CONF_TOPIC: value})
|
||||
|
||||
|
||||
MQTT_MESSAGE_BASE = vol.Schema({
|
||||
vol.Required(CONF_TOPIC): cv.publish_topic,
|
||||
vol.Optional(CONF_QOS, default=0): vol.All(vol.Coerce(int), vol.In([0, 1, 2])),
|
||||
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
|
||||
vol.Optional(CONF_RETAIN, default=True): cv.boolean,
|
||||
})
|
||||
|
||||
@@ -28,12 +31,15 @@ MQTT_MESSAGE_SCHEMA = vol.Any(None, MQTT_MESSAGE_BASE.extend({
|
||||
vol.Required(CONF_PAYLOAD): cv.mqtt_payload,
|
||||
}))
|
||||
|
||||
mqtt_ns = esphomelib_ns.namespace('mqtt')
|
||||
MQTTMessage = mqtt_ns.MQTTMessage
|
||||
MQTTClientComponent = mqtt_ns.MQTTClientComponent
|
||||
MQTTPublishAction = mqtt_ns.MQTTPublishAction
|
||||
MQTTMessageTrigger = mqtt_ns.MQTTMessageTrigger
|
||||
|
||||
|
||||
def validate_broker(value):
|
||||
value = cv.string_strict(value)
|
||||
if value.endswith(u'.local'):
|
||||
raise vol.Invalid(u"MQTT server addresses ending with '.local' are currently unsupported."
|
||||
u" Please use the static IP instead.")
|
||||
if u':' in value:
|
||||
raise vol.Invalid(u"Please specify the port using the port: option")
|
||||
if not value:
|
||||
@@ -49,7 +55,7 @@ def validate_fingerprint(value):
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID(CONF_MQTT): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
|
||||
vol.Required(CONF_BROKER): validate_broker,
|
||||
vol.Optional(CONF_PORT, default=1883): cv.port,
|
||||
vol.Optional(CONF_USERNAME, default=''): cv.string,
|
||||
@@ -65,14 +71,20 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_SSL_FINGERPRINTS): vol.All(cv.only_on_esp8266,
|
||||
cv.ensure_list, [validate_fingerprint]),
|
||||
vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds,
|
||||
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.Optional(CONF_QOS, default=0): cv.mqtt_qos,
|
||||
})])
|
||||
})
|
||||
|
||||
|
||||
def exp_mqtt_message(config):
|
||||
if config is None:
|
||||
return exp_empty_optional('mqtt::MQTTMessage')
|
||||
return optional(TemplateArguments(MQTTMessage))
|
||||
exp = StructInitializer(
|
||||
'mqtt::MQTTMessage',
|
||||
MQTTMessage,
|
||||
('topic', config[CONF_TOPIC]),
|
||||
('payload', config.get(CONF_PAYLOAD, "")),
|
||||
('qos', config[CONF_QOS]),
|
||||
@@ -84,7 +96,7 @@ def exp_mqtt_message(config):
|
||||
def to_code(config):
|
||||
rhs = App.init_mqtt(config[CONF_BROKER], config[CONF_PORT],
|
||||
config[CONF_USERNAME], config[CONF_PASSWORD])
|
||||
mqtt = Pvariable('mqtt::MQTTClientComponent', config[CONF_ID], rhs)
|
||||
mqtt = Pvariable(config[CONF_ID], rhs)
|
||||
if not config.get(CONF_DISCOVERY, True):
|
||||
add(mqtt.disable_discovery())
|
||||
if CONF_DISCOVERY_RETAIN in config or CONF_DISCOVERY_PREFIX in config:
|
||||
@@ -95,13 +107,13 @@ def to_code(config):
|
||||
add(mqtt.set_topic_prefix(config[CONF_TOPIC_PREFIX]))
|
||||
if CONF_BIRTH_MESSAGE in config:
|
||||
birth_message = config[CONF_BIRTH_MESSAGE]
|
||||
if birth_message is None:
|
||||
if not birth_message:
|
||||
add(mqtt.disable_birth_message())
|
||||
else:
|
||||
add(mqtt.set_birth_message(exp_mqtt_message(birth_message)))
|
||||
if CONF_WILL_MESSAGE in config:
|
||||
will_message = config[CONF_WILL_MESSAGE]
|
||||
if will_message is None:
|
||||
if not will_message:
|
||||
add(mqtt.disable_last_will())
|
||||
else:
|
||||
add(mqtt.set_last_will(exp_mqtt_message(will_message)))
|
||||
@@ -109,16 +121,23 @@ def to_code(config):
|
||||
add(mqtt.set_client_id(config[CONF_CLIENT_ID]))
|
||||
if CONF_LOG_TOPIC in config:
|
||||
log_topic = config[CONF_LOG_TOPIC]
|
||||
if log_topic is None:
|
||||
if not log_topic:
|
||||
add(mqtt.disable_log_message())
|
||||
else:
|
||||
add(mqtt.set_log_topic(exp_mqtt_message(log_topic)))
|
||||
add(mqtt.set_log_message_template(exp_mqtt_message(log_topic)))
|
||||
if CONF_SSL_FINGERPRINTS in config:
|
||||
for fingerprint in config[CONF_SSL_FINGERPRINTS]:
|
||||
arr = [RawExpression("0x{}".format(fingerprint[i:i + 2])) for i in range(0, 40, 2)]
|
||||
add(mqtt.add_ssl_fingerprint(ArrayInitializer(*arr, multiline=False)))
|
||||
if CONF_KEEPALIVE in config:
|
||||
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, []):
|
||||
rhs = mqtt.make_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS])
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, std_string, conf)
|
||||
|
||||
|
||||
def required_build_flags(config):
|
||||
|
||||
@@ -8,12 +8,14 @@ from esphomeyaml import core
|
||||
from esphomeyaml.const import CONF_ID, CONF_OTA, CONF_PASSWORD, CONF_PORT, CONF_SAFE_MODE, \
|
||||
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import App, Pvariable, add
|
||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
OTAComponent = esphomelib_ns.OTAComponent
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID(CONF_OTA): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(OTAComponent),
|
||||
vol.Optional(CONF_SAFE_MODE, default=True): cv.boolean,
|
||||
# TODO Num attempts + wait time
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
@@ -23,10 +25,12 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.init_ota()
|
||||
ota = Pvariable('OTAComponent', config[CONF_ID], rhs)
|
||||
ota = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_PASSWORD in config:
|
||||
hash_ = hashlib.md5(config[CONF_PASSWORD].encode()).hexdigest()
|
||||
add(ota.set_auth_password_hash(hash_))
|
||||
if CONF_PORT in config:
|
||||
add(ota.set_port(config[CONF_PORT]))
|
||||
if config[CONF_SAFE_MODE]:
|
||||
add(ota.start_safe_mode())
|
||||
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_POWER_SUPPLY, CONF_INVERTED, CONF_MAX_POWER
|
||||
from esphomeyaml.helpers import get_variable, add
|
||||
from esphomeyaml.components.power_supply import PowerSupplyComponent
|
||||
from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY
|
||||
from esphomeyaml.helpers import add, esphomelib_ns, get_variable
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_POWER_SUPPLY): cv.variable_id,
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
}).extend(cv.REQUIRED_ID_SCHEMA.schema)
|
||||
|
||||
FLOAT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_MAX_POWER): cv.zero_to_one_float,
|
||||
})
|
||||
|
||||
BINARY_OUTPUT_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent),
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
})
|
||||
|
||||
def setup_output_platform(obj, config, skip_power_supply=False):
|
||||
BINARY_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_OUTPUT_SCHEMA.schema)
|
||||
|
||||
FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({
|
||||
vol.Optional(CONF_MAX_POWER): cv.percentage,
|
||||
})
|
||||
|
||||
FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema)
|
||||
|
||||
output_ns = esphomelib_ns.namespace('output')
|
||||
|
||||
|
||||
def setup_output_platform_(obj, config, skip_power_supply=False):
|
||||
if CONF_INVERTED in config:
|
||||
add(obj.set_inverted(config[CONF_INVERTED]))
|
||||
if not skip_power_supply and CONF_POWER_SUPPLY in config:
|
||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
||||
power_supply = None
|
||||
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||
yield
|
||||
add(obj.set_power_supply(power_supply))
|
||||
if CONF_MAX_POWER in config:
|
||||
add(obj.set_max_power(config[CONF_MAX_POWER]))
|
||||
|
||||
|
||||
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'
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphomeyaml import pins
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import output
|
||||
from esphomeyaml.const import CONF_ID, CONF_PIN, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import App, Pvariable, exp_gpio_output_pin
|
||||
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP8266]
|
||||
|
||||
|
||||
def valid_pwm_pin(value):
|
||||
if value >= 16:
|
||||
if value[CONF_NUMBER] > 16:
|
||||
raise ESPHomeYAMLError(u"ESP8266: Only pins 0-16 support PWM.")
|
||||
return value
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = output.FLOAT_PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_PIN): vol.All(pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
pins.schema_validate_number(valid_pwm_pin)),
|
||||
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):
|
||||
pin = exp_gpio_output_pin(config[CONF_PIN])
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_esp8266_pwm_output(pin)
|
||||
gpio = Pvariable('output::ESP8266PWMOutput', config[CONF_ID], rhs)
|
||||
gpio = Pvariable(config[CONF_ID], rhs)
|
||||
output.setup_output_platform(gpio, config)
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphomeyaml import pins
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import output
|
||||
from esphomeyaml.const import CONF_ID, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, exp_gpio_output_pin
|
||||
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression
|
||||
|
||||
PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
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):
|
||||
pin = exp_gpio_output_pin(config[CONF_PIN])
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_gpio_output(pin)
|
||||
gpio = Pvariable('output::GPIOBinaryOutputComponent', config[CONF_ID], rhs)
|
||||
gpio = Pvariable(config[CONF_ID], rhs)
|
||||
output.setup_output_platform(gpio, config)
|
||||
|
||||
|
||||
|
||||
@@ -15,12 +15,15 @@ def validate_frequency_bit_depth(obj):
|
||||
bit_depth = obj.get(CONF_BIT_DEPTH, 12)
|
||||
max_freq = APB_CLOCK_FREQ / (2**bit_depth)
|
||||
if frequency > max_freq:
|
||||
raise vol.Invalid('Maximum frequency for bit depth {} is {}'.format(bit_depth, max_freq))
|
||||
raise vol.Invalid('Maximum frequency for bit depth {} is {}Hz'.format(bit_depth, max_freq))
|
||||
return obj
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(output.FLOAT_PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_PIN): vol.All(pins.output_pin, vol.Range(min=0, max=33)),
|
||||
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.Optional(CONF_FREQUENCY): cv.frequency,
|
||||
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))
|
||||
@@ -32,7 +35,7 @@ def to_code(config):
|
||||
if frequency is None and CONF_BIT_DEPTH in config:
|
||||
frequency = 1000
|
||||
rhs = App.make_ledc_output(config[CONF_PIN], frequency, config.get(CONF_BIT_DEPTH))
|
||||
ledc = Pvariable('output::LEDCOutputComponent', config[CONF_ID], rhs)
|
||||
ledc = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_CHANNEL in config:
|
||||
add(ledc.set_channel(config[CONF_CHANNEL]))
|
||||
output.setup_output_platform(ledc, config)
|
||||
|
||||
@@ -2,26 +2,32 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import output
|
||||
from esphomeyaml.components.pca9685 import PCA9685_COMPONENT_TYPE
|
||||
from esphomeyaml.components.pca9685 import PCA9685OutputComponent
|
||||
from esphomeyaml.const import CONF_CHANNEL, CONF_ID, CONF_PCA9685_ID, CONF_POWER_SUPPLY
|
||||
from esphomeyaml.helpers import Pvariable, get_variable
|
||||
|
||||
DEPENDENCIES = ['pca9685']
|
||||
|
||||
PLATFORM_SCHEMA = output.FLOAT_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.Range(min=0, max=15)),
|
||||
vol.Optional(CONF_PCA9685_ID): cv.variable_id,
|
||||
cv.GenerateID(CONF_PCA9685_ID): cv.use_variable_id(PCA9685OutputComponent),
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
power_supply = None
|
||||
if CONF_POWER_SUPPLY in config:
|
||||
power_supply = get_variable(config[CONF_POWER_SUPPLY])
|
||||
pca9685 = get_variable(config.get(CONF_PCA9685_ID), PCA9685_COMPONENT_TYPE)
|
||||
for power_supply in get_variable(config[CONF_POWER_SUPPLY]):
|
||||
yield
|
||||
pca9685 = None
|
||||
for pca9685 in get_variable(config[CONF_PCA9685_ID]):
|
||||
yield
|
||||
rhs = pca9685.create_channel(config[CONF_CHANNEL], power_supply)
|
||||
out = Pvariable('output::PCA9685OutputComponent::Channel', config[CONF_ID], rhs)
|
||||
out = Pvariable(config[CONF_ID], rhs)
|
||||
output.setup_output_platform(out, config, skip_power_supply=True)
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import output
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_FREQUENCY, CONF_ID, CONF_PHASE_BALANCER
|
||||
from esphomeyaml.helpers import App, HexIntLiteral, Pvariable, RawExpression, add
|
||||
from esphomeyaml.helpers import App, HexIntLiteral, Pvariable, add
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
PHASE_BALANCERS = ['None', 'Linear', 'Weaved']
|
||||
|
||||
PCA9685_COMPONENT_TYPE = 'output::PCA9685OutputComponent'
|
||||
PCA9685OutputComponent = output.output_ns.namespace('PCA9685OutputComponent')
|
||||
|
||||
PHASE_BALANCER_MESSAGE = ("The phase_balancer option has been removed in version 1.5.0. "
|
||||
"esphomelib will now automatically choose a suitable phase balancer.")
|
||||
|
||||
PCA9685_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('pca9685'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
|
||||
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
|
||||
vol.Range(min=23.84, max=1525.88)),
|
||||
vol.Optional(CONF_ADDRESS): cv.i2c_address,
|
||||
@@ -28,13 +27,9 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCA9685_SCHEMA])
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
rhs = App.make_pca9685_component(conf.get(CONF_FREQUENCY))
|
||||
pca9685 = Pvariable(PCA9685_COMPONENT_TYPE, conf[CONF_ID], rhs)
|
||||
pca9685 = Pvariable(conf[CONF_ID], rhs)
|
||||
if CONF_ADDRESS in conf:
|
||||
add(pca9685.set_address(HexIntLiteral(conf[CONF_ADDRESS])))
|
||||
if CONF_PHASE_BALANCER in conf:
|
||||
phase_balancer = RawExpression(u'PCA9685_PhaseBalancer_{}'.format(
|
||||
conf[CONF_PHASE_BALANCER]))
|
||||
add(pca9685.set_phase_balancer(phase_balancer))
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_PCA9685_OUTPUT'
|
||||
|
||||
@@ -2,12 +2,15 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_PCF8575
|
||||
from esphomeyaml.helpers import App, Pvariable
|
||||
from esphomeyaml.helpers import App, Pvariable, esphomelib_ns
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
io_ns = esphomelib_ns.namespace('io')
|
||||
PCF8574Component = io_ns.PCF8574Component
|
||||
|
||||
PCF8574_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ID): cv.register_variable_id,
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(PCF8574Component),
|
||||
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
|
||||
vol.Optional(CONF_PCF8575, default=False): cv.boolean,
|
||||
})
|
||||
@@ -18,7 +21,7 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCF8574_SCHEMA])
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
rhs = App.make_pcf8574_component(conf[CONF_ADDRESS], conf[CONF_PCF8575])
|
||||
Pvariable('io::PCF8574Component', conf[CONF_ID], rhs)
|
||||
Pvariable(conf[CONF_ID], rhs)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_PCF8574'
|
||||
|
||||
@@ -3,10 +3,13 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, add, exp_gpio_output_pin
|
||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
|
||||
|
||||
POWER_SUPPLY_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
|
||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
PowerSupplyComponent = esphomelib_ns.PowerSupplyComponent
|
||||
|
||||
POWER_SUPPLY_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
|
||||
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
@@ -16,9 +19,11 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
|
||||
|
||||
def to_code(config):
|
||||
for conf in config:
|
||||
pin = exp_gpio_output_pin(conf[CONF_PIN])
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(conf[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_power_supply(pin)
|
||||
psu = Pvariable('PowerSupplyComponent', conf[CONF_ID], rhs)
|
||||
psu = Pvariable(conf[CONF_ID], rhs)
|
||||
if CONF_ENABLE_TIME in conf:
|
||||
add(psu.set_enable_time(conf[CONF_ENABLE_TIME]))
|
||||
if CONF_KEEP_ON_TIME in conf:
|
||||
|
||||
62
esphomeyaml/components/remote_receiver.py
Normal file
62
esphomeyaml/components/remote_receiver.py
Normal file
@@ -0,0 +1,62 @@
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
def validate_dumpers_all(value):
|
||||
if not isinstance(value, (str, unicode)):
|
||||
raise vol.Invalid("Not valid dumpers")
|
||||
if value.upper() == "ALL":
|
||||
return 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'
|
||||
31
esphomeyaml/components/remote_transmitter.py
Normal file
31
esphomeyaml/components/remote_transmitter.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression
|
||||
|
||||
remote_ns = esphomelib_ns.namespace('remote')
|
||||
|
||||
RemoteTransmitterComponent = remote_ns.RemoteTransmitterComponent
|
||||
|
||||
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 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'
|
||||
@@ -1,107 +1,202 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_EXPIRE_AFTER, \
|
||||
CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, CONF_FILTER_NAN, CONF_FILTER_OUT, CONF_ICON, \
|
||||
CONF_LAMBDA, CONF_MQTT_ID, CONF_MULTIPLY, CONF_NAME, CONF_OFFSET, CONF_SEND_EVERY, \
|
||||
CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, CONF_ID
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \
|
||||
setup_mqtt_component
|
||||
from esphomeyaml import automation
|
||||
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_FILTER_NAN, CONF_FILTER_OUT, CONF_HEARTBEAT, CONF_ICON, CONF_ID, CONF_INTERNAL, \
|
||||
CONF_LAMBDA, CONF_MQTT_ID, CONF_MULTIPLY, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE, \
|
||||
CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SLIDING_WINDOW_MOVING_AVERAGE, \
|
||||
CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, add_job, esphomelib_ns, \
|
||||
float_, process_lambda, setup_mqtt_component, templatable
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
})
|
||||
|
||||
FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.Any(
|
||||
vol.Schema({vol.Required(CONF_OFFSET): vol.Coerce(float)}),
|
||||
vol.Schema({vol.Required(CONF_MULTIPLY): vol.Coerce(float)}),
|
||||
vol.Schema({vol.Required(CONF_FILTER_OUT): vol.Coerce(float)}),
|
||||
vol.Schema({vol.Required(CONF_FILTER_NAN): None}),
|
||||
vol.Schema({
|
||||
vol.Required(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.Schema({
|
||||
vol.Required(CONF_WINDOW_SIZE): cv.positive_not_null_int,
|
||||
vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int,
|
||||
})
|
||||
}),
|
||||
vol.Schema({
|
||||
vol.Required(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({
|
||||
vol.Required(CONF_ALPHA): cv.positive_float,
|
||||
vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int,
|
||||
})
|
||||
}),
|
||||
vol.Schema({vol.Required(CONF_LAMBDA): cv.string_strict}),
|
||||
)])
|
||||
|
||||
MQTT_SENSOR_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
def validate_recursive_filter(value):
|
||||
return FILTERS_SCHEMA(value)
|
||||
|
||||
|
||||
FILTER_KEYS = [CONF_OFFSET, CONF_MULTIPLY, CONF_FILTER_OUT, CONF_FILTER_NAN,
|
||||
CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_LAMBDA,
|
||||
CONF_THROTTLE, CONF_DELTA, CONF_UNIQUE, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR]
|
||||
|
||||
FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
|
||||
vol.Optional(CONF_OFFSET): vol.Coerce(float),
|
||||
vol.Optional(CONF_MULTIPLY): vol.Coerce(float),
|
||||
vol.Optional(CONF_FILTER_OUT): vol.Coerce(float),
|
||||
vol.Optional(CONF_FILTER_NAN): None,
|
||||
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.Schema({
|
||||
vol.Required(CONF_WINDOW_SIZE): cv.positive_not_null_int,
|
||||
vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int,
|
||||
}),
|
||||
vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({
|
||||
vol.Required(CONF_ALPHA): cv.positive_float,
|
||||
vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int,
|
||||
}),
|
||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_DELTA): vol.Coerce(float),
|
||||
vol.Optional(CONF_UNIQUE): None,
|
||||
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
|
||||
vol.Optional(CONF_OR): validate_recursive_filter,
|
||||
}, cv.has_exactly_one_key(*FILTER_KEYS))])
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
sensor_ns = esphomelib_ns.namespace('sensor')
|
||||
Sensor = sensor_ns.Sensor
|
||||
MQTTSensorComponent = sensor_ns.MQTTSensorComponent
|
||||
OffsetFilter = sensor_ns.OffsetFilter
|
||||
MultiplyFilter = sensor_ns.MultiplyFilter
|
||||
FilterOutValueFilter = sensor_ns.FilterOutValueFilter
|
||||
FilterOutNANFilter = sensor_ns.FilterOutNANFilter
|
||||
SlidingWindowMovingAverageFilter = sensor_ns.SlidingWindowMovingAverageFilter
|
||||
ExponentialMovingAverageFilter = sensor_ns.ExponentialMovingAverageFilter
|
||||
LambdaFilter = sensor_ns.LambdaFilter
|
||||
ThrottleFilter = sensor_ns.ThrottleFilter
|
||||
DeltaFilter = sensor_ns.DeltaFilter
|
||||
OrFilter = sensor_ns.OrFilter
|
||||
HeartbeatFilter = sensor_ns.HeartbeatFilter
|
||||
DebounceFilter = sensor_ns.DebounceFilter
|
||||
UniqueFilter = sensor_ns.UniqueFilter
|
||||
|
||||
SensorValueTrigger = sensor_ns.SensorValueTrigger
|
||||
RawSensorValueTrigger = sensor_ns.RawSensorValueTrigger
|
||||
ValueRangeTrigger = sensor_ns.ValueRangeTrigger
|
||||
|
||||
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent),
|
||||
cv.GenerateID(): cv.declare_variable_id(Sensor),
|
||||
vol.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_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))]),
|
||||
})
|
||||
|
||||
MQTT_SENSOR_ID_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID('mqtt_sensor', CONF_MQTT_ID): cv.register_variable_id,
|
||||
})
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
OffsetFilter = MockObj('new sensor::OffsetFilter')
|
||||
MultiplyFilter = MockObj('new sensor::MultiplyFilter')
|
||||
FilterOutValueFilter = MockObj('new sensor::FilterOutValueFilter')
|
||||
FilterOutNANFilter = MockObj('new sensor::FilterOutNANFilter')
|
||||
SlidingWindowMovingAverageFilter = MockObj('new sensor::SlidingWindowMovingAverageFilter')
|
||||
ExponentialMovingAverageFilter = MockObj('new sensor::ExponentialMovingAverageFilter')
|
||||
LambdaFilter = MockObj('new sensor::LambdaFilter')
|
||||
SENSOR_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(SENSOR_SCHEMA.schema)
|
||||
|
||||
|
||||
def setup_filter(config):
|
||||
if CONF_OFFSET in config:
|
||||
return OffsetFilter(config[CONF_OFFSET])
|
||||
if CONF_MULTIPLY in config:
|
||||
return MultiplyFilter(config[CONF_MULTIPLY])
|
||||
if CONF_FILTER_OUT in config:
|
||||
return FilterOutValueFilter(config[CONF_FILTER_OUT])
|
||||
if CONF_FILTER_NAN in config:
|
||||
return FilterOutNANFilter()
|
||||
if CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
|
||||
yield OffsetFilter.new(config[CONF_OFFSET])
|
||||
elif CONF_MULTIPLY in config:
|
||||
yield MultiplyFilter.new(config[CONF_MULTIPLY])
|
||||
elif CONF_FILTER_OUT in config:
|
||||
yield FilterOutValueFilter.new(config[CONF_FILTER_OUT])
|
||||
elif CONF_FILTER_NAN in config:
|
||||
yield FilterOutNANFilter.new()
|
||||
elif CONF_SLIDING_WINDOW_MOVING_AVERAGE in config:
|
||||
conf = config[CONF_SLIDING_WINDOW_MOVING_AVERAGE]
|
||||
return SlidingWindowMovingAverageFilter(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
|
||||
if CONF_EXPONENTIAL_MOVING_AVERAGE in config:
|
||||
yield SlidingWindowMovingAverageFilter.new(conf[CONF_WINDOW_SIZE], conf[CONF_SEND_EVERY])
|
||||
elif CONF_EXPONENTIAL_MOVING_AVERAGE in config:
|
||||
conf = config[CONF_EXPONENTIAL_MOVING_AVERAGE]
|
||||
return ExponentialMovingAverageFilter(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
|
||||
if CONF_LAMBDA in config:
|
||||
s = u'[](float x) -> Optional<float> {{ return {}; }}'.format(config[CONF_LAMBDA])
|
||||
return LambdaFilter(RawExpression(s))
|
||||
raise ValueError(u"Filter unsupported: {}".format(config))
|
||||
yield ExponentialMovingAverageFilter.new(conf[CONF_ALPHA], conf[CONF_SEND_EVERY])
|
||||
elif CONF_LAMBDA in config:
|
||||
lambda_ = None
|
||||
for lambda_ in process_lambda(config[CONF_LAMBDA], [(float_, 'x')]):
|
||||
yield None
|
||||
yield LambdaFilter.new(lambda_)
|
||||
elif CONF_THROTTLE in config:
|
||||
yield ThrottleFilter.new(config[CONF_THROTTLE])
|
||||
elif CONF_DELTA in config:
|
||||
yield DeltaFilter.new(config[CONF_DELTA])
|
||||
elif CONF_OR in config:
|
||||
filters = None
|
||||
for filters in setup_filters(config[CONF_OR]):
|
||||
yield None
|
||||
yield OrFilter.new(filters)
|
||||
elif CONF_HEARTBEAT in config:
|
||||
yield App.register_component(HeartbeatFilter.new(config[CONF_HEARTBEAT]))
|
||||
elif CONF_DEBOUNCE in config:
|
||||
yield App.register_component(DebounceFilter.new(config[CONF_DEBOUNCE]))
|
||||
elif CONF_UNIQUE in config:
|
||||
yield UniqueFilter.new()
|
||||
|
||||
|
||||
def setup_mqtt_sensor_component(obj, config):
|
||||
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_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:
|
||||
add(sensor_var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))
|
||||
if CONF_ICON in config:
|
||||
add(sensor_var.set_icon(config[CONF_ICON]))
|
||||
if CONF_ACCURACY_DECIMALS in config:
|
||||
add(sensor_var.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS]))
|
||||
if CONF_FILTERS in config:
|
||||
filters = None
|
||||
for filters in setup_filters(config[CONF_FILTERS]):
|
||||
yield
|
||||
add(sensor_var.set_filters(filters))
|
||||
|
||||
for conf in config.get(CONF_ON_VALUE, []):
|
||||
rhs = sensor_var.make_value_trigger()
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, float_, conf)
|
||||
for conf in config.get(CONF_ON_RAW_VALUE, []):
|
||||
rhs = sensor_var.make_raw_value_trigger()
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, float_, conf)
|
||||
for conf in config.get(CONF_ON_VALUE_RANGE, []):
|
||||
rhs = sensor_var.make_value_range_trigger()
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
if CONF_ABOVE in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_ABOVE], float_, float_):
|
||||
yield
|
||||
trigger.set_min(template_)
|
||||
if CONF_BELOW in conf:
|
||||
template_ = None
|
||||
for template_ in templatable(conf[CONF_BELOW], float_, float_):
|
||||
yield
|
||||
trigger.set_max(template_)
|
||||
automation.build_automation(trigger, float_, conf)
|
||||
|
||||
if CONF_EXPIRE_AFTER in config:
|
||||
if config[CONF_EXPIRE_AFTER] is None:
|
||||
add(obj.disable_expire_after())
|
||||
add(mqtt_var.disable_expire_after())
|
||||
else:
|
||||
add(obj.set_expire_after(config[CONF_EXPIRE_AFTER]))
|
||||
setup_mqtt_component(obj, config)
|
||||
add(mqtt_var.set_expire_after(config[CONF_EXPIRE_AFTER]))
|
||||
setup_mqtt_component(mqtt_var, config)
|
||||
|
||||
|
||||
def setup_sensor(obj, config):
|
||||
if CONF_UNIT_OF_MEASUREMENT in config:
|
||||
add(obj.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT]))
|
||||
if CONF_ICON in config:
|
||||
add(obj.set_icon(config[CONF_ICON]))
|
||||
if CONF_ACCURACY_DECIMALS in config:
|
||||
add(obj.set_accuracy_decimals(config[CONF_ACCURACY_DECIMALS]))
|
||||
if CONF_FILTERS in config:
|
||||
filters = [setup_filter(x) for x in config[CONF_FILTERS]]
|
||||
add(obj.set_filters(ArrayInitializer(*filters)))
|
||||
def setup_sensor(sensor_obj, mqtt_obj, config):
|
||||
sensor_var = Pvariable(config[CONF_ID], sensor_obj, has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
|
||||
|
||||
|
||||
def register_sensor(var, config):
|
||||
setup_sensor(var, config)
|
||||
rhs = App.register_sensor(var)
|
||||
mqtt_sensor = Pvariable('sensor::MQTTSensorComponent', config[CONF_MQTT_ID], rhs)
|
||||
setup_mqtt_sensor_component(mqtt_sensor, config)
|
||||
sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
|
||||
rhs = App.register_sensor(sensor_var)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
|
||||
add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_SENSOR'
|
||||
|
||||
@@ -3,37 +3,52 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ATTENUATION, CONF_ID, CONF_NAME, CONF_PIN, \
|
||||
from esphomeyaml.const import CONF_ATTENUATION, CONF_MAKE_ID, CONF_NAME, CONF_PIN, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
from esphomeyaml.helpers import App, Application, add, global_ns, variable
|
||||
|
||||
ATTENUATION_MODES = {
|
||||
'0db': 'ADC_0db',
|
||||
'2.5db': 'ADC_2_5db',
|
||||
'6db': 'ADC_6db',
|
||||
'11db': 'ADC_11db',
|
||||
'0db': global_ns.ADC_0db,
|
||||
'2.5db': global_ns.ADC_2_5db,
|
||||
'6db': global_ns.ADC_6db,
|
||||
'11db': global_ns.ADC_11db,
|
||||
}
|
||||
|
||||
ATTENUATION_MODE_SCHEMA = vol.Any(*list(ATTENUATION_MODES.keys()))
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('adc'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): pins.analog_pin,
|
||||
vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, ATTENUATION_MODE_SCHEMA),
|
||||
def validate_adc_pin(value):
|
||||
vcc = str(value).upper()
|
||||
if vcc == 'VCC':
|
||||
return cv.only_on_esp8266(vcc)
|
||||
return pins.analog_pin(value)
|
||||
|
||||
|
||||
MakeADCSensor = Application.MakeADCSensor
|
||||
|
||||
PLATFORM_SCHEMA = 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.positive_time_period_milliseconds,
|
||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_adc_sensor(config[CONF_NAME], config[CONF_PIN],
|
||||
pin = config[CONF_PIN]
|
||||
if pin == 'VCC':
|
||||
pin = 0
|
||||
rhs = App.make_adc_sensor(config[CONF_NAME], pin,
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable('Application::MakeADCSensor', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
adc = make.Padc
|
||||
if CONF_ATTENUATION in config:
|
||||
attenuation = ATTENUATION_MODES[config[CONF_ATTENUATION]]
|
||||
add(adc.set_attenuation(RawExpression(attenuation)))
|
||||
sensor.setup_sensor(adc, config)
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt, config)
|
||||
add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]]))
|
||||
sensor.setup_sensor(make.Padc, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ADC_SENSOR'
|
||||
|
||||
|
||||
def required_build_flags(config):
|
||||
if config[CONF_PIN] == 'VCC':
|
||||
return '-DUSE_ADC_SENSOR_VCC'
|
||||
return None
|
||||
|
||||
@@ -2,30 +2,31 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ADS1115_ID, CONF_GAIN, CONF_MULTIPLEXER, CONF_UPDATE_INTERVAL, \
|
||||
CONF_NAME, CONF_ID
|
||||
from esphomeyaml.helpers import RawExpression, get_variable, Pvariable
|
||||
from esphomeyaml.components.ads1115 import ADS1115Component
|
||||
from esphomeyaml.const import CONF_ADS1115_ID, CONF_GAIN, CONF_MULTIPLEXER, CONF_NAME, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import get_variable
|
||||
|
||||
DEPENDENCIES = ['ads1115']
|
||||
|
||||
MUX = {
|
||||
'A0_A1': 'sensor::ADS1115_MULTIPLEXER_P0_N1',
|
||||
'A0_A3': 'sensor::ADS1115_MULTIPLEXER_P0_N3',
|
||||
'A1_A3': 'sensor::ADS1115_MULTIPLEXER_P1_N3',
|
||||
'A2_A3': 'sensor::ADS1115_MULTIPLEXER_P2_N3',
|
||||
'A0_GND': 'sensor::ADS1115_MULTIPLEXER_P0_NG',
|
||||
'A1_GND': 'sensor::ADS1115_MULTIPLEXER_P1_NG',
|
||||
'A2_GND': 'sensor::ADS1115_MULTIPLEXER_P2_NG',
|
||||
'A3_GND': 'sensor::ADS1115_MULTIPLEXER_P3_NG',
|
||||
'A0_A1': sensor.sensor_ns.ADS1115_MULTIPLEXER_P0_N1,
|
||||
'A0_A3': sensor.sensor_ns.ADS1115_MULTIPLEXER_P0_N3,
|
||||
'A1_A3': sensor.sensor_ns.ADS1115_MULTIPLEXER_P1_N3,
|
||||
'A2_A3': sensor.sensor_ns.ADS1115_MULTIPLEXER_P2_N3,
|
||||
'A0_GND': sensor.sensor_ns.ADS1115_MULTIPLEXER_P0_NG,
|
||||
'A1_GND': sensor.sensor_ns.ADS1115_MULTIPLEXER_P1_NG,
|
||||
'A2_GND': sensor.sensor_ns.ADS1115_MULTIPLEXER_P2_NG,
|
||||
'A3_GND': sensor.sensor_ns.ADS1115_MULTIPLEXER_P3_NG,
|
||||
}
|
||||
|
||||
GAIN = {
|
||||
'6.144': 'sensor::ADS1115_GAIN_6P144',
|
||||
'4.096': 'sensor::ADS1115_GAIN_6P096',
|
||||
'2.048': 'sensor::ADS1115_GAIN_2P048',
|
||||
'1.024': 'sensor::ADS1115_GAIN_1P024',
|
||||
'0.512': 'sensor::ADS1115_GAIN_0P512',
|
||||
'0.256': 'sensor::ADS1115_GAIN_0P256',
|
||||
'6.144': sensor.sensor_ns.ADS1115_GAIN_6P144,
|
||||
'4.096': sensor.sensor_ns.ADS1115_GAIN_6P096,
|
||||
'2.048': sensor.sensor_ns.ADS1115_GAIN_2P048,
|
||||
'1.024': sensor.sensor_ns.ADS1115_GAIN_1P024,
|
||||
'0.512': sensor.sensor_ns.ADS1115_GAIN_0P512,
|
||||
'0.256': sensor.sensor_ns.ADS1115_GAIN_0P256,
|
||||
}
|
||||
|
||||
|
||||
@@ -35,28 +36,32 @@ def validate_gain(value):
|
||||
elif not isinstance(value, (str, unicode)):
|
||||
raise vol.Invalid('invalid gain "{}"'.format(value))
|
||||
|
||||
if value not in GAIN:
|
||||
raise vol.Invalid("Invalid gain, options are {}".format(', '.join(GAIN.keys())))
|
||||
return value
|
||||
return cv.one_of(*GAIN)(value)
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('ads1115_sensor'): cv.register_variable_id,
|
||||
vol.Required(CONF_MULTIPLEXER): vol.All(vol.Upper, vol.Any(*list(MUX.keys()))),
|
||||
def validate_mux(value):
|
||||
value = cv.string(value).upper()
|
||||
value = value.replace(' ', '_')
|
||||
return cv.one_of(*MUX)(value)
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_MULTIPLEXER): validate_mux,
|
||||
vol.Required(CONF_GAIN): validate_gain,
|
||||
vol.Optional(CONF_ADS1115_ID): cv.variable_id,
|
||||
cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component),
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}).extend(sensor.MQTT_SENSOR_ID_SCHEMA.schema)
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
hub = get_variable(config.get(CONF_ADS1115_ID), u'sensor::ADS1115Component')
|
||||
hub = None
|
||||
for hub in get_variable(config[CONF_ADS1115_ID]):
|
||||
yield
|
||||
|
||||
mux = RawExpression(MUX[config[CONF_MULTIPLEXER]])
|
||||
gain = RawExpression(GAIN[config[CONF_GAIN]])
|
||||
mux = MUX[config[CONF_MULTIPLEXER]]
|
||||
gain = GAIN[config[CONF_GAIN]]
|
||||
rhs = hub.get_sensor(config[CONF_NAME], mux, gain, config.get(CONF_UPDATE_INTERVAL))
|
||||
sensor_ = Pvariable('sensor::ADS1115Sensor', config[CONF_ID], rhs)
|
||||
sensor.register_sensor(sensor_, config)
|
||||
sensor.register_sensor(rhs, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
|
||||
|
||||
@@ -2,36 +2,36 @@ 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_RESOLUTION, \
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_RESOLUTION, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
from esphomeyaml.helpers import App, Application, add, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
BH1750_RESOLUTIONS = {
|
||||
4.0: 'sensor::BH1750_RESOLUTION_4P0_LX',
|
||||
1.0: 'sensor::BH1750_RESOLUTION_1P0_LX',
|
||||
0.5: 'sensor::BH1750_RESOLUTION_0P5_LX',
|
||||
4.0: sensor.sensor_ns.BH1750_RESOLUTION_4P0_LX,
|
||||
1.0: sensor.sensor_ns.BH1750_RESOLUTION_1P0_LX,
|
||||
0.5: sensor.sensor_ns.BH1750_RESOLUTION_0P5_LX,
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('bh1750_sensor'): cv.register_variable_id,
|
||||
MakeBH1750Sensor = Application.MakeBH1750Sensor
|
||||
|
||||
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_RESOLUTION): vol.All(cv.positive_float, vol.Any(*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,
|
||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_bh1750_sensor(config[CONF_NAME], config[CONF_ADDRESS],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make_bh1750 = variable('Application::MakeBH1750Sensor', config[CONF_ID], rhs)
|
||||
make_bh1750 = variable(config[CONF_MAKE_ID], rhs)
|
||||
bh1750 = make_bh1750.Pbh1750
|
||||
if CONF_RESOLUTION in config:
|
||||
constant = BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]
|
||||
add(bh1750.set_resolution(RawExpression(constant)))
|
||||
sensor.setup_sensor(bh1750, config)
|
||||
sensor.setup_mqtt_sensor_component(make_bh1750.Pmqtt, config)
|
||||
add(bh1750.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]))
|
||||
sensor.setup_sensor(bh1750, make_bh1750.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_BH1750'
|
||||
|
||||
@@ -2,41 +2,42 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_NAME, \
|
||||
CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, 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::BME280_OVERSAMPLING_NONE',
|
||||
'1X': 'sensor::BME280_OVERSAMPLING_1X',
|
||||
'2X': 'sensor::BME280_OVERSAMPLING_2X',
|
||||
'4X': 'sensor::BME280_OVERSAMPLING_4X',
|
||||
'8X': 'sensor::BME280_OVERSAMPLING_8X',
|
||||
'16X': 'sensor::BME280_OVERSAMPLING_16X',
|
||||
'NONE': sensor.sensor_ns.BME280_OVERSAMPLING_NONE,
|
||||
'1X': sensor.sensor_ns.BME280_OVERSAMPLING_1X,
|
||||
'2X': sensor.sensor_ns.BME280_OVERSAMPLING_2X,
|
||||
'4X': sensor.sensor_ns.BME280_OVERSAMPLING_4X,
|
||||
'8X': sensor.sensor_ns.BME280_OVERSAMPLING_8X,
|
||||
'16X': sensor.sensor_ns.BME280_OVERSAMPLING_16X,
|
||||
}
|
||||
|
||||
IIR_FILTER_OPTIONS = {
|
||||
'OFF': 'sensor::BME280_IIR_FILTER_OFF',
|
||||
'2X': 'sensor::BME280_IIR_FILTER_2X',
|
||||
'4X': 'sensor::BME280_IIR_FILTER_4X',
|
||||
'8X': 'sensor::BME280_IIR_FILTER_8X',
|
||||
'16X': 'sensor::BME280_IIR_FILTER_16X',
|
||||
'OFF': sensor.sensor_ns.BME280_IIR_FILTER_OFF,
|
||||
'2X': sensor.sensor_ns.BME280_IIR_FILTER_2X,
|
||||
'4X': sensor.sensor_ns.BME280_IIR_FILTER_4X,
|
||||
'8X': sensor.sensor_ns.BME280_IIR_FILTER_8X,
|
||||
'16X': sensor.sensor_ns.BME280_IIR_FILTER_16X,
|
||||
}
|
||||
|
||||
BME280_OVERSAMPLING_SENSOR_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
|
||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, vol.Any(*OVERSAMPLING_OPTIONS)),
|
||||
BME280_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
||||
})
|
||||
|
||||
MakeBME280Sensor = Application.MakeBME280Sensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('bme280'): cv.register_variable_id,
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME280Sensor),
|
||||
vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address,
|
||||
vol.Required(CONF_TEMPERATURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_PRESSURE): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): BME280_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, vol.Any(*IIR_FILTER_OPTIONS)),
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
@@ -47,29 +48,27 @@ def to_code(config):
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
config[CONF_ADDRESS],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable('Application::MakeBME280Sensor', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
bme280 = make.Pbme280
|
||||
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
||||
add(bme280.set_temperature_oversampling(RawExpression(constant)))
|
||||
add(bme280.set_temperature_oversampling(constant))
|
||||
if CONF_OVERSAMPLING in config[CONF_PRESSURE]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_PRESSURE][CONF_OVERSAMPLING]]
|
||||
add(bme280.set_pressure_oversampling(RawExpression(constant)))
|
||||
add(bme280.set_pressure_oversampling(constant))
|
||||
if CONF_OVERSAMPLING in config[CONF_HUMIDITY]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_HUMIDITY][CONF_OVERSAMPLING]]
|
||||
add(bme280.set_humidity_oversampling(RawExpression(constant)))
|
||||
add(bme280.set_humidity_oversampling(constant))
|
||||
if CONF_IIR_FILTER in config:
|
||||
constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
|
||||
add(bme280.set_iir_filter(RawExpression(constant)))
|
||||
add(bme280.set_iir_filter(constant))
|
||||
|
||||
sensor.setup_sensor(bme280.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
|
||||
sensor.setup_sensor(bme280.Pget_pressure_sensor(), config[CONF_PRESSURE])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_pressure, config[CONF_PRESSURE])
|
||||
|
||||
sensor.setup_sensor(bme280.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
sensor.setup_sensor(bme280.Pget_temperature_sensor(), make.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(bme280.Pget_pressure_sensor(), make.Pmqtt_pressure,
|
||||
config[CONF_PRESSURE])
|
||||
sensor.setup_sensor(bme280.Pget_humidity_sensor(), make.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_BME280'
|
||||
|
||||
@@ -2,45 +2,47 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_NAME, \
|
||||
CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, CONF_GAS_RESISTANCE
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
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_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, add, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
OVERSAMPLING_OPTIONS = {
|
||||
'NONE': 'sensor::BME680_OVERSAMPLING_NONE',
|
||||
'1X': 'sensor::BME680_OVERSAMPLING_1X',
|
||||
'2X': 'sensor::BME680_OVERSAMPLING_2X',
|
||||
'4X': 'sensor::BME680_OVERSAMPLING_4X',
|
||||
'8X': 'sensor::BME680_OVERSAMPLING_8X',
|
||||
'16X': 'sensor::BME680_OVERSAMPLING_16X',
|
||||
'NONE': sensor.sensor_ns.BME680_OVERSAMPLING_NONE,
|
||||
'1X': sensor.sensor_ns.BME680_OVERSAMPLING_1X,
|
||||
'2X': sensor.sensor_ns.BME680_OVERSAMPLING_2X,
|
||||
'4X': sensor.sensor_ns.BME680_OVERSAMPLING_4X,
|
||||
'8X': sensor.sensor_ns.BME680_OVERSAMPLING_8X,
|
||||
'16X': sensor.sensor_ns.BME680_OVERSAMPLING_16X,
|
||||
}
|
||||
|
||||
IIR_FILTER_OPTIONS = {
|
||||
'OFF': 'sensor::BME680_IIR_FILTER_OFF',
|
||||
'1X': 'sensor::BME680_IIR_FILTER_1X',
|
||||
'3X': 'sensor::BME680_IIR_FILTER_3X',
|
||||
'7X': 'sensor::BME680_IIR_FILTER_7X',
|
||||
'15X': 'sensor::BME680_IIR_FILTER_15X',
|
||||
'31X': 'sensor::BME680_IIR_FILTER_31X',
|
||||
'63X': 'sensor::BME680_IIR_FILTER_63X',
|
||||
'127X': 'sensor::BME680_IIR_FILTER_127X',
|
||||
'OFF': sensor.sensor_ns.BME680_IIR_FILTER_OFF,
|
||||
'1X': sensor.sensor_ns.BME680_IIR_FILTER_1X,
|
||||
'3X': sensor.sensor_ns.BME680_IIR_FILTER_3X,
|
||||
'7X': sensor.sensor_ns.BME680_IIR_FILTER_7X,
|
||||
'15X': sensor.sensor_ns.BME680_IIR_FILTER_15X,
|
||||
'31X': sensor.sensor_ns.BME680_IIR_FILTER_31X,
|
||||
'63X': sensor.sensor_ns.BME680_IIR_FILTER_63X,
|
||||
'127X': sensor.sensor_ns.BME680_IIR_FILTER_127X,
|
||||
}
|
||||
|
||||
BME680_OVERSAMPLING_SENSOR_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
|
||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, vol.Any(*OVERSAMPLING_OPTIONS)),
|
||||
BME680_OVERSAMPLING_SENSOR_SCHEMA = sensor.SENSOR_SCHEMA.extend({
|
||||
vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, cv.one_of(*OVERSAMPLING_OPTIONS)),
|
||||
})
|
||||
|
||||
MakeBME680Sensor = Application.MakeBME680Sensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('bme680'): cv.register_variable_id,
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME680Sensor),
|
||||
vol.Optional(CONF_ADDRESS, default=0x76): cv.i2c_address,
|
||||
vol.Required(CONF_TEMPERATURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_PRESSURE): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): BME680_OVERSAMPLING_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_GAS_RESISTANCE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, vol.Any(*IIR_FILTER_OPTIONS)),
|
||||
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)),
|
||||
# TODO: Heater
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
@@ -53,32 +55,29 @@ def to_code(config):
|
||||
config[CONF_GAS_RESISTANCE][CONF_NAME],
|
||||
config[CONF_ADDRESS],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable('Application::MakeBME680Sensor', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
bme680 = make.Pbme680
|
||||
if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
|
||||
add(bme680.set_temperature_oversampling(RawExpression(constant)))
|
||||
add(bme680.set_temperature_oversampling(constant))
|
||||
if CONF_OVERSAMPLING in config[CONF_PRESSURE]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_PRESSURE][CONF_OVERSAMPLING]]
|
||||
add(bme680.set_pressure_oversampling(RawExpression(constant)))
|
||||
add(bme680.set_pressure_oversampling(constant))
|
||||
if CONF_OVERSAMPLING in config[CONF_HUMIDITY]:
|
||||
constant = OVERSAMPLING_OPTIONS[config[CONF_HUMIDITY][CONF_OVERSAMPLING]]
|
||||
add(bme680.set_humidity_oversampling(RawExpression(constant)))
|
||||
add(bme680.set_humidity_oversampling(constant))
|
||||
if CONF_IIR_FILTER in config:
|
||||
constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
|
||||
add(bme680.set_iir_filter(RawExpression(constant)))
|
||||
add(bme680.set_iir_filter(constant))
|
||||
|
||||
sensor.setup_sensor(bme680.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
|
||||
sensor.setup_sensor(bme680.Pget_pressure_sensor(), config[CONF_PRESSURE])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_pressure, config[CONF_PRESSURE])
|
||||
|
||||
sensor.setup_sensor(bme680.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
|
||||
sensor.setup_sensor(bme680.Pget_gas_resistance_sensor(), config[CONF_GAS_RESISTANCE])
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt_gas_resistance, config[CONF_GAS_RESISTANCE])
|
||||
sensor.setup_sensor(bme680.Pget_temperature_sensor(), make.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(bme680.Pget_pressure_sensor(), make.Pmqtt_pressure,
|
||||
config[CONF_PRESSURE])
|
||||
sensor.setup_sensor(bme680.Pget_humidity_sensor(), make.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
sensor.setup_sensor(bme680.Pget_gas_resistance_sensor(), make.Pmqtt_gas_resistance,
|
||||
config[CONF_GAS_RESISTANCE])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_BME680'
|
||||
|
||||
@@ -2,17 +2,18 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_NAME, \
|
||||
CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, HexIntLiteral, add, variable
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \
|
||||
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, HexIntLiteral, add, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
MakeBMP085Sensor = Application.MakeBMP085Sensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('bmp085_sensor'): cv.register_variable_id,
|
||||
vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_PRESSURE): MQTT_SENSOR_SCHEMA,
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
@@ -22,13 +23,14 @@ def to_code(config):
|
||||
rhs = App.make_bmp085_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_PRESSURE][CONF_NAME],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
bmp = variable('Application::MakeBMP085Sensor', config[CONF_ID], rhs)
|
||||
bmp = variable(config[CONF_MAKE_ID], rhs)
|
||||
if CONF_ADDRESS in config:
|
||||
add(bmp.Pbmp.set_address(HexIntLiteral(config[CONF_ADDRESS])))
|
||||
sensor.setup_sensor(bmp.Pbmp.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(bmp.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(bmp.Pbmp.Pget_pressure_sensor(), config[CONF_PRESSURE])
|
||||
sensor.setup_mqtt_sensor_component(bmp.Pmqtt_pressure, config[CONF_PRESSURE])
|
||||
|
||||
sensor.setup_sensor(bmp.Pbmp.Pget_temperature_sensor(), bmp.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(bmp.Pbmp.Pget_pressure_sensor(), bmp.Pmqtt_pressure,
|
||||
config[CONF_PRESSURE])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_BMP085_SENSOR'
|
||||
|
||||
@@ -2,36 +2,30 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.dallas import DALLAS_COMPONENT_CLASS
|
||||
from esphomeyaml.components.dallas import DallasComponent
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \
|
||||
CONF_RESOLUTION, \
|
||||
CONF_UPDATE_INTERVAL, CONF_ID
|
||||
from esphomeyaml.helpers import HexIntLiteral, get_variable, Pvariable
|
||||
CONF_RESOLUTION
|
||||
from esphomeyaml.helpers import HexIntLiteral, get_variable
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('dallas_sensor'): cv.register_variable_id,
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int,
|
||||
vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int,
|
||||
vol.Optional(CONF_DALLAS_ID): cv.variable_id,
|
||||
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=8, max=12)),
|
||||
}).extend(sensor.MQTT_SENSOR_ID_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
|
||||
cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent),
|
||||
vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=9, max=12)),
|
||||
}), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
hub = get_variable(config.get(CONF_DALLAS_ID), DALLAS_COMPONENT_CLASS)
|
||||
update_interval = config.get(CONF_UPDATE_INTERVAL)
|
||||
if CONF_RESOLUTION in config and update_interval is None:
|
||||
update_interval = 10000
|
||||
|
||||
hub = None
|
||||
for hub in get_variable(config[CONF_DALLAS_ID]):
|
||||
yield
|
||||
if CONF_ADDRESS in config:
|
||||
address = HexIntLiteral(config[CONF_ADDRESS])
|
||||
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, update_interval,
|
||||
config.get(CONF_RESOLUTION))
|
||||
rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, config.get(CONF_RESOLUTION))
|
||||
else:
|
||||
rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX],
|
||||
update_interval, config.get(CONF_RESOLUTION))
|
||||
sensor_ = Pvariable('sensor::DallasTemperatureSensor', config[CONF_ID], rhs)
|
||||
sensor.register_sensor(sensor_, config)
|
||||
config.get(CONF_RESOLUTION))
|
||||
sensor.register_sensor(rhs, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'
|
||||
|
||||
@@ -2,43 +2,47 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_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
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable, exp_gpio_output_pin
|
||||
from esphomeyaml.pins import GPIO_OUTPUT_PIN_SCHEMA
|
||||
from esphomeyaml.helpers import App, Application, add, gpio_output_pin_expression, variable
|
||||
from esphomeyaml.pins import gpio_output_pin_schema
|
||||
|
||||
DHT_MODELS = {
|
||||
'AUTO_DETECT': 'sensor::DHT_MODEL_AUTO_DETECT',
|
||||
'DHT11': 'sensor::DHT_MODEL_DHT11',
|
||||
'DHT22': 'sensor::DHT_MODEL_DHT22',
|
||||
'AM2302': 'sensor::DHT_MODEL_AM2302',
|
||||
'RHT03': 'sensor::DHT_MODEL_RHT03',
|
||||
'AUTO_DETECT': sensor.sensor_ns.DHT_MODEL_AUTO_DETECT,
|
||||
'DHT11': sensor.sensor_ns.DHT_MODEL_DHT11,
|
||||
'DHT22': sensor.sensor_ns.DHT_MODEL_DHT22,
|
||||
'AM2302': sensor.sensor_ns.DHT_MODEL_AM2302,
|
||||
'RHT03': sensor.sensor_ns.DHT_MODEL_RHT03,
|
||||
}
|
||||
|
||||
MakeDHTSensor = Application.MakeDHTSensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('dht_sensor'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): GPIO_OUTPUT_PIN_SCHEMA,
|
||||
vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_MODEL): vol.All(vol.Upper, vol.Any(*DHT_MODELS)),
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
pin = exp_gpio_output_pin(config[CONF_PIN])
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_dht_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
pin, config.get(CONF_UPDATE_INTERVAL))
|
||||
dht = variable('Application::MakeDHTSensor', config[CONF_ID], rhs)
|
||||
dht = variable(config[CONF_MAKE_ID], rhs)
|
||||
if CONF_MODEL in config:
|
||||
constant = DHT_MODELS[config[CONF_MODEL]]
|
||||
add(dht.Pdht.set_dht_model(RawExpression(constant)))
|
||||
sensor.setup_sensor(dht.Pdht.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(dht.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(dht.Pdht.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(dht.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
add(dht.Pdht.set_dht_model(constant))
|
||||
|
||||
sensor.setup_sensor(dht.Pdht.Pget_temperature_sensor(),
|
||||
dht.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(dht.Pdht.Pget_humidity_sensor(),
|
||||
dht.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_DHT_SENSOR'
|
||||
|
||||
33
esphomeyaml/components/sensor/dht12.py
Normal file
33
esphomeyaml/components/sensor/dht12.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_dht12_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
dht = variable(config[CONF_MAKE_ID], rhs)
|
||||
|
||||
sensor.setup_sensor(dht.Pdht12.Pget_temperature_sensor(), dht.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(dht.Pdht12.Pget_humidity_sensor(), dht.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_DHT12_SENSOR'
|
||||
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.positive_time_period_milliseconds,
|
||||
}))
|
||||
|
||||
|
||||
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.positive_time_period_milliseconds,
|
||||
}))
|
||||
|
||||
|
||||
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'
|
||||
@@ -2,17 +2,18 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, variable
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
MakeHDC1080Sensor = Application.MakeHDC1080Sensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('dht_sensor'): cv.register_variable_id,
|
||||
vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
@@ -21,11 +22,13 @@ def to_code(config):
|
||||
rhs = App.make_hdc1080_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
hdc1080 = variable('Application::MakeHDC1080Sensor', config[CONF_ID], rhs)
|
||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(hdc1080.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(hdc1080.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
hdc1080 = variable(config[CONF_MAKE_ID], rhs)
|
||||
|
||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_temperature_sensor(),
|
||||
hdc1080.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(hdc1080.Phdc1080.Pget_humidity_sensor(), hdc1080.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_HDC1080_SENSOR'
|
||||
|
||||
@@ -2,17 +2,18 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, variable
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
MakeHTU21DSensor = Application.MakeHTU21DSensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('htu21d'): cv.register_variable_id,
|
||||
vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
|
||||
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.positive_time_period_milliseconds,
|
||||
})
|
||||
|
||||
@@ -21,11 +22,11 @@ def to_code(config):
|
||||
rhs = App.make_htu21d_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
htu21d = variable('Application::MakeHTU21DSensor', config[CONF_ID], rhs)
|
||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(htu21d.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(htu21d.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
htu21d = variable(config[CONF_MAKE_ID], rhs)
|
||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_temperature_sensor(), htu21d.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(htu21d.Phtu21d.Pget_humidity_sensor(), htu21d.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_HTU21D_SENSOR'
|
||||
|
||||
38
esphomeyaml/components/sensor/max6675.py
Normal file
38
esphomeyaml/components/sensor/max6675.py
Normal file
@@ -0,0 +1,38 @@
|
||||
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_CLOCK, CONF_PIN_CS, CONF_PIN_MISO, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, \
|
||||
gpio_output_pin_expression, variable
|
||||
|
||||
MakeMAX6675Sensor = Application.MakeMAX6675Sensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMAX6675Sensor),
|
||||
vol.Required(CONF_PIN_CS): pins.gpio_output_pin_schema,
|
||||
vol.Required(CONF_PIN_CLOCK): pins.gpio_output_pin_schema,
|
||||
vol.Required(CONF_PIN_MISO): pins.gpio_input_pin_schema,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
pin_cs = None
|
||||
for pin_cs in gpio_output_pin_expression(config[CONF_PIN_CS]):
|
||||
yield
|
||||
pin_clock = None
|
||||
for pin_clock in gpio_output_pin_expression(config[CONF_PIN_CLOCK]):
|
||||
yield
|
||||
pin_miso = None
|
||||
for pin_miso in gpio_input_pin_expression(config[CONF_PIN_MISO]):
|
||||
yield
|
||||
rhs = App.make_max6675_sensor(config[CONF_NAME], pin_cs, pin_clock, pin_miso,
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
sensor.setup_sensor(make.Pmax6675, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_MAX6675_SENSOR'
|
||||
@@ -2,8 +2,7 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_ID_SCHEMA
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_MQTT_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Pvariable
|
||||
|
||||
@@ -16,58 +15,57 @@ CONF_GYRO_X = 'gyro_x'
|
||||
CONF_GYRO_Y = 'gyro_y'
|
||||
CONF_GYRO_Z = 'gyro_z'
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('mpu6050'): cv.register_variable_id,
|
||||
MPU6050Component = sensor.sensor_ns.MPU6050Component
|
||||
MPU6050AccelSensor = sensor.sensor_ns.MPU6050AccelSensor
|
||||
MPU6050GyroSensor = sensor.sensor_ns.MPU6050GyroSensor
|
||||
MPU6050TemperatureSensor = sensor.sensor_ns.MPU6050TemperatureSensor
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(MPU6050Component),
|
||||
vol.Optional(CONF_ADDRESS, default=0x68): cv.i2c_address,
|
||||
vol.Optional(CONF_ACCEL_X): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_ACCEL_Y): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_ACCEL_Z): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_GYRO_X): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_GYRO_Y): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_GYRO_Z): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_TEMPERATURE): MQTT_SENSOR_ID_SCHEMA,
|
||||
vol.Optional(CONF_ACCEL_X): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_ACCEL_Y): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_ACCEL_Z): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_GYRO_X): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_GYRO_Y): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_GYRO_Z): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
})
|
||||
}), cv.has_at_least_one_key(CONF_ACCEL_X, CONF_ACCEL_Y, CONF_ACCEL_Z,
|
||||
CONF_GYRO_X, CONF_GYRO_Y, CONF_GYRO_Z))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_mpu6050_sensor(config[CONF_ADDRESS], config.get(CONF_UPDATE_INTERVAL))
|
||||
mpu = Pvariable('sensor::MPU6050Component', config[CONF_ID], rhs)
|
||||
mpu = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_ACCEL_X in config:
|
||||
conf = config[CONF_ACCEL_X]
|
||||
rhs = mpu.Pmake_accel_x_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050AccelSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_ACCEL_Y in config:
|
||||
conf = config[CONF_ACCEL_Y]
|
||||
rhs = mpu.Pmake_accel_y_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050AccelSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_ACCEL_Z in config:
|
||||
conf = config[CONF_ACCEL_Z]
|
||||
rhs = mpu.Pmake_accel_z_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050AccelSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_GYRO_X in config:
|
||||
conf = config[CONF_GYRO_X]
|
||||
rhs = mpu.Pmake_gyro_x_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050GyroSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_GYRO_Y in config:
|
||||
conf = config[CONF_GYRO_Y]
|
||||
rhs = mpu.Pmake_gyro_y_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050GyroSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_GYRO_Z in config:
|
||||
conf = config[CONF_GYRO_Z]
|
||||
rhs = mpu.Pmake_gyro_z_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050GyroSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
if CONF_TEMPERATURE in config:
|
||||
conf = config[CONF_TEMPERATURE]
|
||||
rhs = mpu.Pmake_temperature_sensor(conf[CONF_NAME])
|
||||
sensor_ = Pvariable('sensor::MPU6050TemperatureSensor', conf[CONF_MQTT_ID], rhs)
|
||||
sensor.register_sensor(sensor_, conf)
|
||||
sensor.register_sensor(rhs, conf)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_MPU6050'
|
||||
|
||||
@@ -1,62 +1,67 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml import core, pins
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_COUNT_MODE, CONF_FALLING_EDGE, CONF_ID, CONF_INTERNAL_FILTER, \
|
||||
CONF_NAME, CONF_PIN, CONF_PULL_MODE, CONF_RISING_EDGE, CONF_UPDATE_INTERVAL, \
|
||||
from esphomeyaml.const import CONF_COUNT_MODE, CONF_FALLING_EDGE, CONF_INTERNAL_FILTER, \
|
||||
CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_PULL_MODE, CONF_RISING_EDGE, CONF_UPDATE_INTERVAL, \
|
||||
ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
|
||||
GPIO_PULL_MODES = {
|
||||
'PULLUP': 'GPIO_PULLUP_ONLY',
|
||||
'PULLDOWN': 'GPIO_PULLDOWN_ONLY',
|
||||
'PULLUP_PULLDOWN': 'GPIO_PULLUP_PULLDOWN',
|
||||
'FLOATING': 'GPIO_FLOATING',
|
||||
}
|
||||
|
||||
GPIO_PULL_MODE_SCHEMA = vol.All(vol.Upper, vol.Any(*list(GPIO_PULL_MODES.keys())))
|
||||
from esphomeyaml.helpers import App, Application, add, variable, gpio_input_pin_expression
|
||||
|
||||
COUNT_MODES = {
|
||||
'DISABLE': 'PCNT_COUNT_DIS',
|
||||
'INCREMENT': 'PCNT_COUNT_INC',
|
||||
'DECREMENT': 'PCNT_COUNT_DEC',
|
||||
'DISABLE': sensor.sensor_ns.PULSE_COUNTER_DISABLE,
|
||||
'INCREMENT': sensor.sensor_ns.PULSE_COUNTER_INCREMENT,
|
||||
'DECREMENT': sensor.sensor_ns.PULSE_COUNTER_DECREMENT,
|
||||
}
|
||||
|
||||
COUNT_MODE_SCHEMA = vol.All(vol.Upper, vol.Any(*list(COUNT_MODES.keys())))
|
||||
COUNT_MODE_SCHEMA = vol.All(vol.Upper, cv.one_of(*COUNT_MODES))
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('pulse_counter'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): pins.input_pin,
|
||||
vol.Optional(CONF_PULL_MODE): GPIO_PULL_MODE_SCHEMA,
|
||||
MakePulseCounterSensor = Application.MakePulseCounterSensor
|
||||
|
||||
|
||||
def validate_internal_filter(value):
|
||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
|
||||
if isinstance(value, int):
|
||||
raise vol.Invalid("Please specify the internal filter in microseconds now "
|
||||
"(since 1.7.0). For example '17ms'")
|
||||
value = cv.positive_time_period_microseconds(value)
|
||||
if value.total_microseconds > 13:
|
||||
raise vol.Invalid("Maximum internal filter value for ESP32 is 13us")
|
||||
return value
|
||||
else:
|
||||
return cv.positive_time_period_microseconds(value)
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakePulseCounterSensor),
|
||||
vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
|
||||
vol.Optional(CONF_COUNT_MODE): vol.Schema({
|
||||
vol.Required(CONF_RISING_EDGE): COUNT_MODE_SCHEMA,
|
||||
vol.Required(CONF_FALLING_EDGE): COUNT_MODE_SCHEMA,
|
||||
}),
|
||||
vol.Optional(CONF_INTERNAL_FILTER): vol.All(vol.Coerce(int), vol.Range(min=0, max=1023)),
|
||||
vol.Optional(CONF_INTERNAL_FILTER): validate_internal_filter,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
|
||||
|
||||
vol.Optional(CONF_PULL_MODE): cv.invalid("The pull_mode option has been removed in 1.7.0, "
|
||||
"please use the pin mode schema now.")
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_pulse_counter_sensor(config[CONF_NAME], config[CONF_PIN],
|
||||
pin = None
|
||||
for pin in gpio_input_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_pulse_counter_sensor(config[CONF_NAME], pin,
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable('Application::MakePulseCounterSensor', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
pcnt = make.Ppcnt
|
||||
if CONF_PULL_MODE in config:
|
||||
pull_mode = GPIO_PULL_MODES[config[CONF_PULL_MODE]]
|
||||
add(pcnt.set_pull_mode(RawExpression(pull_mode)))
|
||||
if CONF_COUNT_MODE in config:
|
||||
count_mode = config[CONF_COUNT_MODE]
|
||||
rising_edge = COUNT_MODES[count_mode[CONF_RISING_EDGE]]
|
||||
falling_edge = COUNT_MODES[count_mode[CONF_FALLING_EDGE]]
|
||||
add(pcnt.set_edge_mode(RawExpression(rising_edge), RawExpression(falling_edge)))
|
||||
rising_edge = COUNT_MODES[config[CONF_COUNT_MODE][CONF_RISING_EDGE]]
|
||||
falling_edge = COUNT_MODES[config[CONF_COUNT_MODE][CONF_FALLING_EDGE]]
|
||||
add(pcnt.set_edge_mode(rising_edge, falling_edge))
|
||||
if CONF_INTERNAL_FILTER in config:
|
||||
add(pcnt.set_filter(config[CONF_INTERNAL_FILTER]))
|
||||
sensor.setup_sensor(pcnt, config)
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt, config)
|
||||
add(pcnt.set_filter_us(config[CONF_INTERNAL_FILTER]))
|
||||
sensor.setup_sensor(make.Ppcnt, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_PULSE_COUNTER_SENSOR'
|
||||
|
||||
51
esphomeyaml/components/sensor/rotary_encoder.py
Normal file
51
esphomeyaml/components/sensor/rotary_encoder.py
Normal file
@@ -0,0 +1,51 @@
|
||||
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_RESOLUTION
|
||||
from esphomeyaml.helpers import App, Application, add, gpio_input_pin_expression, variable
|
||||
|
||||
RESOLUTIONS = {
|
||||
'1': sensor.sensor_ns.ROTARY_ENCODER_1_PULSE_PER_CYCLE,
|
||||
'2': sensor.sensor_ns.ROTARY_ENCODER_2_PULSES_PER_CYCLE,
|
||||
'4': sensor.sensor_ns.ROTARY_ENCODER_4_PULSES_PER_CYCLE,
|
||||
}
|
||||
|
||||
CONF_PIN_A = 'pin_a'
|
||||
CONF_PIN_B = 'pin_b'
|
||||
CONF_PIN_RESET = 'pin_reset'
|
||||
|
||||
MakeRotaryEncoderSensor = Application.MakeRotaryEncoderSensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRotaryEncoderSensor),
|
||||
vol.Required(CONF_PIN_A): pins.internal_gpio_input_pin_schema,
|
||||
vol.Required(CONF_PIN_B): pins.internal_gpio_input_pin_schema,
|
||||
vol.Optional(CONF_PIN_RESET): pins.internal_gpio_input_pin_schema,
|
||||
vol.Optional(CONF_RESOLUTION): vol.All(cv.string, cv.one_of(*RESOLUTIONS)),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
pin_a = None
|
||||
for pin_a in gpio_input_pin_expression(config[CONF_PIN_A]):
|
||||
yield
|
||||
pin_b = None
|
||||
for pin_b in gpio_input_pin_expression(config[CONF_PIN_B]):
|
||||
yield
|
||||
rhs = App.make_rotary_encoder_sensor(config[CONF_NAME], pin_a, pin_b)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
encoder = make.Protary_encoder
|
||||
if CONF_PIN_RESET in config:
|
||||
pin_i = None
|
||||
for pin_i in gpio_input_pin_expression(config[CONF_PIN_RESET]):
|
||||
yield
|
||||
add(encoder.set_reset_pin(pin_i))
|
||||
if CONF_RESOLUTION in config:
|
||||
resolution = RESOLUTIONS[config[CONF_RESOLUTION]]
|
||||
add(encoder.set_resolution(resolution))
|
||||
sensor.setup_sensor(encoder, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ROTARY_ENCODER_SENSOR'
|
||||
@@ -2,44 +2,37 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
|
||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
|
||||
CONF_UPDATE_INTERVAL, CONF_ADDRESS, CONF_ACCURACY
|
||||
from esphomeyaml.helpers import App, variable, RawExpression, add
|
||||
from esphomeyaml.const import CONF_ACCURACY, CONF_ADDRESS, CONF_HUMIDITY, CONF_MAKE_ID, CONF_NAME, \
|
||||
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
SHT_ACCURACIES = {
|
||||
'LOW': 'sensor::SHT3XD_ACCURACY_LOW',
|
||||
'MEDIUM': 'sensor::SHT3XD_ACCURACY_MEDIUM',
|
||||
'HIGH': 'sensor::SHT3XD_ACCURACY_HIGH',
|
||||
}
|
||||
MakeSHT3XDSensor = Application.MakeSHT3XDSensor
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('sht3xd'): cv.register_variable_id,
|
||||
vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
|
||||
vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSHT3XDSensor),
|
||||
vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA),
|
||||
vol.Optional(CONF_ADDRESS, default=0x44): cv.i2c_address,
|
||||
vol.Optional(CONF_ACCURACY): vol.All(vol.Upper, vol.Any(*SHT_ACCURACIES)),
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
|
||||
vol.Optional(CONF_ACCURACY): cv.invalid("The accuracy option has been removed and now "
|
||||
"defaults to HIGH."),
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_sht3xd_sensor(config[CONF_TEMPERATURE][CONF_NAME],
|
||||
config[CONF_HUMIDITY][CONF_NAME],
|
||||
config[CONF_ADDRESS],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
sht3xd = variable('Application::MakeSHT3XDSensor', config[CONF_ID], rhs)
|
||||
sht3xd = variable(config[CONF_MAKE_ID], rhs)
|
||||
|
||||
if CONF_ACCURACY in config:
|
||||
constant = RawExpression(SHT_ACCURACIES[config[CONF_ACCURACY]])
|
||||
add(sht3xd.Psht3xd.set_accuracy(constant))
|
||||
|
||||
sensor.setup_sensor(sht3xd.Psht3xd.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
|
||||
sensor.setup_mqtt_sensor_component(sht3xd.Pmqtt_temperature, config[CONF_TEMPERATURE])
|
||||
|
||||
sensor.setup_sensor(sht3xd.PPsht3xd.Pget_humidity_sensor(), config[CONF_HUMIDITY])
|
||||
sensor.setup_mqtt_sensor_component(sht3xd.Pmqtt_humidity, config[CONF_HUMIDITY])
|
||||
sensor.setup_sensor(sht3xd.Psht3xd.Pget_temperature_sensor(), sht3xd.Pmqtt_temperature,
|
||||
config[CONF_TEMPERATURE])
|
||||
sensor.setup_sensor(sht3xd.Psht3xd.Pget_humidity_sensor(), sht3xd.Pmqtt_humidity,
|
||||
config[CONF_HUMIDITY])
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_SHT3XD'
|
||||
|
||||
28
esphomeyaml/components/sensor/template.py
Normal file
28
esphomeyaml/components/sensor/template.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, process_lambda, variable, Application, float_, optional
|
||||
|
||||
MakeTemplateSensor = Application.MakeTemplateSensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSensor),
|
||||
vol.Required(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
template_ = None
|
||||
for template_ in process_lambda(config[CONF_LAMBDA], [],
|
||||
return_type=optional.template(float_)):
|
||||
yield
|
||||
rhs = App.make_template_sensor(config[CONF_NAME], template_,
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
sensor.setup_sensor(make.Ptemplate_, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_TEMPLATE_SENSOR'
|
||||
@@ -2,20 +2,20 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_GAIN, CONF_ID, CONF_INTEGRATION_TIME, CONF_NAME, \
|
||||
CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, RawExpression, add, variable
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_GAIN, CONF_INTEGRATION_TIME, CONF_MAKE_ID, \
|
||||
CONF_NAME, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, add, variable
|
||||
|
||||
DEPENDENCIES = ['i2c']
|
||||
|
||||
INTEGRATION_TIMES = {
|
||||
14: 'sensor::TSL2561_INTEGRATION_14MS',
|
||||
101: 'sensor::TSL2561_INTEGRATION_101MS',
|
||||
402: 'sensor::TSL2561_INTEGRATION_402MS',
|
||||
14: sensor.sensor_ns.TSL2561_INTEGRATION_14MS,
|
||||
101: sensor.sensor_ns.TSL2561_INTEGRATION_101MS,
|
||||
402: sensor.sensor_ns.TSL2561_INTEGRATION_402MS,
|
||||
}
|
||||
GAINS = {
|
||||
'1X': 'sensor::TSL2561_GAIN_1X',
|
||||
'16X': 'sensor::TSL2561_GAIN_16X',
|
||||
'1X': sensor.sensor_ns.TSL2561_GAIN_1X,
|
||||
'16X': sensor.sensor_ns.TSL2561_GAIN_16X,
|
||||
}
|
||||
|
||||
CONF_IS_CS_PACKAGE = 'is_cs_package'
|
||||
@@ -28,31 +28,30 @@ def validate_integration_time(value):
|
||||
return value
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('tsl2561_sensor'): cv.register_variable_id,
|
||||
MakeTSL2561Sensor = Application.MakeTSL2561Sensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTSL2561Sensor),
|
||||
vol.Optional(CONF_ADDRESS, default=0x39): cv.i2c_address,
|
||||
vol.Optional(CONF_INTEGRATION_TIME): validate_integration_time,
|
||||
vol.Optional(CONF_GAIN): vol.All(vol.Upper, vol.Any(*GAINS)),
|
||||
vol.Optional(CONF_GAIN): vol.All(vol.Upper, cv.one_of(*GAINS)),
|
||||
vol.Optional(CONF_IS_CS_PACKAGE): cv.boolean,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_tsl2561_sensor(config[CONF_NAME], config[CONF_ADDRESS],
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make_tsl = variable('Application::MakeTSL2561Sensor', config[CONF_ID], rhs)
|
||||
make_tsl = variable(config[CONF_MAKE_ID], rhs)
|
||||
tsl2561 = make_tsl.Ptsl2561
|
||||
if CONF_INTEGRATION_TIME in config:
|
||||
constant = INTEGRATION_TIMES[config[CONF_INTEGRATION_TIME]]
|
||||
add(tsl2561.set_integration_time(RawExpression(constant)))
|
||||
add(tsl2561.set_integration_time(INTEGRATION_TIMES[config[CONF_INTEGRATION_TIME]]))
|
||||
if CONF_GAIN in config:
|
||||
constant = GAINS[config[CONF_GAIN]]
|
||||
add(tsl2561.set_gain(RawExpression(constant)))
|
||||
add(tsl2561.set_gain(GAINS[config[CONF_GAIN]]))
|
||||
if CONF_IS_CS_PACKAGE in config:
|
||||
add(tsl2561.set_is_cs_package(config[CONF_IS_CS_PACKAGE]))
|
||||
sensor.setup_sensor(tsl2561, config)
|
||||
sensor.setup_mqtt_sensor_component(make_tsl.Pmqtt, config)
|
||||
sensor.setup_sensor(tsl2561, make_tsl.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_TSL2561'
|
||||
|
||||
@@ -3,34 +3,39 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import sensor
|
||||
from esphomeyaml.const import CONF_ECHO_PIN, CONF_ID, CONF_NAME, \
|
||||
CONF_TIMEOUT_METER, CONF_TIMEOUT_TIME, CONF_TRIGGER_PIN, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, add, exp_gpio_input_pin, exp_gpio_output_pin, \
|
||||
variable
|
||||
from esphomeyaml.const import CONF_ECHO_PIN, CONF_MAKE_ID, CONF_NAME, CONF_TIMEOUT_METER, \
|
||||
CONF_TIMEOUT_TIME, CONF_TRIGGER_PIN, CONF_UPDATE_INTERVAL
|
||||
from esphomeyaml.helpers import App, Application, add, gpio_input_pin_expression, \
|
||||
gpio_output_pin_expression, variable
|
||||
|
||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('ultrasonic'): cv.register_variable_id,
|
||||
vol.Required(CONF_TRIGGER_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
vol.Required(CONF_ECHO_PIN): pins.GPIO_INPUT_PIN_SCHEMA,
|
||||
MakeUltrasonicSensor = Application.MakeUltrasonicSensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeUltrasonicSensor),
|
||||
vol.Required(CONF_TRIGGER_PIN): pins.gpio_output_pin_schema,
|
||||
vol.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema,
|
||||
vol.Exclusive(CONF_TIMEOUT_METER, 'timeout'): cv.positive_float,
|
||||
vol.Exclusive(CONF_TIMEOUT_TIME, 'timeout'): cv.positive_time_period_microseconds,
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
trigger = exp_gpio_output_pin(config[CONF_TRIGGER_PIN])
|
||||
echo = exp_gpio_input_pin(config[CONF_ECHO_PIN])
|
||||
trigger = None
|
||||
for trigger in gpio_output_pin_expression(config[CONF_TRIGGER_PIN]):
|
||||
yield
|
||||
echo = None
|
||||
for echo in gpio_input_pin_expression(config[CONF_ECHO_PIN]):
|
||||
yield
|
||||
rhs = App.make_ultrasonic_sensor(config[CONF_NAME], trigger, echo,
|
||||
config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable('Application::MakeUltrasonicSensor', config[CONF_ID], rhs)
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
ultrasonic = make.Pultrasonic
|
||||
if CONF_TIMEOUT_TIME in config:
|
||||
add(ultrasonic.set_timeout_us(config[CONF_TIMEOUT_TIME]))
|
||||
elif CONF_TIMEOUT_METER in config:
|
||||
add(ultrasonic.set_timeout_m(config[CONF_TIMEOUT_METER]))
|
||||
sensor.setup_sensor(ultrasonic, config)
|
||||
sensor.setup_mqtt_sensor_component(make.Pmqtt, config)
|
||||
sensor.setup_sensor(ultrasonic, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ULTRASONIC_SENSOR'
|
||||
|
||||
22
esphomeyaml/components/sensor/wifi_signal.py
Normal file
22
esphomeyaml/components/sensor/wifi_signal.py
Normal file
@@ -0,0 +1,22 @@
|
||||
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
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
MakeWiFiSignalSensor = Application.MakeWiFiSignalSensor
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeWiFiSignalSensor),
|
||||
vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_wifi_signal_sensor(config[CONF_NAME], config.get(CONF_UPDATE_INTERVAL))
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
sensor.setup_sensor(make.Pwifi, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_WIFI_SIGNAL_SENSOR'
|
||||
23
esphomeyaml/components/status_led.py
Normal file
23
esphomeyaml/components/status_led.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import voluptuous as vol
|
||||
|
||||
from esphomeyaml import config_validation as cv, pins
|
||||
from esphomeyaml.const import CONF_ID, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Pvariable, esphomelib_ns, gpio_output_pin_expression
|
||||
|
||||
StatusLED = esphomelib_ns.StatusLED
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(StatusLED),
|
||||
vol.Optional(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_status_led(pin)
|
||||
Pvariable(config[CONF_ID], rhs)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_STATUS_LED'
|
||||
@@ -1,36 +1,52 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.const import CONF_ICON, CONF_ID, CONF_NAME, CONF_MQTT_ID
|
||||
from esphomeyaml.helpers import App, Pvariable, add, setup_mqtt_component
|
||||
from esphomeyaml.const import CONF_ICON, CONF_ID, CONF_INVERTED, CONF_MQTT_ID, CONF_INTERNAL
|
||||
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, setup_mqtt_component
|
||||
|
||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
})
|
||||
|
||||
MQTT_SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
switch_ns = esphomelib_ns.namespace('switch_')
|
||||
Switch = switch_ns.Switch
|
||||
MQTTSwitchComponent = switch_ns.MQTTSwitchComponent
|
||||
ToggleAction = switch_ns.ToggleAction
|
||||
TurnOffAction = switch_ns.TurnOffAction
|
||||
TurnOnAction = switch_ns.TurnOnAction
|
||||
|
||||
SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(Switch),
|
||||
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSwitchComponent),
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_INVERTED): cv.boolean,
|
||||
})
|
||||
|
||||
MQTT_SWITCH_ID_SCHEMA = MQTT_SWITCH_SCHEMA.extend({
|
||||
cv.GenerateID('mqtt_switch', CONF_MQTT_ID): cv.register_variable_id,
|
||||
})
|
||||
SWITCH_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(SWITCH_SCHEMA.schema)
|
||||
|
||||
|
||||
def setup_mqtt_switch(obj, config):
|
||||
setup_mqtt_component(obj, config)
|
||||
|
||||
|
||||
def setup_switch(obj, config):
|
||||
def setup_switch_core_(switch_var, mqtt_var, config):
|
||||
if CONF_INTERNAL in config:
|
||||
add(switch_var.set_internal(config[CONF_INTERNAL]))
|
||||
if CONF_ICON in config:
|
||||
add(obj.set_icon(config[CONF_ICON]))
|
||||
add(switch_var.set_icon(config[CONF_ICON]))
|
||||
if CONF_INVERTED in config:
|
||||
add(switch_var.set_inverted(config[CONF_INVERTED]))
|
||||
|
||||
setup_mqtt_component(mqtt_var, config)
|
||||
|
||||
|
||||
def setup_switch(switch_obj, mqtt_obj, config):
|
||||
switch_var = Pvariable(config[CONF_ID], switch_obj, has_side_effects=False)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
|
||||
setup_switch_core_(switch_var, mqtt_var, config)
|
||||
|
||||
|
||||
def register_switch(var, config):
|
||||
setup_switch(var, config)
|
||||
rhs = App.register_switch(var)
|
||||
mqtt_switch = Pvariable('switch_::MQTTSwitchComponent', config[CONF_MQTT_ID], rhs)
|
||||
setup_mqtt_switch(mqtt_switch, config)
|
||||
switch_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
|
||||
rhs = App.register_switch(switch_var)
|
||||
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
|
||||
setup_switch_core_(switch_var, mqtt_var, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_SWITCH'
|
||||
|
||||
@@ -3,20 +3,24 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import pins
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME, CONF_PIN
|
||||
from esphomeyaml.helpers import App, exp_gpio_output_pin, variable
|
||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
|
||||
from esphomeyaml.helpers import App, Application, gpio_output_pin_expression, variable
|
||||
|
||||
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('gpio_switch'): cv.register_variable_id,
|
||||
vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
|
||||
}).extend(switch.MQTT_SWITCH_SCHEMA.schema)
|
||||
MakeGPIOSwitch = Application.MakeGPIOSwitch
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOSwitch),
|
||||
vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_gpio_switch(config[CONF_NAME], exp_gpio_output_pin(config[CONF_PIN]))
|
||||
gpio = variable('Application::MakeGPIOSwitch', config[CONF_ID], rhs)
|
||||
switch.setup_switch(gpio.Pswitch_, config)
|
||||
switch.setup_mqtt_switch(gpio.Pmqtt, config)
|
||||
pin = None
|
||||
for pin in gpio_output_pin_expression(config[CONF_PIN]):
|
||||
yield
|
||||
rhs = App.make_gpio_switch(config[CONF_NAME], pin)
|
||||
gpio = variable(config[CONF_MAKE_ID], rhs)
|
||||
switch.setup_switch(gpio.Pswitch_, gpio.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_GPIO_SWITCH'
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.components.ir_transmitter import IR_TRANSMITTER_COMPONENT_CLASS
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_FREQUENCY, CONF_COMMAND, CONF_DATA, \
|
||||
CONF_ID, CONF_IR_TRANSMITTER_ID, CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, CONF_PANASONIC, \
|
||||
CONF_RAW, CONF_REPEAT, CONF_SONY, CONF_TIMES, CONF_WAIT_TIME
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import ArrayInitializer, HexIntLiteral, MockObj, Pvariable, get_variable
|
||||
|
||||
DEPENDENCIES = ['ir_transmitter']
|
||||
|
||||
IR_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW]
|
||||
|
||||
WAIT_TIME_MESSAGE = "The wait_time_us option has been renamed to wait_time in order to decrease " \
|
||||
"ambiguity. "
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('ir_transmitter_switch'): cv.register_variable_id,
|
||||
vol.Exclusive(CONF_NEC, 'code'): vol.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint16_t,
|
||||
}),
|
||||
vol.Exclusive(CONF_LG, 'code'): vol.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=28): vol.All(vol.Coerce(int), vol.Range(min=0, max=32)),
|
||||
}),
|
||||
vol.Exclusive(CONF_SONY, 'code'): vol.Schema({
|
||||
vol.Required(CONF_DATA): cv.hex_uint32_t,
|
||||
vol.Optional(CONF_NBITS, default=12): vol.All(vol.Coerce(int), vol.Range(min=0, max=32)),
|
||||
}),
|
||||
vol.Exclusive(CONF_PANASONIC, 'code'): vol.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
|
||||
vol.Required(CONF_COMMAND): cv.hex_uint32_t,
|
||||
}),
|
||||
vol.Exclusive(CONF_RAW, 'code'): vol.Schema({
|
||||
vol.Required(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)),
|
||||
vol.Required(CONF_DATA): [vol.Coerce(int)],
|
||||
}),
|
||||
vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({
|
||||
vol.Required(CONF_TIMES): cv.positive_not_null_int,
|
||||
vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds,
|
||||
|
||||
vol.Optional('wait_time_us'): cv.invalid(WAIT_TIME_MESSAGE),
|
||||
})),
|
||||
vol.Optional(CONF_IR_TRANSMITTER_ID): cv.variable_id,
|
||||
}).extend(switch.MQTT_SWITCH_ID_SCHEMA.schema), cv.has_at_least_one_key(*IR_KEYS))
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
SendData = MockObj('switch_::ir::SendData', '::')
|
||||
|
||||
|
||||
def safe_hex(value):
|
||||
if value is None:
|
||||
return None
|
||||
return HexIntLiteral(value)
|
||||
|
||||
|
||||
def exp_send_data(config):
|
||||
if CONF_NEC in config:
|
||||
conf = config[CONF_NEC]
|
||||
base = SendData.from_nec(safe_hex(conf[CONF_ADDRESS]),
|
||||
safe_hex(conf[CONF_COMMAND]))
|
||||
elif CONF_LG in config:
|
||||
conf = config[CONF_LG]
|
||||
base = SendData.from_lg(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS))
|
||||
elif CONF_SONY in config:
|
||||
conf = config[CONF_SONY]
|
||||
base = SendData.from_sony(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS))
|
||||
elif CONF_PANASONIC in config:
|
||||
conf = config[CONF_PANASONIC]
|
||||
base = SendData.from_panasonic(safe_hex(conf[CONF_ADDRESS]),
|
||||
safe_hex(conf[CONF_COMMAND]))
|
||||
elif CONF_RAW in config:
|
||||
conf = config[CONF_RAW]
|
||||
data = ArrayInitializer(*conf[CONF_DATA])
|
||||
base = SendData.from_raw(data, conf[CONF_CARRIER_FREQUENCY])
|
||||
else:
|
||||
raise ESPHomeYAMLError(u"Unsupported IR mode {}".format(config))
|
||||
|
||||
if CONF_REPEAT in config:
|
||||
if isinstance(config[CONF_REPEAT], int):
|
||||
times = config[CONF_REPEAT]
|
||||
wait_us = None
|
||||
else:
|
||||
times = config[CONF_REPEAT][CONF_TIMES]
|
||||
wait_us = config[CONF_REPEAT][CONF_WAIT_TIME]
|
||||
base = MockObj(unicode(base), u'.')
|
||||
base = base.repeat(times, wait_us)
|
||||
return base
|
||||
|
||||
|
||||
def to_code(config):
|
||||
ir = get_variable(config.get(CONF_IR_TRANSMITTER_ID), IR_TRANSMITTER_COMPONENT_CLASS)
|
||||
send_data = exp_send_data(config)
|
||||
rhs = ir.create_transmitter(config[CONF_NAME], send_data)
|
||||
switch_ = Pvariable(IR_TRANSMITTER_COMPONENT_CLASS + '::DataTransmitter', config[CONF_ID],
|
||||
rhs)
|
||||
switch.register_switch(switch_, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_IR_TRANSMITTER'
|
||||
@@ -2,21 +2,24 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME, CONF_OUTPUT
|
||||
from esphomeyaml.helpers import App, get_variable, variable
|
||||
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
|
||||
from esphomeyaml.helpers import App, Application, get_variable, variable
|
||||
|
||||
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('output_switch'): cv.register_variable_id,
|
||||
vol.Required(CONF_OUTPUT): cv.variable_id,
|
||||
}).extend(switch.MQTT_SWITCH_SCHEMA.schema)
|
||||
MakeSimpleSwitch = Application.MakeSimpleSwitch
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSimpleSwitch),
|
||||
vol.Required(CONF_OUTPUT): cv.use_variable_id(None),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
output = get_variable(config[CONF_OUTPUT])
|
||||
output = None
|
||||
for output in get_variable(config[CONF_OUTPUT]):
|
||||
yield
|
||||
rhs = App.make_simple_switch(config[CONF_NAME], output)
|
||||
gpio = variable('Application::MakeSimpleSwitch', config[CONF_ID], rhs)
|
||||
switch.setup_switch(gpio.Pswitch_, config)
|
||||
switch.setup_mqtt_switch(gpio.Pmqtt, config)
|
||||
gpio = variable(config[CONF_MAKE_ID], rhs)
|
||||
switch.setup_switch(gpio.Pswitch_, gpio.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_SIMPLE_SWITCH'
|
||||
|
||||
105
esphomeyaml/components/switch/remote_transmitter.py
Normal file
105
esphomeyaml/components/switch/remote_transmitter.py
Normal file
@@ -0,0 +1,105 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.components.remote_transmitter import RemoteTransmitterComponent, remote_ns
|
||||
from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_FREQUENCY, CONF_COMMAND, CONF_DATA, \
|
||||
CONF_INVERTED, CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, \
|
||||
CONF_PANASONIC, CONF_RAW, CONF_REPEAT, CONF_SONY, CONF_TIMES, CONF_WAIT_TIME
|
||||
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, get_variable
|
||||
|
||||
DEPENDENCIES = ['remote_transmitter']
|
||||
|
||||
IR_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW]
|
||||
|
||||
CONF_REMOTE_TRANSMITTER_ID = 'remote_transmitter_id'
|
||||
CONF_TRANSMITTER_ID = 'transmitter_id'
|
||||
|
||||
RemoteTransmitter = remote_ns.RemoteTransmitter
|
||||
LGTransmitter = remote_ns.LGTransmitter
|
||||
NECTransmitter = remote_ns.NECTransmitter
|
||||
PanasonicTransmitter = remote_ns.PanasonicTransmitter
|
||||
RawTransmitter = remote_ns.RawTransmitter
|
||||
SonyTransmitter = remote_ns.SonyTransmitter
|
||||
|
||||
validate_raw_data = [vol.Any(vol.Coerce(int), cv.time_period_microseconds)]
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_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(validate_raw_data, vol.Schema({
|
||||
vol.Required(CONF_DATA): validate_raw_data,
|
||||
vol.Optional(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)),
|
||||
})),
|
||||
vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({
|
||||
vol.Required(CONF_TIMES): cv.positive_not_null_int,
|
||||
vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds,
|
||||
})),
|
||||
cv.GenerateID(CONF_REMOTE_TRANSMITTER_ID): cv.use_variable_id(RemoteTransmitterComponent),
|
||||
cv.GenerateID(CONF_TRANSMITTER_ID): cv.declare_variable_id(RemoteTransmitter),
|
||||
|
||||
vol.Optional(CONF_INVERTED): cv.invalid("Remote Transmitters do not support inverted mode!"),
|
||||
}), cv.has_exactly_one_key(*IR_KEYS))
|
||||
|
||||
|
||||
def transmitter_base(config):
|
||||
if CONF_LG in config:
|
||||
conf = config[CONF_LG]
|
||||
return LGTransmitter.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS])
|
||||
elif CONF_NEC in config:
|
||||
conf = config[CONF_NEC]
|
||||
return NECTransmitter.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND])
|
||||
elif CONF_PANASONIC in config:
|
||||
conf = config[CONF_PANASONIC]
|
||||
return PanasonicTransmitter.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND])
|
||||
elif CONF_SONY in config:
|
||||
conf = config[CONF_SONY]
|
||||
return SonyTransmitter.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS])
|
||||
elif CONF_RAW in config:
|
||||
conf = config[CONF_RAW]
|
||||
if isinstance(conf, dict):
|
||||
data = conf[CONF_DATA]
|
||||
carrier_frequency = conf.get(CONF_CARRIER_FREQUENCY)
|
||||
else:
|
||||
data = conf
|
||||
carrier_frequency = None
|
||||
return RawTransmitter.new(config[CONF_NAME], ArrayInitializer(*data, multiline=False),
|
||||
carrier_frequency)
|
||||
else:
|
||||
raise ValueError("Unknown transmitter type {}".format(config))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
remote = None
|
||||
for remote in get_variable(config[CONF_REMOTE_TRANSMITTER_ID]):
|
||||
yield
|
||||
rhs = App.register_component(transmitter_base(config))
|
||||
transmitter = Pvariable(config[CONF_TRANSMITTER_ID], rhs)
|
||||
|
||||
if CONF_REPEAT in config:
|
||||
if isinstance(config[CONF_REPEAT], int):
|
||||
times = config[CONF_REPEAT]
|
||||
wait_us = 1000
|
||||
else:
|
||||
times = config[CONF_REPEAT][CONF_TIMES]
|
||||
wait_us = config[CONF_REPEAT][CONF_WAIT_TIME]
|
||||
add(transmitter.set_repeat(times, wait_us))
|
||||
|
||||
switch.register_switch(remote.add_transmitter(transmitter), config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER'
|
||||
@@ -1,18 +1,22 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, variable
|
||||
from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('restart_switch'): cv.register_variable_id,
|
||||
}).extend(switch.MQTT_SWITCH_SCHEMA.schema)
|
||||
MakeRestartSwitch = Application.MakeRestartSwitch
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRestartSwitch),
|
||||
vol.Optional(CONF_INVERTED): cv.invalid("Restart switches do not support inverted mode!"),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_restart_switch(config[CONF_NAME])
|
||||
restart = variable('Application::MakeRestartSwitch', config[CONF_ID], rhs)
|
||||
switch.setup_switch(restart.Prestart, config)
|
||||
switch.setup_mqtt_switch(restart.Pmqtt, config)
|
||||
restart = variable(config[CONF_MAKE_ID], rhs)
|
||||
switch.setup_switch(restart.Prestart, restart.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_RESTART_SWITCH'
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.const import CONF_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, variable
|
||||
from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME
|
||||
from esphomeyaml.helpers import App, Application, variable
|
||||
|
||||
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID('shutdown_switch'): cv.register_variable_id,
|
||||
}).extend(switch.MQTT_SWITCH_SCHEMA.schema)
|
||||
MakeShutdownSwitch = Application.MakeShutdownSwitch
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeShutdownSwitch),
|
||||
vol.Optional(CONF_INVERTED): cv.invalid("Shutdown switches do not support inverted mode!"),
|
||||
}))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_shutdown_switch(config[CONF_NAME])
|
||||
shutdown = variable('Application::MakeShutdownSwitch', config[CONF_ID],
|
||||
rhs)
|
||||
switch.setup_switch(shutdown.Pshutdown, config)
|
||||
switch.setup_mqtt_switch(shutdown.Pmqtt, config)
|
||||
shutdown = variable(config[CONF_MAKE_ID], rhs)
|
||||
switch.setup_switch(shutdown.Pshutdown, shutdown.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_SHUTDOWN_SWITCH'
|
||||
|
||||
44
esphomeyaml/components/switch/template.py
Normal file
44
esphomeyaml/components/switch/template.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import automation
|
||||
from esphomeyaml.components import switch
|
||||
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_TURN_OFF_ACTION, \
|
||||
CONF_TURN_ON_ACTION, CONF_OPTIMISTIC
|
||||
from esphomeyaml.helpers import App, Application, process_lambda, variable, NoArg, add, bool_, \
|
||||
optional
|
||||
|
||||
MakeTemplateSwitch = Application.MakeTemplateSwitch
|
||||
|
||||
PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSwitch),
|
||||
vol.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
||||
vol.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(),
|
||||
vol.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(),
|
||||
}), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.make_template_switch(config[CONF_NAME])
|
||||
make = variable(config[CONF_MAKE_ID], rhs)
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
template_ = None
|
||||
for template_ in process_lambda(config[CONF_LAMBDA], [],
|
||||
return_type=optional.template(bool_)):
|
||||
yield
|
||||
add(make.Ptemplate_.set_state_lambda(template_))
|
||||
if CONF_TURN_OFF_ACTION in config:
|
||||
automation.build_automation(make.Ptemplate_.get_turn_off_trigger(), NoArg,
|
||||
config[CONF_TURN_OFF_ACTION])
|
||||
if CONF_TURN_ON_ACTION in config:
|
||||
automation.build_automation(make.Ptemplate_.get_turn_on_trigger(), NoArg,
|
||||
config[CONF_TURN_ON_ACTION])
|
||||
if CONF_OPTIMISTIC in config:
|
||||
add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC]))
|
||||
|
||||
switch.setup_switch(make.Ptemplate_, make.Pmqtt, config)
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_TEMPLATE_SWITCH'
|
||||
@@ -5,21 +5,23 @@ import voluptuous as vol
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import core
|
||||
from esphomeyaml.const import CONF_PORT, CONF_JS_URL, CONF_CSS_URL, CONF_ID, ESP_PLATFORM_ESP32
|
||||
from esphomeyaml.helpers import App, add, Pvariable
|
||||
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
WebServer = esphomelib_ns.WebServer
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('web_server'): cv.register_variable_id,
|
||||
cv.GenerateID(): cv.declare_variable_id(WebServer),
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
vol.Optional(CONF_CSS_URL): vol.Url,
|
||||
vol.Optional(CONF_JS_URL): vol.Url,
|
||||
vol.Optional(CONF_CSS_URL): cv.string,
|
||||
vol.Optional(CONF_JS_URL): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = App.init_web_server(config.get(CONF_PORT))
|
||||
web_server = Pvariable('WebServer', config[CONF_ID], rhs)
|
||||
web_server = Pvariable(config[CONF_ID], rhs)
|
||||
if CONF_CSS_URL in config:
|
||||
add(web_server.set_css_url(config[CONF_CSS_URL]))
|
||||
if CONF_JS_URL in config:
|
||||
|
||||
@@ -2,10 +2,10 @@ import voluptuous as vol
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import core
|
||||
from esphomeyaml.const import CONF_AP, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_GATEWAY, \
|
||||
CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET, \
|
||||
ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.helpers import App, MockObj, Pvariable, StructInitializer, add
|
||||
from esphomeyaml.const import CONF_AP, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \
|
||||
CONF_GATEWAY, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_REBOOT_TIMEOUT, \
|
||||
CONF_SSID, CONF_STATIC_IP, CONF_SUBNET, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.helpers import App, Pvariable, StructInitializer, add, esphomelib_ns, global_ns
|
||||
|
||||
|
||||
def validate_password(value):
|
||||
@@ -19,6 +19,15 @@ def validate_password(value):
|
||||
return value
|
||||
|
||||
|
||||
def validate_channel(value):
|
||||
value = cv.positive_int(value)
|
||||
if value < 1:
|
||||
raise vol.Invalid("Minimum WiFi channel is 1")
|
||||
if value > 14:
|
||||
raise vol.Invalid("Maximum WiFi channel is 14")
|
||||
return value
|
||||
|
||||
|
||||
AP_MANUAL_IP_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_STATIC_IP): cv.ipv4,
|
||||
vol.Required(CONF_GATEWAY): cv.ipv4,
|
||||
@@ -30,33 +39,60 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({
|
||||
vol.Inclusive(CONF_DNS2, 'dns'): cv.ipv4,
|
||||
})
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
cv.GenerateID('wifi'): cv.register_variable_id,
|
||||
WIFI_NETWORK_BASE = vol.Schema({
|
||||
vol.Required(CONF_SSID): cv.ssid,
|
||||
vol.Optional(CONF_PASSWORD): validate_password,
|
||||
vol.Optional(CONF_CHANNEL): validate_channel,
|
||||
vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA,
|
||||
})
|
||||
|
||||
WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({
|
||||
vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA,
|
||||
})
|
||||
|
||||
WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({
|
||||
vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
|
||||
})
|
||||
|
||||
|
||||
def validate(config):
|
||||
if CONF_PASSWORD in config and CONF_SSID not in config:
|
||||
raise vol.Invalid("Cannot have WiFi password without SSID!")
|
||||
if CONF_SSID not in config and CONF_AP not in config:
|
||||
raise vol.Invalid("Please specify at least an SSID or an Access Point "
|
||||
"to create.")
|
||||
return config
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
IPAddress = global_ns.IPAddress
|
||||
ManualIP = esphomelib_ns.ManualIP
|
||||
WiFiComponent = esphomelib_ns.WiFiComponent
|
||||
WiFiAp = esphomelib_ns.WiFiAp
|
||||
|
||||
CONFIG_SCHEMA = vol.All(vol.Schema({
|
||||
cv.GenerateID(): cv.declare_variable_id(WiFiComponent),
|
||||
vol.Optional(CONF_SSID): cv.ssid,
|
||||
vol.Optional(CONF_PASSWORD): validate_password,
|
||||
vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
|
||||
vol.Optional(CONF_AP): vol.Schema({
|
||||
vol.Required(CONF_SSID): cv.ssid,
|
||||
vol.Optional(CONF_PASSWORD): validate_password,
|
||||
vol.Optional(CONF_CHANNEL): vol.All(cv.positive_int, vol.Range(min=1, max=14)),
|
||||
vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA,
|
||||
}),
|
||||
vol.Optional(CONF_AP): WIFI_NETWORK_AP,
|
||||
vol.Optional(CONF_HOSTNAME): cv.hostname,
|
||||
})
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
IPAddress = MockObj('IPAddress')
|
||||
vol.Optional(CONF_DOMAIN, default='.local'): cv.domainname,
|
||||
vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds,
|
||||
}), validate)
|
||||
|
||||
|
||||
def safe_ip(ip):
|
||||
if ip is None:
|
||||
return None
|
||||
return IPAddress(0, 0, 0, 0)
|
||||
return IPAddress(*ip.args)
|
||||
|
||||
|
||||
def manual_ip(config):
|
||||
if config is None:
|
||||
return None
|
||||
return StructInitializer(
|
||||
'ManualIP',
|
||||
ManualIP,
|
||||
('static_ip', safe_ip(config[CONF_STATIC_IP])),
|
||||
('gateway', safe_ip(config[CONF_GATEWAY])),
|
||||
('subnet', safe_ip(config[CONF_SUBNET])),
|
||||
@@ -65,31 +101,32 @@ def manual_ip(config):
|
||||
)
|
||||
|
||||
|
||||
def wifi_network(config):
|
||||
return StructInitializer(
|
||||
WiFiAp,
|
||||
('ssid', config.get(CONF_SSID, "")),
|
||||
('password', config.get(CONF_PASSWORD, "")),
|
||||
('channel', config.get(CONF_CHANNEL, -1)),
|
||||
('manual_ip', manual_ip(config.get(CONF_MANUAL_IP))),
|
||||
)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
sta = CONF_SSID in config
|
||||
ap = CONF_AP in config
|
||||
if sta:
|
||||
rhs = App.init_wifi(config[CONF_SSID], config.get(CONF_PASSWORD))
|
||||
else:
|
||||
rhs = App.init_wifi()
|
||||
wifi = Pvariable('WiFiComponent', config[CONF_ID], rhs)
|
||||
rhs = App.init_wifi()
|
||||
wifi = Pvariable(config[CONF_ID], rhs)
|
||||
|
||||
if sta and CONF_MANUAL_IP in config:
|
||||
add(wifi.set_sta_manual_ip(manual_ip(config[CONF_MANUAL_IP])))
|
||||
if CONF_SSID in config:
|
||||
add(wifi.set_sta(wifi_network(config)))
|
||||
|
||||
if ap:
|
||||
conf = config[CONF_AP]
|
||||
password = config.get(CONF_PASSWORD)
|
||||
if password is None and CONF_CHANNEL in conf:
|
||||
password = u""
|
||||
add(wifi.set_ap(conf[CONF_SSID], password, conf.get(CONF_CHANNEL)))
|
||||
|
||||
if CONF_MANUAL_IP in conf:
|
||||
add(wifi.set_ap_manual_ip(manual_ip(conf[CONF_MANUAL_IP])))
|
||||
if CONF_AP in config:
|
||||
add(wifi.set_ap(wifi_network(config[CONF_AP])))
|
||||
|
||||
if CONF_HOSTNAME in config:
|
||||
add(wifi.set_hostname(config[CONF_HOSTNAME]))
|
||||
|
||||
if CONF_REBOOT_TIMEOUT in config:
|
||||
add(wifi.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||
|
||||
|
||||
def lib_deps(config):
|
||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
|
||||
|
||||
24
esphomeyaml/config.json
Normal file
24
esphomeyaml/config.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "esphomeyaml",
|
||||
"version": "1.7.0",
|
||||
"slug": "esphomeyaml",
|
||||
"description": "esphomeyaml HassIO add-on for intelligently managing all your ESP8266/ESP32 devices.",
|
||||
"url": "https://esphomelib.com/esphomeyaml/index.html",
|
||||
"startup": "application",
|
||||
"webui": "http://[HOST]:[PORT:6052]",
|
||||
"boot": "auto",
|
||||
"ports": {
|
||||
"6052/tcp": 6052,
|
||||
"6053/tcp": 6053
|
||||
},
|
||||
"auto_uart": true,
|
||||
"map": [
|
||||
"config:rw"
|
||||
],
|
||||
"options": {},
|
||||
"environment": {
|
||||
"ESPHOMEYAML_OTA_HOST_PORT": "6053"
|
||||
},
|
||||
"schema": {},
|
||||
"image": "ottowinter/esphomeyaml-hassio-{arch}"
|
||||
}
|
||||
@@ -8,19 +8,21 @@ import voluptuous as vol
|
||||
from voluptuous.humanize import humanize_error
|
||||
|
||||
import esphomeyaml.config_validation as cv
|
||||
from esphomeyaml import core, yaml_util
|
||||
from esphomeyaml import core, yaml_util, automation
|
||||
from esphomeyaml.const import CONF_BOARD, CONF_BOARD_FLASH_MODE, CONF_ESPHOMEYAML, \
|
||||
CONF_LIBRARY_URI, \
|
||||
CONF_NAME, CONF_PLATFORM, CONF_SIMPLIFY, CONF_USE_BUILD_FLAGS, CONF_WIFI, ESP_PLATFORMS, \
|
||||
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
|
||||
CONF_LIBRARY_URI, CONF_NAME, CONF_PLATFORM, CONF_SIMPLIFY, CONF_USE_BUILD_FLAGS, CONF_WIFI, \
|
||||
ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, CONF_ON_BOOT, CONF_TRIGGER_ID, \
|
||||
CONF_PRIORITY, CONF_ON_SHUTDOWN
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import App, add, color
|
||||
from esphomeyaml.helpers import App, add, color, esphomelib_ns, Pvariable, NoArg, const_char_p
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.5.1'
|
||||
DEFAULT_LIBRARY_URI = u'https://github.com/OttoWinter/esphomelib.git#v1.7.0'
|
||||
|
||||
BUILD_FLASH_MODES = ['qio', 'qout', 'dio', 'dout']
|
||||
StartupTrigger = esphomelib_ns.StartupTrigger
|
||||
ShutdownTrigger = esphomelib_ns.ShutdownTrigger
|
||||
|
||||
CORE_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_NAME): cv.valid_name,
|
||||
@@ -29,7 +31,14 @@ CORE_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_LIBRARY_URI, default=DEFAULT_LIBRARY_URI): cv.string,
|
||||
vol.Optional(CONF_SIMPLIFY, default=True): cv.boolean,
|
||||
vol.Optional(CONF_USE_BUILD_FLAGS, default=True): cv.boolean,
|
||||
vol.Optional(CONF_BOARD_FLASH_MODE): vol.All(vol.Lower, vol.Any(*BUILD_FLASH_MODES)),
|
||||
vol.Optional(CONF_BOARD_FLASH_MODE): vol.All(vol.Lower, cv.one_of(*BUILD_FLASH_MODES)),
|
||||
vol.Optional(CONF_ON_BOOT): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(StartupTrigger),
|
||||
vol.Optional(CONF_PRIORITY): vol.Coerce(float),
|
||||
})]),
|
||||
vol.Optional(CONF_ON_SHUTDOWN): vol.All(cv.ensure_list, [automation.validate_automation({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ShutdownTrigger),
|
||||
})]),
|
||||
})
|
||||
|
||||
REQUIRED_COMPONENTS = [
|
||||
@@ -43,6 +52,15 @@ _ALL_COMPONENTS = []
|
||||
def core_to_code(config):
|
||||
add(App.set_name(config[CONF_NAME]))
|
||||
|
||||
for conf in config.get(CONF_ON_BOOT, []):
|
||||
rhs = App.register_component(StartupTrigger.new(conf.get(CONF_PRIORITY)))
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
automation.build_automation(trigger, NoArg, conf)
|
||||
|
||||
for conf in config.get(CONF_ON_SHUTDOWN, []):
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], ShutdownTrigger.new())
|
||||
automation.build_automation(trigger, const_char_p, conf)
|
||||
|
||||
|
||||
def get_component(domain):
|
||||
if domain in _COMPONENT_CACHE:
|
||||
@@ -93,6 +111,50 @@ class Config(OrderedDict):
|
||||
self.errors.append((message, domain, config))
|
||||
|
||||
|
||||
def iter_ids(config, prefix=None, parent=None):
|
||||
prefix = prefix or []
|
||||
parent = parent or {}
|
||||
if isinstance(config, core.ID):
|
||||
yield config, prefix, parent
|
||||
elif isinstance(config, core.Lambda):
|
||||
for id in config.requires_ids:
|
||||
yield id, prefix, parent
|
||||
elif isinstance(config, list):
|
||||
for i, item in enumerate(config):
|
||||
for result in iter_ids(item, prefix + [str(i)], config):
|
||||
yield result
|
||||
elif isinstance(config, dict):
|
||||
for key, value in config.iteritems():
|
||||
for result in iter_ids(value, prefix + [str(key)], config):
|
||||
yield result
|
||||
|
||||
|
||||
def do_id_pass(result):
|
||||
declare_ids = []
|
||||
searching_ids = []
|
||||
for id, prefix, config in iter_ids(result):
|
||||
if id.is_declaration:
|
||||
if id.id is not None and any(v[0].id == id.id for v in declare_ids):
|
||||
result.add_error("ID {} redefined!".format(id.id), '.'.join(prefix), config)
|
||||
continue
|
||||
declare_ids.append((id, prefix, config))
|
||||
else:
|
||||
searching_ids.append((id, prefix, config))
|
||||
# Resolve default ids after manual IDs
|
||||
for id, _, _ in declare_ids:
|
||||
id.resolve([v[0].id for v in declare_ids])
|
||||
|
||||
# Check searched IDs
|
||||
for id, prefix, config in searching_ids:
|
||||
if id.id is not None and not any(v[0].id == id.id for v in declare_ids):
|
||||
result.add_error("Couldn't find ID {}".format(id.id), '.'.join(prefix), config)
|
||||
if id.id is None and id.type is not None:
|
||||
id.id = next((v[0].id for v in declare_ids if v[0].type == id.type), None)
|
||||
if id.id is None:
|
||||
result.add_error("Couldn't resolve ID for type {}".format(id.type),
|
||||
'.'.join(prefix), config)
|
||||
|
||||
|
||||
def validate_config(config):
|
||||
global _ALL_COMPONENTS
|
||||
|
||||
@@ -131,7 +193,7 @@ def validate_config(config):
|
||||
dependencies = getattr(component, 'DEPENDENCIES', [])
|
||||
for dependency in dependencies:
|
||||
if dependency not in _ALL_COMPONENTS:
|
||||
result.add_error(u"Component {} requires {}".format(domain, dependency))
|
||||
result.add_error(u"Component {} requires component {}".format(domain, dependency))
|
||||
success = False
|
||||
if not success:
|
||||
continue
|
||||
@@ -158,19 +220,25 @@ def validate_config(config):
|
||||
continue
|
||||
platform = get_platform(domain, p_name)
|
||||
if platform is None:
|
||||
result.add_error(u"Platform not found: {}.{}")
|
||||
result.add_error(u"Platform not found: {}.{}".format(domain, p_name))
|
||||
continue
|
||||
|
||||
success = True
|
||||
dependencies = getattr(platform, 'DEPENDENCIES', [])
|
||||
for dependency in dependencies:
|
||||
if dependency not in _ALL_COMPONENTS:
|
||||
result.add_error(u"Platform {}.{} requires {}".format(domain, p_name,
|
||||
dependency))
|
||||
result.add_error(u"Platform {}.{} requires component {}".format(domain, p_name,
|
||||
dependency))
|
||||
success = False
|
||||
if not success:
|
||||
continue
|
||||
|
||||
esp_platforms = getattr(platform, 'ESP_PLATFORMS', ESP_PLATFORMS)
|
||||
if core.ESP_PLATFORM not in esp_platforms:
|
||||
result.add_error(
|
||||
u"Platform {}.{} doesn't support {}.".format(domain, p_name, core.ESP_PLATFORM))
|
||||
continue
|
||||
|
||||
if hasattr(platform, u'PLATFORM_SCHEMA'):
|
||||
try:
|
||||
p_validated = platform.PLATFORM_SCHEMA(p_config)
|
||||
@@ -179,6 +247,8 @@ def validate_config(config):
|
||||
continue
|
||||
platforms.append(p_validated)
|
||||
result[domain] = platforms
|
||||
|
||||
do_id_pass(result)
|
||||
return result
|
||||
|
||||
|
||||
@@ -215,20 +285,26 @@ def load_config(path):
|
||||
if CONF_ESPHOMEYAML not in config:
|
||||
raise ESPHomeYAMLError(u"No esphomeyaml section in config")
|
||||
core_conf = config[CONF_ESPHOMEYAML]
|
||||
esp_platform = unicode(core_conf.get(CONF_PLATFORM, u""))
|
||||
if CONF_PLATFORM not in core_conf:
|
||||
raise ESPHomeYAMLError("esphomeyaml.platform not specified.")
|
||||
esp_platform = unicode(core_conf[CONF_PLATFORM])
|
||||
esp_platform = esp_platform.upper()
|
||||
if '8266' in esp_platform:
|
||||
esp_platform = ESP_PLATFORM_ESP8266
|
||||
if '32' in esp_platform:
|
||||
esp_platform = ESP_PLATFORM_ESP32
|
||||
core.ESP_PLATFORM = esp_platform
|
||||
core.BOARD = unicode(core_conf.get(CONF_BOARD, u""))
|
||||
if CONF_BOARD not in core_conf:
|
||||
raise ESPHomeYAMLError("esphomeyaml.board not specified.")
|
||||
core.BOARD = unicode(core_conf[CONF_BOARD])
|
||||
core.SIMPLIFY = cv.boolean(core_conf.get(CONF_SIMPLIFY, True))
|
||||
|
||||
try:
|
||||
result = validate_config(config)
|
||||
except ESPHomeYAMLError:
|
||||
raise
|
||||
except Exception:
|
||||
print(u"Unexpected exception while reading configuration:")
|
||||
_LOGGER.error(u"Unexpected exception while reading configuration:")
|
||||
raise
|
||||
|
||||
return result
|
||||
@@ -269,18 +345,18 @@ def dump_dict(layer, indent_count=3, listi=False, **kwargs):
|
||||
|
||||
|
||||
def read_config(path):
|
||||
_LOGGER.debug("Reading configuration...")
|
||||
_LOGGER.info("Reading configuration...")
|
||||
try:
|
||||
res = load_config(path)
|
||||
except ESPHomeYAMLError as err:
|
||||
_LOGGER.error(u"Error while reading config: %s", err)
|
||||
return None
|
||||
excepts = {}
|
||||
for err in res.errors:
|
||||
domain = err[1] or u"General Error"
|
||||
excepts.setdefault(domain, []).append(err[0])
|
||||
if err[2] is not None:
|
||||
excepts[domain].append(err[2])
|
||||
for message, domain, config in res.errors:
|
||||
domain = domain or u"General Error"
|
||||
excepts.setdefault(domain, []).append(message)
|
||||
if config is not None:
|
||||
excepts[domain].append(config)
|
||||
|
||||
if excepts:
|
||||
print(color('bold_white', u"Failed config"))
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import print_function
|
||||
|
||||
import logging
|
||||
import re
|
||||
import uuid as uuid_
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -11,10 +12,9 @@ from esphomeyaml import core
|
||||
from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_ID, \
|
||||
CONF_NAME, CONF_PAYLOAD_AVAILABLE, \
|
||||
CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \
|
||||
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import HexInt, IPAddress, TimePeriod, TimePeriodMilliseconds, \
|
||||
TimePeriodMicroseconds, TimePeriodSeconds
|
||||
from esphomeyaml.helpers import ensure_unique_string
|
||||
ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, CONF_INTERNAL
|
||||
from esphomeyaml.core import HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \
|
||||
TimePeriodMilliseconds, TimePeriodSeconds
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -26,7 +26,7 @@ zero_to_one_float = vol.All(vol.Coerce(float), vol.Range(min=0, max=1))
|
||||
positive_int = vol.All(vol.Coerce(int), vol.Range(min=0))
|
||||
positive_not_null_int = vol.All(vol.Coerce(int), vol.Range(min=0, min_included=False))
|
||||
|
||||
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
||||
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_'
|
||||
|
||||
RESERVED_IDS = [
|
||||
# C++ keywords http://en.cppreference.com/w/cpp/keyword
|
||||
@@ -57,8 +57,10 @@ def alphanumeric(value):
|
||||
|
||||
def valid_name(value):
|
||||
value = string_strict(value)
|
||||
if not all(c in ALLOWED_NAME_CHARS for c in value):
|
||||
raise vol.Invalid(u"Valid characters for name are {}".format(ALLOWED_NAME_CHARS))
|
||||
for c in value:
|
||||
if c not in ALLOWED_NAME_CHARS:
|
||||
raise vol.Invalid(u"'{}' is an invalid character for names. Valid characters are: {}"
|
||||
u"".format(c, ALLOWED_NAME_CHARS))
|
||||
return value
|
||||
|
||||
|
||||
@@ -134,16 +136,54 @@ def int_(value):
|
||||
|
||||
|
||||
hex_int = vol.Coerce(hex_int_)
|
||||
match_cpp_var_ = vol.Match(r'^[a-zA-Z_][a-zA-Z0-9_]+$', msg=u"Must be a valid C++ variable name")
|
||||
|
||||
|
||||
def variable_id(value):
|
||||
value = match_cpp_var_(value)
|
||||
def variable_id_str_(value):
|
||||
value = string(value)
|
||||
if not value:
|
||||
raise vol.Invalid("ID must not be empty")
|
||||
if value[0].isdigit():
|
||||
raise vol.Invalid("First character in ID cannot be a digit.")
|
||||
if '-' in value:
|
||||
raise vol.Invalid("Dashes are not supported in IDs, please use underscores instead.")
|
||||
for char in value:
|
||||
if char != '_' and not char.isalnum():
|
||||
raise vol.Invalid(u"IDs must only consist of upper/lowercase characters and numbers."
|
||||
u"The character '{}' cannot be used".format(char))
|
||||
if value in RESERVED_IDS:
|
||||
raise vol.Invalid(u"ID {} is reserved internally and cannot be used".format(value))
|
||||
return value
|
||||
|
||||
|
||||
def use_variable_id(type):
|
||||
def validator(value):
|
||||
if value is None:
|
||||
return core.ID(None, is_declaration=False, type=type)
|
||||
|
||||
return core.ID(variable_id_str_(value), is_declaration=False, type=type)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
def declare_variable_id(type):
|
||||
def validator(value):
|
||||
if value is None:
|
||||
return core.ID(None, is_declaration=True, type=type)
|
||||
|
||||
return core.ID(variable_id_str_(value), is_declaration=True, type=type)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
def templatable(other_validators):
|
||||
def validator(value):
|
||||
if isinstance(value, Lambda):
|
||||
return value
|
||||
return other_validators(value)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
def only_on(platforms):
|
||||
if not isinstance(platforms, list):
|
||||
platforms = [platforms]
|
||||
@@ -170,10 +210,24 @@ def has_at_least_one_key(*keys):
|
||||
if not isinstance(obj, dict):
|
||||
raise vol.Invalid('expected dictionary')
|
||||
|
||||
for k in obj.keys():
|
||||
if k in keys:
|
||||
return obj
|
||||
raise vol.Invalid('must contain one of {}.'.format(', '.join(keys)))
|
||||
if not any(k in keys for k in obj):
|
||||
raise vol.Invalid('Must contain at least one of {}.'.format(', '.join(keys)))
|
||||
return obj
|
||||
|
||||
return validate
|
||||
|
||||
|
||||
def has_exactly_one_key(*keys):
|
||||
def validate(obj):
|
||||
if not isinstance(obj, dict):
|
||||
raise vol.Invalid('expected dictionary')
|
||||
|
||||
number = sum(k in keys for k in obj)
|
||||
if number > 1:
|
||||
raise vol.Invalid("Cannot specify more than one of {}.".format(', '.join(keys)))
|
||||
if number < 1:
|
||||
raise vol.Invalid('Must contain exactly one of {}.'.format(', '.join(keys)))
|
||||
return obj
|
||||
|
||||
return validate
|
||||
|
||||
@@ -194,14 +248,6 @@ time_period_dict = vol.All(
|
||||
lambda value: TimePeriod(**value))
|
||||
|
||||
|
||||
TIME_PERIOD_EXPLICIT_MESSAGE = ("The old way of being able to write time values without a "
|
||||
"time unit (like \"1000\" for 1000 milliseconds) has been "
|
||||
"removed in 1.5.0 as it was ambiguous in some places. Please "
|
||||
"now explicitly specify the time unit (like \"1000ms\"). See "
|
||||
"https://esphomelib.com/esphomeyaml/configuration-types.html#time "
|
||||
"for more information.")
|
||||
|
||||
|
||||
def time_period_str_colon(value):
|
||||
"""Validate and transform time offset with format HH:MM[:SS]."""
|
||||
if isinstance(value, int):
|
||||
@@ -209,13 +255,6 @@ def time_period_str_colon(value):
|
||||
elif not isinstance(value, str):
|
||||
raise vol.Invalid(TIME_PERIOD_ERROR.format(value))
|
||||
|
||||
negative_offset = False
|
||||
if value.startswith('-'):
|
||||
negative_offset = True
|
||||
value = value[1:]
|
||||
elif value.startswith('+'):
|
||||
value = value[1:]
|
||||
|
||||
try:
|
||||
parsed = [int(x) for x in value.split(':')]
|
||||
except ValueError:
|
||||
@@ -229,12 +268,7 @@ def time_period_str_colon(value):
|
||||
else:
|
||||
raise vol.Invalid(TIME_PERIOD_ERROR.format(value))
|
||||
|
||||
offset = TimePeriod(hours=hour, minutes=minute, seconds=second)
|
||||
|
||||
if negative_offset:
|
||||
offset *= -1
|
||||
|
||||
return offset
|
||||
return TimePeriod(hours=hour, minutes=minute, seconds=second)
|
||||
|
||||
|
||||
def time_period_str_unit(value):
|
||||
@@ -244,13 +278,6 @@ def time_period_str_unit(value):
|
||||
elif not isinstance(value, (str, unicode)):
|
||||
raise vol.Invalid("Expected string for time period with unit.")
|
||||
|
||||
try:
|
||||
float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
raise vol.Invalid(TIME_PERIOD_EXPLICIT_MESSAGE)
|
||||
|
||||
unit_to_kwarg = {
|
||||
'us': 'microseconds',
|
||||
'microseconds': 'microseconds',
|
||||
@@ -277,17 +304,17 @@ def time_period_str_unit(value):
|
||||
return TimePeriod(**{kwarg: float(match.group(1))})
|
||||
|
||||
|
||||
def time_period_in_milliseconds(value):
|
||||
def time_period_in_milliseconds_(value):
|
||||
if value.microseconds is not None and value.microseconds != 0:
|
||||
raise vol.Invalid("Maximum precision is milliseconds")
|
||||
return TimePeriodMilliseconds(**value.as_dict())
|
||||
|
||||
|
||||
def time_period_in_microseconds(value):
|
||||
def time_period_in_microseconds_(value):
|
||||
return TimePeriodMicroseconds(**value.as_dict())
|
||||
|
||||
|
||||
def time_period_in_seconds(value):
|
||||
def time_period_in_seconds_(value):
|
||||
if value.microseconds is not None and value.microseconds != 0:
|
||||
raise vol.Invalid("Maximum precision is seconds")
|
||||
if value.milliseconds is not None and value.milliseconds != 0:
|
||||
@@ -297,13 +324,35 @@ def time_period_in_seconds(value):
|
||||
|
||||
time_period = vol.Any(time_period_str_unit, time_period_str_colon, time_period_dict)
|
||||
positive_time_period = vol.All(time_period, vol.Range(min=TimePeriod()))
|
||||
positive_time_period_milliseconds = vol.All(positive_time_period, time_period_in_milliseconds)
|
||||
positive_time_period_seconds = vol.All(positive_time_period, time_period_in_seconds)
|
||||
positive_time_period_microseconds = vol.All(positive_time_period, time_period_in_microseconds)
|
||||
positive_time_period_milliseconds = vol.All(positive_time_period, time_period_in_milliseconds_)
|
||||
positive_time_period_seconds = vol.All(positive_time_period, time_period_in_seconds_)
|
||||
time_period_microseconds = vol.All(time_period, time_period_in_microseconds_)
|
||||
positive_time_period_microseconds = vol.All(positive_time_period, time_period_in_microseconds_)
|
||||
positive_not_null_time_period = vol.All(time_period,
|
||||
vol.Range(min=TimePeriod(), min_included=False))
|
||||
|
||||
|
||||
def mac_address(value):
|
||||
value = 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 core.MACAddress(*parts_int)
|
||||
|
||||
|
||||
def uuid(value):
|
||||
return vol.Coerce(uuid_.UUID)(value)
|
||||
|
||||
|
||||
METRIC_SUFFIXES = {
|
||||
'E': 1e18, 'P': 1e15, 'T': 1e12, 'G': 1e9, 'M': 1e6, 'k': 1e3, 'da': 10, 'd': 1e-1,
|
||||
'c': 1e-2, 'm': 0.001, u'µ': 1e-6, 'u': 1e-6, 'n': 1e-9, 'p': 1e-12, 'f': 1e-15, 'a': 1e-18,
|
||||
@@ -327,6 +376,23 @@ def frequency(value):
|
||||
return mantissa * multiplier
|
||||
|
||||
|
||||
def validate_bytes(value):
|
||||
value = string(value)
|
||||
match = re.match(r"^([0-9]+)\s*(\w*?)(?:byte|B|b)?s?$", value)
|
||||
|
||||
if match is None:
|
||||
raise vol.Invalid(u"Expected number of bytes with unit, got {}".format(value))
|
||||
|
||||
mantissa = int(match.group(1))
|
||||
if match.group(2) not in METRIC_SUFFIXES:
|
||||
raise vol.Invalid(u"Invalid metric suffix {}".format(match.group(2)))
|
||||
multiplier = METRIC_SUFFIXES[match.group(2)]
|
||||
if multiplier < 1:
|
||||
raise vol.Invalid(u"Only suffixes with positive exponents are supported. "
|
||||
u"Got {}".format(match.group(2)))
|
||||
return int(mantissa * multiplier)
|
||||
|
||||
|
||||
def hostname(value):
|
||||
value = string(value)
|
||||
if len(value) > 63:
|
||||
@@ -337,6 +403,18 @@ def hostname(value):
|
||||
return value
|
||||
|
||||
|
||||
def domainname(value):
|
||||
value = string(value)
|
||||
if not value.startswith('.'):
|
||||
raise vol.Invalid("Domainname must start with .")
|
||||
if value.startswith('..'):
|
||||
raise vol.Invalid("Domainname must start with single .")
|
||||
for c in value:
|
||||
if not (c.isalnum() or c in '._-'):
|
||||
raise vol.Invalid("Domainname can only have alphanumeric characters and _ or -")
|
||||
return value
|
||||
|
||||
|
||||
def ssid(value):
|
||||
if value is None:
|
||||
raise vol.Invalid("SSID can not be None")
|
||||
@@ -422,6 +500,14 @@ def mqtt_payload(value):
|
||||
return string(value)
|
||||
|
||||
|
||||
def mqtt_qos(value):
|
||||
try:
|
||||
value = int(value)
|
||||
except (TypeError, ValueError):
|
||||
raise vol.Invalid(u"MQTT Quality of Service must be integer, got {}".format(value))
|
||||
return one_of(0, 1, 2)(value)
|
||||
|
||||
|
||||
uint8_t = vol.All(int_, vol.Range(min=0, max=255))
|
||||
uint16_t = vol.All(int_, vol.Range(min=0, max=65535))
|
||||
uint32_t = vol.All(int_, vol.Range(min=0, max=4294967295))
|
||||
@@ -431,9 +517,22 @@ hex_uint32_t = vol.All(hex_int, vol.Range(min=0, max=4294967295))
|
||||
i2c_address = hex_uint8_t
|
||||
|
||||
|
||||
def percentage(value):
|
||||
if isinstance(value, (str, unicode)) and value.endswith('%'):
|
||||
value = float(value[:-1].rstrip()) / 100.0
|
||||
return zero_to_one_float(value)
|
||||
|
||||
|
||||
def percentage_int(value):
|
||||
if isinstance(value, (str, unicode)) and value.endswith('%'):
|
||||
value = int(value[:-1].rstrip())
|
||||
return value
|
||||
|
||||
|
||||
def invalid(message):
|
||||
def validator(value):
|
||||
raise vol.Invalid(message)
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
@@ -441,29 +540,47 @@ def valid(value):
|
||||
return value
|
||||
|
||||
|
||||
def one_of(*values):
|
||||
options = u', '.join(u"'{}'".format(x) for x in values)
|
||||
|
||||
def validator(value):
|
||||
if value not in values:
|
||||
raise vol.Invalid(u"Unknown value '{}', must be one of {}".format(value, options))
|
||||
return value
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
def lambda_(value):
|
||||
if isinstance(value, Lambda):
|
||||
return value
|
||||
return Lambda(string_strict(value))
|
||||
|
||||
|
||||
REGISTERED_IDS = set()
|
||||
|
||||
|
||||
def register_variable_id(value):
|
||||
s = variable_id(value)
|
||||
if s in REGISTERED_IDS:
|
||||
raise vol.Invalid("This ID has already been used")
|
||||
REGISTERED_IDS.add(s)
|
||||
return s
|
||||
|
||||
|
||||
class GenerateID(vol.Optional):
|
||||
def __init__(self, basename, key=CONF_ID):
|
||||
self._basename = basename
|
||||
super(GenerateID, self).__init__(key, default=self.default_variable_id)
|
||||
|
||||
def default_variable_id(self):
|
||||
return ensure_unique_string(self._basename, REGISTERED_IDS)
|
||||
def __init__(self, key=CONF_ID):
|
||||
super(GenerateID, self).__init__(key, default=lambda: None)
|
||||
|
||||
|
||||
REQUIRED_ID_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ID): register_variable_id,
|
||||
})
|
||||
def nameable(*schemas):
|
||||
def validator(config):
|
||||
config = vol.All(*schemas)(config)
|
||||
if CONF_NAME not in config and CONF_ID not in config:
|
||||
raise vol.Invalid("At least one of 'id:' or 'name:' is required!")
|
||||
if CONF_NAME not in config:
|
||||
id = config[CONF_ID]
|
||||
if not id.is_manual:
|
||||
raise vol.Invalid("At least one of 'id:' or 'name:' is required!")
|
||||
config[CONF_NAME] = id.id
|
||||
config[CONF_INTERNAL] = True
|
||||
return config
|
||||
return config
|
||||
|
||||
return validator
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): valid,
|
||||
@@ -476,11 +593,12 @@ MQTT_COMPONENT_AVAILABILITY_SCHEMA = vol.Schema({
|
||||
})
|
||||
|
||||
MQTT_COMPONENT_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_NAME): string,
|
||||
vol.Optional(CONF_NAME): string,
|
||||
vol.Optional(CONF_RETAIN): boolean,
|
||||
vol.Optional(CONF_DISCOVERY): boolean,
|
||||
vol.Optional(CONF_STATE_TOPIC): publish_topic,
|
||||
vol.Optional(CONF_AVAILABILITY): MQTT_COMPONENT_AVAILABILITY_SCHEMA,
|
||||
vol.Optional(CONF_AVAILABILITY): vol.Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA),
|
||||
vol.Optional(CONF_INTERNAL): boolean,
|
||||
})
|
||||
|
||||
MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Constants used by esphomeyaml."""
|
||||
|
||||
MAJOR_VERSION = 1
|
||||
MINOR_VERSION = 5
|
||||
PATCH_VERSION = '1'
|
||||
MINOR_VERSION = 7
|
||||
PATCH_VERSION = '0'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
|
||||
@@ -34,6 +34,13 @@ CONF_USERNAME = 'username'
|
||||
CONF_POWER_SUPPLY = 'power_supply'
|
||||
CONF_ID = 'id'
|
||||
CONF_MQTT_ID = 'mqtt_id'
|
||||
CONF_SENSOR_ID = 'sensor_id'
|
||||
CONF_TRIGGER_ID = 'trigger_id'
|
||||
CONF_ACTION_ID = 'action_id'
|
||||
CONF_CONDITION_ID = 'condition_id'
|
||||
CONF_MAKE_ID = 'make_id'
|
||||
CONF_AUTOMATION_ID = 'automation_id'
|
||||
CONF_DELAY = 'delay'
|
||||
CONF_PIN = 'pin'
|
||||
CONF_NUMBER = 'number'
|
||||
CONF_INVERTED = 'inverted'
|
||||
@@ -70,6 +77,15 @@ CONF_TOPIC = 'topic'
|
||||
CONF_PAYLOAD_AVAILABLE = 'payload_available'
|
||||
CONF_PAYLOAD_NOT_AVAILABLE = 'payload_not_available'
|
||||
CONF_DEFAULT_TRANSITION_LENGTH = 'default_transition_length'
|
||||
CONF_TRANSITION_LENGTH = 'transition_length'
|
||||
CONF_FLASH_LENGTH = 'flash_length'
|
||||
CONF_BRIGHTNESS = 'brightness'
|
||||
CONF_EFFECT = 'effect'
|
||||
CONF_ABOVE = 'above'
|
||||
CONF_BELOW = 'below'
|
||||
CONF_ON = 'on'
|
||||
CONF_IF = 'if'
|
||||
CONF_THEN = 'then'
|
||||
CONF_BINARY = 'binary'
|
||||
CONF_WHITE = 'white'
|
||||
CONF_RGBW = 'rgbw'
|
||||
@@ -109,6 +125,14 @@ CONF_WINDOW_SIZE = 'window_size'
|
||||
CONF_SEND_EVERY = 'send_every'
|
||||
CONF_ALPHA = 'alpha'
|
||||
CONF_LAMBDA = 'lambda'
|
||||
CONF_THROTTLE = 'throttle'
|
||||
CONF_DELTA = 'delta'
|
||||
CONF_OR = 'or'
|
||||
CONF_AND = 'and'
|
||||
CONF_RANGE = 'range'
|
||||
CONF_UNIQUE = 'unique'
|
||||
CONF_HEARTBEAT = 'heartbeat'
|
||||
CONF_DEBOUNCE = 'debounce'
|
||||
CONF_UPDATE_INTERVAL = 'update_interval'
|
||||
CONF_PULL_MODE = 'pull_mode'
|
||||
CONF_COUNT_MODE = 'count_mode'
|
||||
@@ -124,7 +148,6 @@ CONF_TRIGGER_PIN = 'trigger_pin'
|
||||
CONF_ECHO_PIN = 'echo_pin'
|
||||
CONF_TIMEOUT_METER = 'timeout_meter'
|
||||
CONF_TIMEOUT_TIME = 'timeout_time'
|
||||
CONF_IR_TRANSMITTER_ID = 'ir_transmitter_id'
|
||||
CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent'
|
||||
CONF_NEC = 'nec'
|
||||
CONF_COMMAND = 'command'
|
||||
@@ -140,6 +163,7 @@ CONF_OSCILLATION_OUTPUT = 'oscillation_output'
|
||||
CONF_SPEED = 'speed'
|
||||
CONF_OSCILLATION_STATE_TOPIC = 'oscillation_state_topic'
|
||||
CONF_OSCILLATION_COMMAND_TOPIC = 'oscillation_command_topic'
|
||||
CONF_OSCILLATING = 'oscillating'
|
||||
CONF_SPEED_STATE_TOPIC = 'speed_state_topic'
|
||||
CONF_SPEED_COMMAND_TOPIC = 'speed_command_topic'
|
||||
CONF_LOW = 'low'
|
||||
@@ -186,6 +210,43 @@ CONF_CLOCK_PIN = 'clock_pin'
|
||||
CONF_RGB_ORDER = 'rgb_order'
|
||||
CONF_ACCURACY = 'accuracy'
|
||||
CONF_BOARD_FLASH_MODE = 'board_flash_mode'
|
||||
CONF_ON_PRESS = 'on_press'
|
||||
CONF_ON_RELEASE = 'on_release'
|
||||
CONF_ON_CLICK = 'on_click'
|
||||
CONF_ON_DOUBLE_CLICK = 'on_double_click'
|
||||
CONF_MIN_LENGTH = 'min_length'
|
||||
CONF_MAX_LENGTH = 'max_length'
|
||||
CONF_ON_VALUE = 'on_value'
|
||||
CONF_ON_RAW_VALUE = 'on_raw_value'
|
||||
CONF_ON_VALUE_RANGE = 'on_value_range'
|
||||
CONF_ON_MESSAGE = 'on_message'
|
||||
CONF_PIN_CS = 'pin_cs'
|
||||
CONF_PIN_CLOCK = 'pin_clock'
|
||||
CONF_PIN_MISO = 'pin_miso'
|
||||
CONF_TURN_ON_ACTION = 'turn_on_action'
|
||||
CONF_TURN_OFF_ACTION = 'turn_off_action'
|
||||
CONF_OPEN_ACTION = 'open_action'
|
||||
CONF_CLOSE_ACTION = 'close_action'
|
||||
CONF_STOP_ACTION = 'stop_action'
|
||||
CONF_DOMAIN = 'domain'
|
||||
CONF_OPTIMISTIC = 'optimistic'
|
||||
CONF_ON_BOOT = 'on_boot'
|
||||
CONF_ON_SHUTDOWN = 'on_shutdown'
|
||||
CONF_PRIORITY = 'priority'
|
||||
CONF_DUMP = 'dump'
|
||||
CONF_BUFFER_SIZE = 'buffer_size'
|
||||
CONF_TOLERANCE = 'tolerance'
|
||||
CONF_FILTER = 'filter'
|
||||
CONF_IDLE = 'idle'
|
||||
CONF_NETWORKS = 'networks'
|
||||
CONF_INTERNAL = 'internal'
|
||||
CONF_BUILD_PATH = 'build_path'
|
||||
CONF_REBOOT_TIMEOUT = 'reboot_timeout'
|
||||
CONF_INVERT = 'invert'
|
||||
CONF_DELAYED_ON = 'delayed_on'
|
||||
CONF_DELAYED_OFF = 'delayed_off'
|
||||
CONF_UUID = 'uuid'
|
||||
CONF_TYPE = 'type'
|
||||
|
||||
ESP32_BOARDS = [
|
||||
'featheresp32', 'node32s', 'espea32', 'firebeetle32', 'esp32doit-devkit-v1',
|
||||
@@ -208,3 +269,5 @@ ESP_BOARDS_FOR_PLATFORM = {
|
||||
ESP_PLATFORM_ESP32: ESP32_BOARDS,
|
||||
ESP_PLATFORM_ESP8266: ESP8266_BOARDS
|
||||
}
|
||||
|
||||
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user