[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234)

* Implement custom sensor platform

* Update

* Ethernet

* Lint

* Fix

* Login page

* Rename cookie secret

* Update manifest

* Update cookie check logic

* Favicon

* Fix

* Favicon manifest

* Fix

* Fix

* Fix

* Use hostname

* Message

* Temporary commit for screenshot

* Automatic board selection

* Undo temporary commit

* Update esphomeyaml-edge

* In-dashboard editing and hosting files locally

* Update esphomeyaml-edge

* Better ANSI color escaping

* Message

* Lint

* Download Efficiency

* Fix gitlab

* Fix

* Rename extra_libraries to libraries

* Add example

* Update README.md

* Update README.md

* Update README.md

* HassIO -> Hass.io

* Updates

* Add update available notice

* Update

* Fix substitutions

* Better error message

* Re-do dashboard ANSI colors

* Only include FastLED if user says so

* Autoscroll logs

* Remove old checks

* Use safer RedirectText

* Improvements

* Fix

* Use enviornment variable

* Use http://hassio/host/info

* Fix conditions

* Update platformio versions

* Revert "Use enviornment variable"

This reverts commit 7f038eb5d2.

* Fix

* README update

* Temp

* Better invalid config messages

* Platformio debug

* Improve error messages

* Debug

* Remove debug

* Multi Conf

* Update

* Better paths

* Remove unused

* Fixes

* Lint

* lib_ignore

* Try fix platformio colors

* Fix dashboard scrolling

* Revert

* Lint

* Revert
This commit is contained in:
Otto Winter 2018-12-05 21:22:06 +01:00 committed by GitHub
parent 2b88c987da
commit 7c7032c59e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
192 changed files with 6156 additions and 2845 deletions

1
.gitignore vendored
View File

@ -105,3 +105,4 @@ venv.bak/
config/ config/
tests/build/ tests/build/
tests/.esphomeyaml/

View File

@ -11,6 +11,8 @@ stages:
.lint: &lint .lint: &lint
stage: lint stage: lint
before_script:
- pip install -e .
tags: tags:
- python2.7 - python2.7
- esphomeyaml-lint - esphomeyaml-lint
@ -24,9 +26,6 @@ stages:
- esphomeyaml-test - esphomeyaml-test
variables: variables:
TZ: UTC TZ: UTC
cache:
paths:
- tests/build
.docker-builder: &docker-builder .docker-builder: &docker-builder
before_script: before_script:
@ -62,21 +61,20 @@ test2:
stage: build stage: build
script: script:
- docker run --rm --privileged hassioaddons/qemu-user-static:latest - docker run --rm --privileged hassioaddons/qemu-user-static:latest
- BUILD_FROM=homeassistant/${ADDON_ARCH}-base-ubuntu:latest - BUILD_FROM=hassioaddons/ubuntu-base-${ADDON_ARCH}:2.2.0
- ADDON_VERSION="${CI_COMMIT_TAG#v}" - ADDON_VERSION="${CI_COMMIT_TAG#v}"
- ADDON_VERSION="${ADDON_VERSION:-${CI_COMMIT_SHA:0:7}}" - ADDON_VERSION="${ADDON_VERSION:-${CI_COMMIT_SHA:0:7}}"
- ESPHOMELIB_VERSION="${ESPHOMELIB_VERSION:-''}"
- echo "Build from ${BUILD_FROM}" - echo "Build from ${BUILD_FROM}"
- echo "Add-on version ${ADDON_VERSION}" - echo "Add-on version ${ADDON_VERSION}"
- echo "Esphomelib version ${ESPHOMELIB_VERSION}"
- echo "Tag ${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:dev" - echo "Tag ${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:dev"
- echo "Tag ${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}" - echo "Tag ${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}"
- | - |
docker build \ docker build \
--build-arg "BUILD_FROM=${BUILD_FROM}" \ --build-arg "BUILD_FROM=${BUILD_FROM}" \
--build-arg "ADDON_ARCH=${ADDON_ARCH}" \ --build-arg "BUILD_DATE=$(date +"%Y-%m-%dT%H:%M:%SZ")" \
--build-arg "ADDON_VERSION=${ADDON_VERSION}" \ --build-arg "BUILD_ARCH=${ADDON_ARCH}" \
--build-arg "ESPHOMELIB_VERSION=${ESPHOMELIB_VERSION}" \ --build-arg "BUILD_REF=${CI_COMMIT_SHA}" \
--build-arg "BUILD_VERSION=${ADDON_VERSION}" \
--tag "${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:dev" \ --tag "${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:dev" \
--tag "${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}" \ --tag "${CI_REGISTRY}/esphomeyaml-hassio-${ADDON_ARCH}:${CI_COMMIT_SHA}" \
--file "docker/Dockerfile.hassio" \ --file "docker/Dockerfile.hassio" \
@ -209,31 +207,28 @@ build:hassio-armhf-edge:
variables: variables:
ADDON_ARCH: armhf ADDON_ARCH: armhf
DO_PUSH: "false" DO_PUSH: "false"
ESPHOMELIB_VERSION: "${CI_COMMIT_TAG}"
build:hassio-armhf: build:hassio-armhf:
<<: *build-hassio-release <<: *build-hassio-release
variables: variables:
ADDON_ARCH: armhf ADDON_ARCH: armhf
build:hassio-aarch64-edge: #build:hassio-aarch64-edge:
<<: *build-hassio-edge # <<: *build-hassio-edge
variables: # variables:
ADDON_ARCH: aarch64 # ADDON_ARCH: aarch64
DO_PUSH: "false" # DO_PUSH: "false"
ESPHOMELIB_VERSION: "${CI_COMMIT_TAG}"
build:hassio-aarch64: #build:hassio-aarch64:
<<: *build-hassio-release # <<: *build-hassio-release
variables: # variables:
ADDON_ARCH: aarch64 # ADDON_ARCH: aarch64
build:hassio-i386-edge: build:hassio-i386-edge:
<<: *build-hassio-edge <<: *build-hassio-edge
variables: variables:
ADDON_ARCH: i386 ADDON_ARCH: i386
DO_PUSH: "false" DO_PUSH: "false"
ESPHOMELIB_VERSION: "${CI_COMMIT_TAG}"
build:hassio-i386: build:hassio-i386:
<<: *build-hassio-release <<: *build-hassio-release
@ -245,7 +240,6 @@ build:hassio-amd64-edge:
variables: variables:
ADDON_ARCH: amd64 ADDON_ARCH: amd64
DO_PUSH: "false" DO_PUSH: "false"
ESPHOMELIB_VERSION: "${CI_COMMIT_TAG}"
build:hassio-amd64: build:hassio-amd64:
<<: *build-hassio-release <<: *build-hassio-release
@ -263,15 +257,15 @@ deploy-beta:armhf:
variables: variables:
ADDON_ARCH: armhf ADDON_ARCH: armhf
deploy-release:aarch64: #deploy-release:aarch64:
<<: *deploy-release # <<: *deploy-release
variables: # variables:
ADDON_ARCH: aarch64 # ADDON_ARCH: aarch64
deploy-beta:aarch64: #deploy-beta:aarch64:
<<: *deploy-beta # <<: *deploy-beta
variables: # variables:
ADDON_ARCH: aarch64 # ADDON_ARCH: aarch64
deploy-release:i386: deploy-release:i386:
<<: *deploy-release <<: *deploy-release

View File

@ -1,4 +1,16 @@
include README.md include README.md
include esphomeyaml/dashboard/templates/index.html include esphomeyaml/dashboard/templates/index.html
include esphomeyaml/dashboard/templates/login.html
include esphomeyaml/dashboard/static/ace.js
include esphomeyaml/dashboard/static/esphomeyaml.css
include esphomeyaml/dashboard/static/esphomeyaml.js
include esphomeyaml/dashboard/static/favicon.ico
include esphomeyaml/dashboard/static/jquery.min.js
include esphomeyaml/dashboard/static/jquery.validate.min.js
include esphomeyaml/dashboard/static/jquery-ui.min.js
include esphomeyaml/dashboard/static/materialize.min.css
include esphomeyaml/dashboard/static/materialize.min.js
include esphomeyaml/dashboard/static/materialize-stepper.min.css include esphomeyaml/dashboard/static/materialize-stepper.min.css
include esphomeyaml/dashboard/static/materialize-stepper.min.js include esphomeyaml/dashboard/static/materialize-stepper.min.js
include esphomeyaml/dashboard/static/mode-yaml.js
include esphomeyaml/dashboard/static/theme-dreamweaver.js

View File

@ -1,40 +1,78 @@
# Dockerfile for HassIO add-on ARG BUILD_FROM=hassioaddons/ubuntu-base:2.2.0
ARG BUILD_FROM=homeassistant/amd64-base-ubuntu:latest # hadolint ignore=DL3006
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
RUN apt-get update && apt-get install -y --no-install-recommends \ # Set shell
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Copy root filesystem
COPY esphomeyaml-edge/rootfs /
COPY setup.py setup.cfg MANIFEST.in /opt/esphomeyaml/
COPY esphomeyaml /opt/esphomeyaml/esphomeyaml
RUN \
# Temporarily move nginx.conf (otherwise dpkg fails)
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bkp \
# Install add-on dependencies
&& apt-get update \
&& apt-get install -y --no-install-recommends \
# Python for esphomeyaml
python \ python \
python-pip \ python-pip \
python-setuptools \ python-setuptools \
# Python Pillow for display component
python-pil \ python-pil \
# Git for esphomelib downloads
git \ git \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* && \ # Ping for dashboard online/offline status
pip install --no-cache-dir --no-binary :all: platformio && \ iputils-ping \
platformio settings set enable_telemetry No && \ # NGINX proxy
platformio settings set check_libraries_interval 1000000 && \ nginx \
platformio settings set check_platformio_interval 1000000 && \ \
platformio settings set check_platforms_interval 1000000 && mv /etc/nginx/nginx.conf.bkp /etc/nginx/nginx.conf \
\
COPY docker/platformio.ini /pio/platformio.ini && pip2 install --no-cache-dir --no-binary :all: -e /opt/esphomeyaml \
RUN platformio run -d /pio; rm -rf /pio \
# tzlocal for automatic timezone detection
&& pip2 install --no-cache-dir --no-binary :all: tzlocal \
COPY . . \
RUN pip install --no-cache-dir --no-binary :all: -e . && \ # Change some platformio settings
pip install --no-cache-dir --no-binary :all: tzlocal && platformio settings set enable_telemetry No \
&& platformio settings set check_libraries_interval 1000000 \
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"] && platformio settings set check_platformio_interval 1000000 \
&& platformio settings set check_platforms_interval 1000000 \
\
# Build an empty platformio project to force platformio to install all fw build dependencies
# The return-code will be non-zero since there's nothing to build.
&& (platformio run -d /opt/pio; echo "Done") \
\
# Cleanup
&& rm -fr \
/tmp/* \
/var/{cache,log}/* \
/var/lib/apt/lists/* \
/opt/pio/
# Build arugments # Build arugments
ARG ADDON_ARCH ARG BUILD_ARCH=amd64
ARG ADDON_VERSION ARG BUILD_DATE
ARG BUILD_REF
ARG BUILD_VERSION
# Labels # Labels
LABEL \ LABEL \
io.hass.name="esphomeyaml" \ io.hass.name="esphomeyaml" \
io.hass.description="esphomeyaml HassIO add-on for intelligently managing all your ESP8266/ESP32 devices." \ io.hass.description="Manage and program ESP8266/ESP32 microcontrollers through YAML configuration files" \
io.hass.arch="${ADDON_ARCH}" \ io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \ io.hass.type="addon" \
io.hass.version="${ADDON_VERSION}" \ io.hass.version=${BUILD_VERSION} \
io.hass.url="https://esphomelib.com/esphomeyaml/index.html" \ maintainer="Otto Winter <contact@otto-winter.com>" \
maintainer="Otto Winter <contact@otto-winter.com>" org.label-schema.description="Manage and program ESP8266/ESP32 microcontrollers through YAML configuration files" \
org.label-schema.build-date=${BUILD_DATE} \
org.label-schema.name="esphomeyaml" \
org.label-schema.schema-version="1.0" \
org.label-schema.url="https://esphomelib.com" \
org.label-schema.usage="https://github.com/OttoWinter/esphomeyaml/tree/dev/esphomeyaml/README.md" \
org.label-schema.vcs-ref=${BUILD_REF} \
org.label-schema.vcs-url="https://github.com/OttoWinter/esphomeyaml" \
org.label-schema.vendor="esphomelib"

View File

@ -8,7 +8,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
git \ git \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*rm -rf /var/lib/apt/lists/* /tmp/* && \
pip install --no-cache-dir --no-binary :all: platformio && \ pip install --no-cache-dir --no-binary :all: platformio && \
platformio settings set enable_telemetry No platformio settings set enable_telemetry No && \
platformio settings set check_libraries_interval 1000000 && \
platformio settings set check_platformio_interval 1000000 && \
platformio settings set check_platforms_interval 1000000
COPY docker/platformio.ini /pio/platformio.ini COPY docker/platformio.ini /pio/platformio.ini
RUN platformio run -d /pio; rm -rf /pio RUN platformio run -d /pio; rm -rf /pio
@ -16,4 +19,4 @@ RUN platformio run -d /pio; rm -rf /pio
COPY requirements.txt /requirements.txt COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt && \ RUN pip install --no-cache-dir -r /requirements.txt && \
pip install --no-cache-dir tzlocal pillow pip install --no-cache-dir tzlocal

View File

@ -2,7 +2,7 @@
"name": "esphomeyaml-beta", "name": "esphomeyaml-beta",
"version": "1.9.3", "version": "1.9.3",
"slug": "esphomeyaml-beta", "slug": "esphomeyaml-beta",
"description": "Beta version of esphomeyaml HassIO add-on.", "description": "Beta version of esphomeyaml Hass.io add-on.",
"url": "https://beta.esphomelib.com/esphomeyaml/index.html", "url": "https://beta.esphomelib.com/esphomeyaml/index.html",
"startup": "application", "startup": "application",
"webui": "http://[HOST]:[PORT:6052]", "webui": "http://[HOST]:[PORT:6052]",

View File

@ -1,24 +1,76 @@
# Dockerfile for HassIO edge add-on ARG BUILD_FROM=hassioaddons/ubuntu-base:2.2.0
ARG BUILD_FROM=homeassistant/amd64-base-ubuntu:latest # hadolint ignore=DL3006
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
RUN apt-get update && apt-get install -y --no-install-recommends \ # Set shell
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Copy root filesystem
COPY rootfs /
RUN \
# Temporarily move nginx.conf (otherwise dpkg fails)
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bkp \
# Install add-on dependencies
&& apt-get update \
&& apt-get install -y --no-install-recommends \
# Python for esphomeyaml
python \ python \
python-pip \ python-pip \
python-setuptools \ python-setuptools \
# Python Pillow for display component
python-pil \ python-pil \
# Git for esphomelib downloads
git \ git \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* && \ # Ping for dashboard online/offline status
pip install --no-cache-dir --no-binary :all: platformio && \ iputils-ping \
platformio settings set enable_telemetry No && \ # NGINX proxy
platformio settings set check_libraries_interval 1000000 && \ nginx \
platformio settings set check_platformio_interval 1000000 && \ \
platformio settings set check_platforms_interval 1000000 && mv /etc/nginx/nginx.conf.bkp /etc/nginx/nginx.conf \
\
&& pip2 install --no-cache-dir --no-binary :all: https://github.com/OttoWinter/esphomeyaml/archive/dev.zip \
\
# tzlocal for automatic timezone detection
&& pip2 install --no-cache-dir --no-binary :all: tzlocal \
\
# Change some platformio settings
&& platformio settings set enable_telemetry No \
&& platformio settings set check_libraries_interval 1000000 \
&& platformio settings set check_platformio_interval 1000000 \
&& platformio settings set check_platforms_interval 1000000 \
\
# Build an empty platformio project to force platformio to install all fw build dependencies
# The return-code will be non-zero since there's nothing to build.
&& (platformio run -d /opt/pio; echo "Done") \
\
# Cleanup
&& rm -fr \
/tmp/* \
/var/{cache,log}/* \
/var/lib/apt/lists/* \
/opt/pio/
COPY platformio.ini /pio/platformio.ini # Build arugments
RUN platformio run -d /pio; rm -rf /pio ARG BUILD_ARCH=amd64
ARG BUILD_DATE
ARG BUILD_REF
ARG BUILD_VERSION
RUN pip install --no-cache-dir git+https://github.com/OttoWinter/esphomeyaml.git@dev#egg=esphomeyaml && \ # Labels
pip install --no-cache-dir pillow tzlocal LABEL \
io.hass.name="esphomeyaml-edge" \
CMD ["esphomeyaml", "/config/esphomeyaml", "dashboard"] io.hass.description="Manage and program ESP8266/ESP32 microcontrollers through YAML configuration files" \
io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \
maintainer="Otto Winter <contact@otto-winter.com>" \
org.label-schema.description="Manage and program ESP8266/ESP32 microcontrollers through YAML configuration files" \
org.label-schema.build-date=${BUILD_DATE} \
org.label-schema.name="esphomeyaml-edge" \
org.label-schema.schema-version="1.0" \
org.label-schema.url="https://esphomelib.com" \
org.label-schema.usage="https://github.com/OttoWinter/esphomeyaml/tree/dev/esphomeyaml-edge/README.md" \
org.label-schema.vcs-ref=${BUILD_REF} \
org.label-schema.vcs-url="https://github.com/OttoWinter/esphomeyaml" \
org.label-schema.vendor="esphomelib"

123
esphomeyaml-edge/README.md Normal file
View File

@ -0,0 +1,123 @@
# Esphomeyaml Hass.io Add-On
[![GitHub Release][releases-shield]][releases]
![Project Stage][project-stage-shield]
[![License][license-shield]](LICENSE.md)
[![GitLab CI][gitlabci-shield]][gitlabci]
![Project Maintenance][maintenance-shield]
[![GitHub Activity][commits-shield]][commits]
[![Discord][discord-shield]][discord]
[![Community Forum][forum-shield]][forum]
[![esphomeyaml logo](logo.png)](https://esphomelib.com/esphomeyaml/index.html)
## About
This add-on allows you to manage and program your ESP8266 and ESP32 based microcontrollers
directly through Hass.io **with no programming experience required**. All you need to do
is write YAML configuration files; the rest (over-the-air updates, compiling) is all
handled by esphomeyaml.
<p align="center">
<img title="esphomeyaml dashboard screenshot" src="images/screenshot.png" width="700px"></img>
</p>
[_View the esphomeyaml documentation here_](https://esphomelib.com/esphomeyaml/index.html)
## Example
With esphomeyaml, you can go from a few lines of YAML straight to a custom-made
firmware. For example, to include a [DHT22][dht22].
temperature and humidity sensor, you just need to include 8 lines of YAML
in your configuration file:
<img title="esphomeyaml DHT configuration example" src="images/dht-example.png" width="500px"></img>
Then just click UPLOAD and the sensor will magically appear in Home Assistant:
<img title="esphomelib Home Assistant MQTT discovery" src="images/temperature-humidity.png" width="600px"></img>
## Installation
To install this Hass.io add-on you need to add the esphomeyaml add-on repository
first:
1. Add our Hass.io add-ons repository to your Hass.io instance. You can do this by navigating to the "Add-on Store" tab in the Hass.io panel and then entering https://github.com/hassio-addons/repository in the "Add new repository by URL" field.
2. Now scroll down and select the "esphomeyaml" add-on.
3. Press install to download the add-on and unpack it on your machine. This can take some time.
4. Optional: If you're using SSL certificates and want to encrypt your communication to this add-on, please enter `true` into the `ssl` field and set the `fullchain` and `certfile` options accordingly.
5. Start the add-on, check the logs of the add-on to see if everything went well.
6. Click "OPEN WEB UI" to open the esphomeyaml dashboard. You will be asked for your Home Assistant credentials - esphomeyaml uses Hass.io's authentication system to log you in.
**NOTE**: Installation on RPis running in 64-bit mode is currently not possible. Please use the 32-bit variant of HassOS instead.
You can view the esphomeyaml docs here: https://esphomelib.com/esphomeyaml/index.html
## Configuration
**Note**: _Remember to restart the add-on when the configuration is changed._
Example add-on configuration:
```json
{
"ssl": true,
"certfile": "fullchain.pem",
"keyfile": "privkey.pem"
}
```
### Option: `ssl`
Enables/Disables encrypted SSL (HTTPS) connections to the web server of this add-on. Set it to `true` to encrypt communications, `false` otherwise. Please note that if you set this to `true` you must also specify a `certfile` and `keyfile`.
### Option: `certfile`
The certificate file to use for SSL.
**Note**: _The file MUST be stored in `/ssl/`, which is the default for Hass.io_
### Option: `keyfile`
The private key file to use for SSL.
**Note**: _The file MUST be stored in `/ssl/`, which is the default for Hass.io_
### Option: `leave_front_door_open`
Adding this option to the add-on configuration allows you to disable
authentication by setting it to `true`.
## Embedding into Home Assistant
It is possible to embed the esphomeyaml dashboard directly into
Home Assistant, allowing you to access your ESP nodes through
the Home Assistant frontend using the `panel_iframe` component.
Example configuration:
```yaml
panel_iframe:
esphomeyaml:
title: esphomeyaml Dashboard
icon: mdi:code-brackets
url: https://addres.to.your.hass.io:6052
```
[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-esphomeyaml.svg
[commits]: https://github.com/hassio-addons/addon-esphomeyaml/commits/master
[discord-shield]: https://img.shields.io/discord/429907082951524364.svg
[dht22]: https://esphomelib.com/esphomeyaml/components/sensor/dht.html
[discord]: https://discord.me/KhAMKrd
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg
[forum]: https://community.home-assistant.io/c/third-party/esphomelib
[gitlabci-shield]: https://gitlab.com/hassio-addons/addon-esphomeyaml/badges/master/pipeline.svg
[gitlabci]: https://gitlab.com/hassio-addons/addon-esphomeyaml/pipelines
[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-esphomeyaml.svg
[maintenance-shield]: https://img.shields.io/maintenance/yes/2018.svg
[project-stage-shield]: https://img.shields.io/badge/project%20stage-stable-green.svg
[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-esphomeyaml.svg
[releases]: https://github.com/hassio-addons/addon-esphomeyaml/releases
[repository]: https://github.com/hassio-addons/repository

View File

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

View File

@ -2,32 +2,41 @@
"name": "esphomeyaml-edge", "name": "esphomeyaml-edge",
"version": "dev", "version": "dev",
"slug": "esphomeyaml-edge", "slug": "esphomeyaml-edge",
"description": "Development build of the esphomeyaml HassIO add-on.", "description": "Development Version! Manage and program ESP8266/ESP32 microcontrollers through YAML configuration files",
"url": "https://esphomelib.com/esphomeyaml/index.html", "url": "https://github.com/OttoWinter/esphomeyaml/tree/dev/esphomeyaml-edge/README.md",
"startup": "application",
"webui": "http://[HOST]:[PORT:6052]", "webui": "http://[HOST]:[PORT:6052]",
"boot": "auto", "startup": "application",
"ports": {
"6052/tcp": 6052,
"6053/tcp": 6053
},
"arch": [ "arch": [
"aarch64", "aarch64",
"amd64", "amd64",
"armhf", "armhf",
"i386" "i386"
], ],
"auto_uart": true, "hassio_api": true,
"auth_api": true,
"services": [
"mqtt:want"
],
"hassio_role": "default",
"homeassistant_api": false,
"host_network": false,
"boot": "auto",
"ports": {
"6052/tcp": 6052
},
"map": [ "map": [
"ssl",
"config:rw" "config:rw"
], ],
"options": { "options": {
"password": "" "ssl": false,
"certfile": "fullchain.pem",
"keyfile": "privkey.pem"
}, },
"schema": { "schema": {
"password": "str?" "ssl": "bool",
}, "certfile": "str",
"environment": { "keyfile": "str",
"ESPHOMEYAML_OTA_HOST_PORT": "6053" "leave_front_door_open": "bool?"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

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

View File

@ -0,0 +1,24 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: esphomeyaml
# Configures NGINX for use with esphomeyaml
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
declare certfile
declare keyfile
mkdir -p /var/log/nginx
# Enable SSL
if hass.config.true 'ssl'; then
rm /etc/nginx/nginx.conf
mv /etc/nginx/nginx-ssl.conf /etc/nginx/nginx.conf
certfile=$(hass.config.get 'certfile')
keyfile=$(hass.config.get 'keyfile')
sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/nginx.conf
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/nginx.conf
fi

View File

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

View File

@ -0,0 +1,46 @@
worker_processes 1;
pid /var/run/nginx.pid;
error_log stderr;
events {
worker_connections 1024;
}
http {
access_log stdout;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream esphomeyaml {
ip_hash;
server 127.0.0.1:80;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name hassio.local;
listen 6052 default_server;
root /dev/null;
location / {
proxy_redirect off;
proxy_pass http://esphomeyaml;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Authorization "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
}
}

View File

@ -0,0 +1,9 @@
#!/usr/bin/execlineb -S0
# ==============================================================================
# Community Hass.io Add-ons: esphomeyaml
# Take down the S6 supervision tree when esphomeyaml fails
# ==============================================================================
if -n { s6-test $# -ne 0 }
if -n { s6-test ${1} -eq 256 }
s6-svscanctl -t /var/run/s6/services

View File

@ -0,0 +1,14 @@
#!/usr/bin/with-contenv bash
# ==============================================================================
# Community Hass.io Add-ons: esphomeyaml
# Runs the esphomeyaml dashboard
# ==============================================================================
# shellcheck disable=SC1091
source /usr/lib/hassio-addons/base.sh
if hass.config.true 'leave_front_door_open'; then
export DISABLE_HA_AUTHENTICATION=true
fi
hass.log.info "Starting esphomeyaml dashboard..."
exec esphomeyaml /config/esphomeyaml dashboard --port 80 --hassio

View File

@ -0,0 +1,9 @@
#!/usr/bin/execlineb -S0
# ==============================================================================
# Community Hass.io Add-ons: esphomeyaml
# Take down the S6 supervision tree when NGINX fails
# ==============================================================================
if -n { s6-test $# -ne 0 }
if -n { s6-test ${1} -eq 256 }
s6-svscanctl -t /var/run/s6/services

View File

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

View File

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

View File

@ -2,21 +2,23 @@ from __future__ import print_function
import argparse import argparse
from collections import OrderedDict from collections import OrderedDict
from datetime import datetime
import logging import logging
import os import os
import random import random
import sys import sys
from datetime import datetime
from esphomeyaml import const, core, core_config, mqtt, wizard, writer, yaml_util, platformio_api from esphomeyaml import const, core_config, mqtt, platformio_api, wizard, writer, yaml_util
from esphomeyaml.config import get_component, iter_components, read_config from esphomeyaml.config import get_component, iter_components, read_config, strip_default_ids
from esphomeyaml.const import CONF_BAUD_RATE, CONF_BUILD_PATH, CONF_DOMAIN, CONF_ESPHOMEYAML, \ from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, \
CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \ CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \
CONF_WIFI, ESP_PLATFORM_ESP8266 CONF_WIFI
from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.core import CORE, EsphomeyamlError
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, \ from esphomeyaml.cpp_generator import Expression, RawStatement, add, statement
_EXPRESSIONS, add, add_job, color, flush_tasks, indent, statement, relative_path from esphomeyaml.helpers import color, indent
from esphomeyaml.util import safe_print, run_external_command from esphomeyaml.storage_json import StorageJSON, storage_path, start_update_check_thread, \
esphomeyaml_storage_path
from esphomeyaml.util import run_external_command, safe_print
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -32,6 +34,7 @@ def get_serial_ports():
continue continue
if "VID:PID" in info: if "VID:PID" in info:
result.append((port, desc)) result.append((port, desc))
result.sort(key=lambda x: x[0])
return result return result
@ -62,7 +65,7 @@ def choose_serial_port(config):
return result[opt][0] return result[opt][0]
def run_miniterm(config, port, escape=False): def run_miniterm(config, port):
import serial import serial
if CONF_LOGGER not in config: if CONF_LOGGER not in config:
_LOGGER.info("Logger is not enabled. Not starting UART logs.") _LOGGER.info("Logger is not enabled. Not starting UART logs.")
@ -83,8 +86,6 @@ def run_miniterm(config, port, escape=False):
line = raw.replace('\r', '').replace('\n', '') line = raw.replace('\r', '').replace('\n', '')
time = datetime.now().time().strftime('[%H:%M:%S]') time = datetime.now().time().strftime('[%H:%M:%S]')
message = time + line message = time + line
if escape:
message = message.replace('\033', '\\033')
safe_print(message) safe_print(message)
backtrace_state = platformio_api.process_stacktrace( backtrace_state = platformio_api.process_stacktrace(
@ -94,43 +95,40 @@ def run_miniterm(config, port, escape=False):
def write_cpp(config): def write_cpp(config):
_LOGGER.info("Generating C++ source...") _LOGGER.info("Generating C++ source...")
add_job(core_config.to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml') CORE.add_job(core_config.to_code, config[CONF_ESPHOMEYAML], domain='esphomeyaml')
for domain in PRE_INITIALIZE: for domain in PRE_INITIALIZE:
if domain == CONF_ESPHOMEYAML or domain not in config: if domain == CONF_ESPHOMEYAML or domain not in config:
continue continue
add_job(get_component(domain).to_code, config[domain], domain=domain) CORE.add_job(get_component(domain).to_code, config[domain], domain=domain)
for domain, component, conf in iter_components(config): for domain, component, conf in iter_components(config):
if domain in PRE_INITIALIZE or not hasattr(component, 'to_code'): if domain in PRE_INITIALIZE or not hasattr(component, 'to_code'):
continue continue
add_job(component.to_code, conf, domain=domain) CORE.add_job(component.to_code, conf, domain=domain)
flush_tasks() CORE.flush_tasks()
add(RawStatement('')) add(RawStatement(''))
add(RawStatement('')) add(RawStatement(''))
all_code = [] all_code = []
for exp in _EXPRESSIONS: for exp in CORE.expressions:
if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]: if not config[CONF_ESPHOMEYAML][CONF_USE_CUSTOM_CODE]:
if isinstance(exp, Expression) and not exp.required: if isinstance(exp, Expression) and not exp.required:
continue continue
if isinstance(exp, AssignmentExpression) and not exp.obj.required:
if not exp.has_side_effects():
continue
exp = exp.rhs
all_code.append(unicode(statement(exp))) all_code.append(unicode(statement(exp)))
build_path = relative_path(config[CONF_ESPHOMEYAML][CONF_BUILD_PATH]) writer.write_platformio_project()
writer.write_platformio_project(config, build_path)
code_s = indent('\n'.join(line.rstrip() for line in all_code)) code_s = indent('\n'.join(line.rstrip() for line in all_code))
cpp_path = os.path.join(build_path, 'src', 'main.cpp') writer.write_cpp(code_s)
writer.write_cpp(code_s, cpp_path)
return 0 return 0
def compile_program(args, config): def compile_program(args, config):
_LOGGER.info("Compiling app...") _LOGGER.info("Compiling app...")
return platformio_api.run_compile(config, args.verbose) thread = start_update_check_thread(esphomeyaml_storage_path(CORE.config_dir))
rc = platformio_api.run_compile(config, args.verbose)
thread.join()
return rc
def get_upload_host(config): def get_upload_host(config):
@ -146,8 +144,7 @@ def get_upload_host(config):
def upload_using_esptool(config, port): def upload_using_esptool(config, port):
import esptool import esptool
build_path = relative_path(config[CONF_ESPHOMEYAML][CONF_BUILD_PATH]) path = os.path.join(CORE.build_path, '.pioenvs', CORE.name, 'firmware.bin')
path = os.path.join(build_path, '.pioenvs', core.NAME, 'firmware.bin')
cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset', cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path] '--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path]
# pylint: disable=protected-access # pylint: disable=protected-access
@ -155,12 +152,10 @@ def upload_using_esptool(config, port):
def upload_program(config, args, port): def upload_program(config, args, port):
build_path = relative_path(config[CONF_ESPHOMEYAML][CONF_BUILD_PATH])
# if upload is to a serial port use platformio, otherwise assume ota # if upload is to a serial port use platformio, otherwise assume ota
serial_port = port.startswith('/') or port.startswith('COM') serial_port = port.startswith('/') or port.startswith('COM')
if port != 'OTA' and serial_port: if port != 'OTA' and serial_port:
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266 and args.use_esptoolpy: if CORE.is_esp8266:
return upload_using_esptool(config, port) return upload_using_esptool(config, port)
return platformio_api.run_upload(config, args.verbose, port) return platformio_api.run_upload(config, args.verbose, port)
@ -178,7 +173,6 @@ def upload_program(config, args, port):
from esphomeyaml.components import ota from esphomeyaml.components import ota
from esphomeyaml import espota2 from esphomeyaml import espota2
bin_file = os.path.join(build_path, '.pioenvs', core.NAME, 'firmware.bin')
if args.host_port is not None: if args.host_port is not None:
host_port = args.host_port host_port = args.host_port
else: else:
@ -188,20 +182,27 @@ def upload_program(config, args, port):
remote_port = ota.get_port(config) remote_port = ota.get_port(config)
password = ota.get_auth(config) password = ota.get_auth(config)
res = espota2.run_ota(host, remote_port, password, bin_file) storage = StorageJSON.load(storage_path())
res = espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
if res == 0: if res == 0:
if storage is not None and storage.use_legacy_ota:
storage.use_legacy_ota = False
storage.save(storage_path())
return res return res
if storage is not None and not storage.use_legacy_ota:
return res
_LOGGER.warn("OTA v2 method failed. Trying with legacy OTA...") _LOGGER.warn("OTA v2 method failed. Trying with legacy OTA...")
return espota2.run_legacy_ota(verbose, host_port, host, remote_port, password, bin_file) return espota2.run_legacy_ota(verbose, host_port, host, remote_port, password,
CORE.firmware_bin)
def show_logs(config, args, port, escape=False): def show_logs(config, args, port):
serial_port = port.startswith('/') or port.startswith('COM') serial_port = port.startswith('/') or port.startswith('COM')
if port != 'OTA' and serial_port: if port != 'OTA' and serial_port:
run_miniterm(config, port, escape=escape) run_miniterm(config, port)
return 0 return 0
return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id, return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id)
escape=escape)
def clean_mqtt(config, args): def clean_mqtt(config, args):
@ -239,26 +240,8 @@ def command_wizard(args):
return wizard.wizard(args.configuration) return wizard.wizard(args.configuration)
def strip_default_ids(config):
value = config
if isinstance(config, list):
value = type(config)()
for x in config:
if isinstance(x, core.ID) and not x.is_manual:
continue
value.append(strip_default_ids(x))
return value
elif isinstance(config, dict):
value = type(config)()
for k, v in config.iteritems():
if isinstance(v, core.ID) and not v.is_manual:
continue
value[k] = strip_default_ids(v)
return value
return value
def command_config(args, config): def command_config(args, config):
_LOGGER.info("Configuration is valid!")
if not args.verbose: if not args.verbose:
config = strip_default_ids(config) config = strip_default_ids(config)
safe_print(yaml_util.dump(config)) safe_print(yaml_util.dump(config))
@ -290,7 +273,7 @@ def command_upload(args, config):
def command_logs(args, config): def command_logs(args, config):
port = args.serial_port or choose_serial_port(config) port = args.serial_port or choose_serial_port(config)
return show_logs(config, args, port, escape=args.escape) return show_logs(config, args, port)
def command_run(args, config): def command_run(args, config):
@ -308,7 +291,7 @@ def command_run(args, config):
_LOGGER.info(u"Successfully uploaded program.") _LOGGER.info(u"Successfully uploaded program.")
if args.no_logs: if args.no_logs:
return 0 return 0
return show_logs(config, args, port, escape=args.escape) return show_logs(config, args, port)
def command_clean_mqtt(args, config): def command_clean_mqtt(args, config):
@ -325,9 +308,8 @@ def command_version(args):
def command_clean(args, config): def command_clean(args, config):
build_path = relative_path(config[CONF_ESPHOMEYAML][CONF_BUILD_PATH])
try: try:
writer.clean_build(build_path) writer.clean_build()
except OSError as err: except OSError as err:
_LOGGER.error("Error deleting build files: %s", err) _LOGGER.error("Error deleting build files: %s", err)
return 1 return 1
@ -403,9 +385,6 @@ def parse_args(argv):
parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. " parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. "
"For example /dev/cu.SLAB_USBtoUART.") "For example /dev/cu.SLAB_USBtoUART.")
parser_upload.add_argument('--host-port', help="Specify the host port.", type=int) 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 ' parser_logs = subparsers.add_parser('logs', help='Validate the configuration '
'and show all MQTT logs.') 'and show all MQTT logs.')
@ -415,8 +394,6 @@ def parse_args(argv):
parser_logs.add_argument('--client-id', help='Manually set the client id.') 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" parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use"
"For example /dev/cu.SLAB_USBtoUART.") "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, ' parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, '
'upload it, and start MQTT logs.') 'upload it, and start MQTT logs.')
@ -429,11 +406,6 @@ def parse_args(argv):
parser_run.add_argument('--username', help='Manually set the MQTT username for logs.') 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('--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('--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 " parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from "
"retain messages.") "retain messages.")
@ -453,39 +425,46 @@ def parse_args(argv):
dashboard = subparsers.add_parser('dashboard', dashboard = subparsers.add_parser('dashboard',
help="Create a simple web server for a dashboard.") help="Create a simple web server for a dashboard.")
dashboard.add_argument("--port", help="The HTTP port to open connections on.", type=int, dashboard.add_argument("--port", help="The HTTP port to open connections on. Defaults to 6052.",
default=6052) type=int, default=6052)
dashboard.add_argument("--password", help="The optional password to require for all requests.", dashboard.add_argument("--password", help="The optional password to require for all requests.",
type=str, default='') type=str, default='')
dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.", dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.",
action='store_true') action='store_true')
dashboard.add_argument("--hassio",
help="Internal flag used to tell esphomeyaml is started as a Hass.io "
"add-on.",
action="store_true")
subparsers.add_parser('hass-config', help="Dump the configuration entries that should be added" subparsers.add_parser('hass-config',
"to Home Assistant when not using MQTT discovery.") help="Dump the configuration entries that should be added "
"to Home Assistant when not using MQTT discovery.")
return parser.parse_args(argv[1:]) return parser.parse_args(argv[1:])
def run_esphomeyaml(argv): def run_esphomeyaml(argv):
args = parse_args(argv) args = parse_args(argv)
setup_log(args.verbose) setup_log(args.verbose)
if args.command in PRE_CONFIG_ACTIONS: if args.command in PRE_CONFIG_ACTIONS:
try: try:
return PRE_CONFIG_ACTIONS[args.command](args) return PRE_CONFIG_ACTIONS[args.command](args)
except ESPHomeYAMLError as e: except EsphomeyamlError as e:
_LOGGER.error(e) _LOGGER.error(e)
return 1 return 1
core.CONFIG_PATH = args.configuration CORE.config_path = args.configuration
config = read_config(core.CONFIG_PATH) config = read_config(args.verbose)
if config is None: if config is None:
return 1 return 1
CORE.config = config
if args.command in POST_CONFIG_ACTIONS: if args.command in POST_CONFIG_ACTIONS:
try: try:
return POST_CONFIG_ACTIONS[args.command](args, config) return POST_CONFIG_ACTIONS[args.command](args, config)
except ESPHomeYAMLError as e: except EsphomeyamlError as e:
_LOGGER.error(e) _LOGGER.error(e)
return 1 return 1
safe_print(u"Unknown command {}".format(args.command)) safe_print(u"Unknown command {}".format(args.command))
@ -495,7 +474,7 @@ def run_esphomeyaml(argv):
def main(): def main():
try: try:
return run_esphomeyaml(sys.argv) return run_esphomeyaml(sys.argv)
except ESPHomeYAMLError as e: except EsphomeyamlError as e:
_LOGGER.error(e) _LOGGER.error(e)
return 1 return 1
except KeyboardInterrupt: except KeyboardInterrupt:

View File

@ -2,16 +2,15 @@ import copy
import voluptuous as vol import voluptuous as vol
from esphomeyaml import core
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \ from esphomeyaml.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, \
CONF_BELOW, CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, \ CONF_BELOW, CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, CONF_ELSE, CONF_ID, CONF_IF, \
CONF_ELSE, CONF_ID, CONF_IF, CONF_LAMBDA, \ CONF_LAMBDA, CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID, CONF_WHILE
CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID from esphomeyaml.core import CORE
from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, TemplateArguments, add, \
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, TemplateArguments, add, add_job, \ get_variable, process_lambda, templatable
esphomelib_ns, float_, process_lambda, templatable, uint32, get_variable, PollingComponent, \ from esphomeyaml.cpp_types import Action, App, Component, PollingComponent, Trigger, \
Action, Component, Trigger esphomelib_ns, float_, uint32
from esphomeyaml.util import ServiceRegistry from esphomeyaml.util import ServiceRegistry
@ -27,41 +26,81 @@ def maybe_simple_id(*validators):
def validate_recursive_condition(value): def validate_recursive_condition(value):
return CONDITIONS_SCHEMA(value) is_list = isinstance(value, list)
value = cv.ensure_list(value)[:]
for i, item in enumerate(value):
path = [i] if is_list else []
item = copy.deepcopy(item)
if not isinstance(item, dict):
raise vol.Invalid(u"Condition must consist of key-value mapping! Got {}".format(item),
path)
key = next((x for x in item if x != CONF_CONDITION_ID), None)
if key is None:
raise vol.Invalid(u"Key missing from action! Got {}".format(item), path)
if key not in CONDITION_REGISTRY:
raise vol.Invalid(u"Unable to find condition with the name '{}', is the "
u"component loaded?".format(key), path + [key])
item.setdefault(CONF_CONDITION_ID, None)
key2 = next((x for x in item if x != CONF_CONDITION_ID and x != key), None)
if key2 is not None:
raise vol.Invalid(u"Cannot have two conditions in one item. Key '{}' overrides '{}'! "
u"Did you forget to indent the block inside the condition?"
u"".format(key, key2), path)
validator = CONDITION_REGISTRY[key][0]
try:
condition = validator(item[key])
except vol.Invalid as err:
err.prepend(path)
raise err
value[i] = {
CONF_CONDITION_ID: cv.declare_variable_id(Condition)(item[CONF_CONDITION_ID]),
key: condition,
}
return value
def validate_recursive_action(value): def validate_recursive_action(value):
is_list = isinstance(value, list)
value = cv.ensure_list(value)[:] value = cv.ensure_list(value)[:]
for i, item in enumerate(value): for i, item in enumerate(value):
path = [i] if is_list else []
item = copy.deepcopy(item) item = copy.deepcopy(item)
if not isinstance(item, dict): if not isinstance(item, dict):
raise vol.Invalid(u"Action must consist of key-value mapping! Got {}".format(item)) raise vol.Invalid(u"Action must consist of key-value mapping! Got {}".format(item),
path)
key = next((x for x in item if x != CONF_ACTION_ID), None) key = next((x for x in item if x != CONF_ACTION_ID), None)
if key is None: if key is None:
raise vol.Invalid(u"Key missing from action! Got {}".format(item)) raise vol.Invalid(u"Key missing from action! Got {}".format(item), path)
if key not in ACTION_REGISTRY: if key not in ACTION_REGISTRY:
raise vol.Invalid(u"Unable to find action with the name '{}', is the component loaded?" raise vol.Invalid(u"Unable to find action with the name '{}', is the component loaded?"
u"".format(key)) u"".format(key), path + [key])
item.setdefault(CONF_ACTION_ID, None) item.setdefault(CONF_ACTION_ID, None)
key2 = next((x for x in item if x != CONF_ACTION_ID and x != key), None) key2 = next((x for x in item if x != CONF_ACTION_ID and x != key), None)
if key2 is not None: if key2 is not None:
raise vol.Invalid(u"Cannot have two actions in one item. Key '{}' overrides '{}'! " raise vol.Invalid(u"Cannot have two actions in one item. Key '{}' overrides '{}'! "
u"Did you forget to indent the action?" u"Did you forget to indent the block inside the action?"
u"".format(key, key2)) u"".format(key, key2), path)
validator = ACTION_REGISTRY[key][0] validator = ACTION_REGISTRY[key][0]
try:
action = validator(item[key])
except vol.Invalid as err:
err.prepend(path)
raise err
value[i] = { value[i] = {
CONF_ACTION_ID: cv.declare_variable_id(Action)(item[CONF_ACTION_ID]), CONF_ACTION_ID: cv.declare_variable_id(Action)(item[CONF_ACTION_ID]),
key: validator(item[key]) key: action,
} }
return value return value
ACTION_REGISTRY = ServiceRegistry() ACTION_REGISTRY = ServiceRegistry()
CONDITION_REGISTRY = ServiceRegistry()
# pylint: disable=invalid-name # pylint: disable=invalid-name
DelayAction = esphomelib_ns.class_('DelayAction', Action, Component) DelayAction = esphomelib_ns.class_('DelayAction', Action, Component)
LambdaAction = esphomelib_ns.class_('LambdaAction', Action) LambdaAction = esphomelib_ns.class_('LambdaAction', Action)
IfAction = esphomelib_ns.class_('IfAction', Action) IfAction = esphomelib_ns.class_('IfAction', Action)
WhileAction = esphomelib_ns.class_('WhileAction', Action)
UpdateComponentAction = esphomelib_ns.class_('UpdateComponentAction', Action) UpdateComponentAction = esphomelib_ns.class_('UpdateComponentAction', Action)
Automation = esphomelib_ns.class_('Automation') Automation = esphomelib_ns.class_('Automation')
@ -71,17 +110,6 @@ OrCondition = esphomelib_ns.class_('OrCondition', Condition)
RangeCondition = esphomelib_ns.class_('RangeCondition', Condition) RangeCondition = esphomelib_ns.class_('RangeCondition', Condition)
LambdaCondition = esphomelib_ns.class_('LambdaCondition', Condition) LambdaCondition = esphomelib_ns.class_('LambdaCondition', Condition)
CONDITIONS_SCHEMA = vol.All(cv.ensure_list, [cv.templatable({
cv.GenerateID(CONF_CONDITION_ID): cv.declare_variable_id(Condition),
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_,
})])
def validate_automation(extra_schema=None, extra_validators=None, single=False): def validate_automation(extra_schema=None, extra_validators=None, single=False):
schema = AUTOMATION_SCHEMA.extend(extra_schema or {}) schema = AUTOMATION_SCHEMA.extend(extra_schema or {})
@ -122,63 +150,63 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
AUTOMATION_SCHEMA = vol.Schema({ AUTOMATION_SCHEMA = vol.Schema({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger),
cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation), cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation),
vol.Optional(CONF_IF): CONDITIONS_SCHEMA, vol.Optional(CONF_IF): validate_recursive_condition,
vol.Required(CONF_THEN): validate_recursive_action, vol.Required(CONF_THEN): validate_recursive_action,
}) })
AND_CONDITION_SCHEMA = validate_recursive_condition
def build_condition(config, arg_type):
template_arg = TemplateArguments(arg_type) @CONDITION_REGISTRY.register(CONF_AND, AND_CONDITION_SCHEMA)
if isinstance(config, core.Lambda): def and_condition_to_code(config, condition_id, arg_type, template_arg):
lambda_ = None for conditions in build_conditions(config, arg_type):
for lambda_ in process_lambda(config, [(arg_type, 'x')]): yield
rhs = AndCondition.new(template_arg, conditions)
type = AndCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
OR_CONDITION_SCHEMA = validate_recursive_condition
@CONDITION_REGISTRY.register(CONF_OR, OR_CONDITION_SCHEMA)
def or_condition_to_code(config, condition_id, arg_type, template_arg):
for conditions in build_conditions(config, arg_type):
yield
rhs = OrCondition.new(template_arg, conditions)
type = OrCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
RANGE_CONDITION_SCHEMA = vol.All(vol.Schema({
vol.Optional(CONF_ABOVE): cv.templatable(cv.float_),
vol.Optional(CONF_BELOW): cv.templatable(cv.float_),
}), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))
@CONDITION_REGISTRY.register(CONF_RANGE, RANGE_CONDITION_SCHEMA)
def range_condition_to_code(config, condition_id, arg_type, template_arg):
for conditions in build_conditions(config, arg_type):
yield
rhs = RangeCondition.new(template_arg, conditions)
type = RangeCondition.template(template_arg)
condition = Pvariable(condition_id, rhs, type=type)
if CONF_ABOVE in config:
for template_ in templatable(config[CONF_ABOVE], arg_type, float_):
yield yield
yield LambdaCondition.new(template_arg, lambda_) condition.set_min(template_)
elif CONF_AND in config: if CONF_BELOW in config:
yield AndCondition.new(template_arg, build_conditions(config[CONF_AND], template_arg)) for template_ in templatable(config[CONF_BELOW], arg_type, float_):
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
yield LambdaCondition.new(template_arg, lambda_) condition.set_max(template_)
elif CONF_RANGE in config: yield condition
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)
DELAY_ACTION_SCHEMA = cv.templatable(cv.positive_time_period_milliseconds) DELAY_ACTION_SCHEMA = cv.templatable(cv.positive_time_period_milliseconds)
@ACTION_REGISTRY.register(CONF_DELAY, DELAY_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_DELAY, DELAY_ACTION_SCHEMA)
def delay_action_to_code(config, action_id, arg_type): def delay_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
rhs = App.register_component(DelayAction.new(template_arg)) rhs = App.register_component(DelayAction.new(template_arg))
type = DelayAction.template(template_arg) type = DelayAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type) action = Pvariable(action_id, rhs, type=type)
@ -196,8 +224,7 @@ IF_ACTION_SCHEMA = vol.All({
@ACTION_REGISTRY.register(CONF_IF, IF_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_IF, IF_ACTION_SCHEMA)
def if_action_to_code(config, action_id, arg_type): def if_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for conditions in build_conditions(config[CONF_CONDITION], arg_type): for conditions in build_conditions(config[CONF_CONDITION], arg_type):
yield None yield None
rhs = IfAction.new(template_arg, conditions) rhs = IfAction.new(template_arg, conditions)
@ -214,12 +241,30 @@ def if_action_to_code(config, action_id, arg_type):
yield action yield action
WHILE_ACTION_SCHEMA = vol.Schema({
vol.Required(CONF_CONDITION): validate_recursive_condition,
vol.Required(CONF_THEN): validate_recursive_action,
})
@ACTION_REGISTRY.register(CONF_WHILE, WHILE_ACTION_SCHEMA)
def while_action_to_code(config, action_id, arg_type, template_arg):
for conditions in build_conditions(config[CONF_CONDITION], arg_type):
yield None
rhs = WhileAction.new(template_arg, conditions)
type = WhileAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type)
for actions in build_actions(config[CONF_THEN], arg_type):
yield None
add(action.add_then(actions))
yield action
LAMBDA_ACTION_SCHEMA = cv.lambda_ LAMBDA_ACTION_SCHEMA = cv.lambda_
@ACTION_REGISTRY.register(CONF_LAMBDA, LAMBDA_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_LAMBDA, LAMBDA_ACTION_SCHEMA)
def lambda_action_to_code(config, action_id, arg_type): def lambda_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for lambda_ in process_lambda(config, [(arg_type, 'x')]): for lambda_ in process_lambda(config, [(arg_type, 'x')]):
yield None yield None
rhs = LambdaAction.new(template_arg, lambda_) rhs = LambdaAction.new(template_arg, lambda_)
@ -227,6 +272,18 @@ def lambda_action_to_code(config, action_id, arg_type):
yield Pvariable(action_id, rhs, type=type) yield Pvariable(action_id, rhs, type=type)
LAMBDA_CONDITION_SCHEMA = cv.lambda_
@CONDITION_REGISTRY.register(CONF_LAMBDA, LAMBDA_CONDITION_SCHEMA)
def lambda_condition_to_code(config, condition_id, arg_type, template_arg):
for lambda_ in process_lambda(config, [(arg_type, 'x')]):
yield
rhs = LambdaCondition.new(template_arg, lambda_)
type = LambdaCondition.template(template_arg)
yield Pvariable(condition_id, rhs, type=type)
CONF_COMPONENT_UPDATE = 'component.update' CONF_COMPONENT_UPDATE = 'component.update'
COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({ COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(PollingComponent), vol.Required(CONF_ID): cv.use_variable_id(PollingComponent),
@ -234,8 +291,7 @@ COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COMPONENT_UPDATE, COMPONENT_UPDATE_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_COMPONENT_UPDATE, COMPONENT_UPDATE_ACTION_SCHEMA)
def component_update_action_to_code(config, action_id, arg_type): def component_update_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = UpdateComponentAction.new(var) rhs = UpdateComponentAction.new(var)
@ -248,7 +304,8 @@ def build_action(full_config, arg_type):
key, config = next((k, v) for k, v in full_config.items() if k in ACTION_REGISTRY) key, config = next((k, v) for k, v in full_config.items() if k in ACTION_REGISTRY)
builder = ACTION_REGISTRY[key][1] builder = ACTION_REGISTRY[key][1]
for result in builder(config, action_id, arg_type): template_arg = TemplateArguments(arg_type)
for result in builder(config, action_id, arg_type, template_arg):
yield None yield None
yield result yield result
@ -263,6 +320,26 @@ def build_actions(config, arg_type):
yield ArrayInitializer(*actions, multiline=False) yield ArrayInitializer(*actions, multiline=False)
def build_condition(full_config, arg_type):
action_id = full_config[CONF_CONDITION_ID]
key, config = next((k, v) for k, v in full_config.items() if k in CONDITION_REGISTRY)
builder = CONDITION_REGISTRY[key][1]
template_arg = TemplateArguments(arg_type)
for result in builder(config, action_id, arg_type, template_arg):
yield None
yield result
def build_conditions(config, arg_type):
conditions = []
for conf in config:
for condition in build_condition(conf, arg_type):
yield None
conditions.append(condition)
yield ArrayInitializer(*conditions, multiline=False)
def build_automation_(trigger, arg_type, config): def build_automation_(trigger, arg_type, config):
rhs = App.make_automation(TemplateArguments(arg_type), trigger) rhs = App.make_automation(TemplateArguments(arg_type), trigger)
type = Automation.template(arg_type) type = Automation.template(arg_type)
@ -280,4 +357,4 @@ def build_automation_(trigger, arg_type, config):
def build_automation(trigger, arg_type, config): def build_automation(trigger, arg_type, config):
add_job(build_automation_, trigger, arg_type, config) CORE.add_job(build_automation_, trigger, arg_type, config)

View File

@ -1,27 +1,27 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.components import sensor, i2c from esphomeyaml.components import i2c, sensor
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADDRESS, CONF_ID from esphomeyaml.const import CONF_ADDRESS, CONF_ID
from esphomeyaml.helpers import App, Pvariable, setup_component, Component from esphomeyaml.cpp_generator import Pvariable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
MULTI_CONF = True
ADS1115Component = sensor.sensor_ns.class_('ADS1115Component', Component, i2c.I2CDevice) ADS1115Component = sensor.sensor_ns.class_('ADS1115Component', Component, i2c.I2CDevice)
ADS1115_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(ADS1115Component), cv.GenerateID(): cv.declare_variable_id(ADS1115Component),
vol.Required(CONF_ADDRESS): cv.i2c_address, vol.Required(CONF_ADDRESS): cv.i2c_address,
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: rhs = App.make_ads1115_component(config[CONF_ADDRESS])
rhs = App.make_ads1115_component(conf[CONF_ADDRESS]) var = Pvariable(config[CONF_ID], rhs)
var = Pvariable(conf[CONF_ID], rhs) setup_component(var, config)
setup_component(var, conf)
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR' BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'

View File

@ -1,16 +1,19 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml import automation, core from esphomeyaml import automation, core
from esphomeyaml.automation import maybe_simple_id, CONDITION_REGISTRY, Condition
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.components.mqtt import setup_mqtt_component
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_DELAYED_OFF, CONF_DELAYED_ON, CONF_DEVICE_CLASS, CONF_FILTERS, \ from esphomeyaml.const import CONF_DELAYED_OFF, CONF_DELAYED_ON, CONF_DEVICE_CLASS, CONF_FILTERS, \
CONF_HEARTBEAT, CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERT, CONF_INVERTED, \ CONF_HEARTBEAT, CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERT, CONF_INVERTED, \
CONF_LAMBDA, CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, \ CONF_LAMBDA, CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, \
CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_STATE, \ CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_STATE, \
CONF_TIMING, CONF_TRIGGER_ID CONF_TIMING, CONF_TRIGGER_ID
from esphomeyaml.helpers import App, ArrayInitializer, NoArg, Pvariable, StructInitializer, add, \ from esphomeyaml.core import CORE
add_job, bool_, esphomelib_ns, process_lambda, setup_mqtt_component, Nameable, Trigger, \ from esphomeyaml.cpp_generator import process_lambda, ArrayInitializer, add, Pvariable, \
Component StructInitializer, get_variable
from esphomeyaml.cpp_types import esphomelib_ns, Nameable, Trigger, NoArg, Component, App, bool_
DEVICE_CLASSES = [ DEVICE_CLASSES = [
'', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas', '', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
@ -25,6 +28,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
binary_sensor_ns = esphomelib_ns.namespace('binary_sensor') binary_sensor_ns = esphomelib_ns.namespace('binary_sensor')
BinarySensor = binary_sensor_ns.class_('BinarySensor', Nameable) BinarySensor = binary_sensor_ns.class_('BinarySensor', Nameable)
BinarySensorPtr = BinarySensor.operator('ptr')
MQTTBinarySensorComponent = binary_sensor_ns.class_('MQTTBinarySensorComponent', mqtt.MQTTComponent) MQTTBinarySensorComponent = binary_sensor_ns.class_('MQTTBinarySensorComponent', mqtt.MQTTComponent)
# Triggers # Triggers
@ -35,6 +39,9 @@ DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', Trigger.templ
MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', Trigger.template(NoArg), Component) MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', Trigger.template(NoArg), Component)
MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent') MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent')
# Condition
BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition)
# Filters # Filters
Filter = binary_sensor_ns.class_('Filter') Filter = binary_sensor_ns.class_('Filter')
DelayedOnFilter = binary_sensor_ns.class_('DelayedOnFilter', Filter, Component) DelayedOnFilter = binary_sensor_ns.class_('DelayedOnFilter', Filter, Component)
@ -269,14 +276,14 @@ def setup_binary_sensor(binary_sensor_obj, mqtt_obj, config):
has_side_effects=False) has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj,
has_side_effects=False) has_side_effects=False)
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config) CORE.add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
def register_binary_sensor(var, config): def register_binary_sensor(var, config):
binary_sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True) binary_sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
rhs = App.register_binary_sensor(binary_sensor_var) rhs = App.register_binary_sensor(binary_sensor_var)
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True) mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config) CORE.add_job(setup_binary_sensor_core_, binary_sensor_var, mqtt_var, config)
def core_to_hass_config(data, config): def core_to_hass_config(data, config):
@ -290,3 +297,33 @@ def core_to_hass_config(data, config):
BUILD_FLAGS = '-DUSE_BINARY_SENSOR' BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
CONF_BINARY_SENSOR_IS_ON = 'binary_sensor.is_on'
BINARY_SENSOR_IS_ON_CONDITION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinarySensor),
})
@CONDITION_REGISTRY.register(CONF_BINARY_SENSOR_IS_ON, BINARY_SENSOR_IS_ON_CONDITION_SCHEMA)
def binary_sensor_is_on_to_code(config, condition_id, arg_type, template_arg):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_binary_sensor_is_on_condition(template_arg)
type = BinarySensorCondition.template(arg_type)
yield Pvariable(condition_id, rhs, type=type)
CONF_BINARY_SENSOR_IS_OFF = 'binary_sensor.is_off'
BINARY_SENSOR_IS_OFF_CONDITION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(BinarySensor),
})
@CONDITION_REGISTRY.register(CONF_BINARY_SENSOR_IS_OFF, BINARY_SENSOR_IS_OFF_CONDITION_SCHEMA)
def binary_sensor_is_off_to_code(config, condition_id, arg_type, template_arg):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_binary_sensor_is_off_condition(template_arg)
type = BinarySensorCondition.template(arg_type)
yield Pvariable(condition_id, rhs, type=type)

View File

@ -0,0 +1,37 @@
import voluptuous as vol
from esphomeyaml.components import binary_sensor
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA
from esphomeyaml.cpp_generator import process_lambda, variable
from esphomeyaml.cpp_types import std_vector
CustomBinarySensorConstructor = binary_sensor.binary_sensor_ns.class_(
'CustomBinarySensorConstructor')
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomBinarySensorConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_BINARY_SENSORS):
vol.All(cv.ensure_list, [binary_sensor.BINARY_SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(binary_sensor.BinarySensor),
})]),
})
def to_code(config):
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=std_vector.template(binary_sensor.BinarySensorPtr)):
yield
rhs = CustomBinarySensorConstructor(template_)
custom = variable(config[CONF_ID], rhs)
for i, sens in enumerate(config[CONF_BINARY_SENSORS]):
binary_sensor.register_binary_sensor(custom.get_binary_sensor(i), sens)
BUILD_FLAGS = '-DUSE_CUSTOM_BINARY_SENSOR'
def to_hass_config(data, config):
return [binary_sensor.core_to_hass_config(data, sens) for sens in config[CONF_BINARY_SENSORS]]

View File

@ -5,7 +5,8 @@ from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLE
make_address_array make_address_array
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME
from esphomeyaml.helpers import esphomelib_ns, get_variable from esphomeyaml.cpp_generator import get_variable
from esphomeyaml.cpp_types import esphomelib_ns
DEPENDENCIES = ['esp32_ble_tracker'] DEPENDENCIES = ['esp32_ble_tracker']
ESP32BLEPresenceDevice = esphomelib_ns.class_('ESP32BLEPresenceDevice', binary_sensor.BinarySensor) ESP32BLEPresenceDevice = esphomelib_ns.class_('ESP32BLEPresenceDevice', binary_sensor.BinarySensor)

View File

@ -4,7 +4,8 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import binary_sensor from esphomeyaml.components import binary_sensor
from esphomeyaml.components.esp32_touch import ESP32TouchComponent from esphomeyaml.components.esp32_touch import ESP32TouchComponent
from esphomeyaml.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32 from esphomeyaml.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32
from esphomeyaml.helpers import get_variable, global_ns from esphomeyaml.cpp_generator import get_variable
from esphomeyaml.cpp_types import global_ns
from esphomeyaml.pins import validate_gpio_pin from esphomeyaml.pins import validate_gpio_pin
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]

View File

@ -4,8 +4,9 @@ import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import binary_sensor from esphomeyaml.components import binary_sensor
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN
from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application, \ from esphomeyaml.cpp_generator import variable
setup_component, Component from esphomeyaml.cpp_helpers import gpio_input_pin_expression, setup_component
from esphomeyaml.cpp_types import Application, Component, App
MakeGPIOBinarySensor = Application.struct('MakeGPIOBinarySensor') MakeGPIOBinarySensor = Application.struct('MakeGPIOBinarySensor')
GPIOBinarySensorComponent = binary_sensor.binary_sensor_ns.class_('GPIOBinarySensorComponent', GPIOBinarySensorComponent = binary_sensor.binary_sensor_ns.class_('GPIOBinarySensorComponent',

View File

@ -4,7 +4,7 @@ from esphomeyaml.components import binary_sensor, display
from esphomeyaml.components.display.nextion import Nextion from esphomeyaml.components.display.nextion import Nextion
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_COMPONENT_ID, CONF_NAME, CONF_PAGE_ID from esphomeyaml.const import CONF_COMPONENT_ID, CONF_NAME, CONF_PAGE_ID
from esphomeyaml.helpers import get_variable from esphomeyaml.cpp_generator import get_variable
DEPENDENCIES = ['display'] DEPENDENCIES = ['display']
@ -22,7 +22,6 @@ PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend
def to_code(config): def to_code(config):
hub = None
for hub in get_variable(config[CONF_NEXTION_ID]): for hub in get_variable(config[CONF_NEXTION_ID]):
yield yield
rhs = hub.make_touch_component(config[CONF_NAME], config[CONF_PAGE_ID], rhs = hub.make_touch_component(config[CONF_NAME], config[CONF_PAGE_ID],

View File

@ -5,7 +5,7 @@ from esphomeyaml.components import binary_sensor
from esphomeyaml.components.pn532 import PN532Component from esphomeyaml.components.pn532 import PN532Component
from esphomeyaml.const import CONF_NAME, CONF_UID from esphomeyaml.const import CONF_NAME, CONF_UID
from esphomeyaml.core import HexInt from esphomeyaml.core import HexInt
from esphomeyaml.helpers import ArrayInitializer, get_variable from esphomeyaml.cpp_generator import get_variable, ArrayInitializer
DEPENDENCIES = ['pn532'] DEPENDENCIES = ['pn532']

View File

@ -3,7 +3,7 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import binary_sensor, rdm6300 from esphomeyaml.components import binary_sensor, rdm6300
from esphomeyaml.const import CONF_NAME, CONF_UID from esphomeyaml.const import CONF_NAME, CONF_UID
from esphomeyaml.helpers import get_variable from esphomeyaml.cpp_generator import get_variable
DEPENDENCIES = ['rdm6300'] DEPENDENCIES = ['rdm6300']

View File

@ -11,7 +11,7 @@ from esphomeyaml.const import CONF_ADDRESS, CONF_CHANNEL, CONF_CODE, CONF_COMMAN
CONF_PANASONIC, CONF_PROTOCOL, CONF_RAW, CONF_RC_SWITCH_RAW, CONF_RC_SWITCH_TYPE_A, \ CONF_PANASONIC, CONF_PROTOCOL, CONF_RAW, CONF_RC_SWITCH_RAW, CONF_RC_SWITCH_TYPE_A, \
CONF_RC_SWITCH_TYPE_B, CONF_RC_SWITCH_TYPE_C, CONF_RC_SWITCH_TYPE_D, CONF_SAMSUNG, CONF_SONY, \ CONF_RC_SWITCH_TYPE_B, CONF_RC_SWITCH_TYPE_C, CONF_RC_SWITCH_TYPE_D, CONF_SAMSUNG, CONF_SONY, \
CONF_STATE CONF_STATE
from esphomeyaml.helpers import ArrayInitializer, Pvariable, get_variable from esphomeyaml.cpp_generator import ArrayInitializer, get_variable, Pvariable
DEPENDENCIES = ['remote_receiver'] DEPENDENCIES = ['remote_receiver']

View File

@ -1,7 +1,9 @@
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import binary_sensor from esphomeyaml.components import binary_sensor
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME
from esphomeyaml.helpers import App, Application, variable, setup_component, Component from esphomeyaml.cpp_generator import variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, Component, App
DEPENDENCIES = ['mqtt'] DEPENDENCIES = ['mqtt']

View File

@ -3,8 +3,9 @@ import voluptuous as vol
from esphomeyaml.components import binary_sensor from esphomeyaml.components import binary_sensor
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME
from esphomeyaml.helpers import App, Application, add, bool_, optional, process_lambda, variable, \ from esphomeyaml.cpp_generator import variable, process_lambda, add
setup_component, Component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, Component, App, optional, bool_
MakeTemplateBinarySensor = Application.struct('MakeTemplateBinarySensor') MakeTemplateBinarySensor = Application.struct('MakeTemplateBinarySensor')
TemplateBinarySensor = binary_sensor.binary_sensor_ns.class_('TemplateBinarySensor', TemplateBinarySensor = binary_sensor.binary_sensor_ns.class_('TemplateBinarySensor',

View File

@ -1,11 +1,12 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.automation import maybe_simple_id, ACTION_REGISTRY from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.components.mqtt import setup_mqtt_component
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_INTERNAL from esphomeyaml.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID
from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component, add, \ from esphomeyaml.cpp_generator import Pvariable, add, get_variable
TemplateArguments, get_variable, Action, Nameable from esphomeyaml.cpp_types import Action, Nameable, esphomelib_ns
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -54,8 +55,7 @@ COVER_OPEN_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_OPEN, COVER_OPEN_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_COVER_OPEN, COVER_OPEN_ACTION_SCHEMA)
def cover_open_to_code(config, action_id, arg_type): def cover_open_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_open_action(template_arg) rhs = var.make_open_action(template_arg)
@ -70,8 +70,7 @@ COVER_CLOSE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_CLOSE, COVER_CLOSE_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_COVER_CLOSE, COVER_CLOSE_ACTION_SCHEMA)
def cover_close_to_code(config, action_id, arg_type): def cover_close_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_close_action(template_arg) rhs = var.make_close_action(template_arg)
@ -86,8 +85,7 @@ COVER_STOP_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_COVER_STOP, COVER_STOP_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_COVER_STOP, COVER_STOP_ACTION_SCHEMA)
def cover_stop_to_code(config, action_id, arg_type): def cover_stop_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_stop_action(template_arg) rhs = var.make_stop_action(template_arg)

View File

@ -5,8 +5,9 @@ from esphomeyaml import automation
from esphomeyaml.components import cover from esphomeyaml.components import cover
from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \ from esphomeyaml.const import CONF_CLOSE_ACTION, CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, \
CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC CONF_OPEN_ACTION, CONF_STOP_ACTION, CONF_OPTIMISTIC
from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, variable, optional, \ from esphomeyaml.cpp_generator import variable, process_lambda, add
setup_component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, App, optional, NoArg
MakeTemplateCover = Application.struct('MakeTemplateCover') MakeTemplateCover = Application.struct('MakeTemplateCover')
TemplateCover = cover.cover_ns.class_('TemplateCover', cover.Cover) TemplateCover = cover.cover_ns.class_('TemplateCover', cover.Cover)

View File

@ -0,0 +1,32 @@
import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_COMPONENTS
from esphomeyaml.cpp_generator import process_lambda, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Component, ComponentPtr, esphomelib_ns, std_vector
CustomComponentConstructor = esphomelib_ns.class_('CustomComponentConstructor')
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_COMPONENTS): vol.All(cv.ensure_list, [vol.Schema({
cv.GenerateID(): cv.declare_variable_id(Component)
}).extend(cv.COMPONENT_SCHEMA.schema)]),
})
def to_code(config):
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=std_vector.template(ComponentPtr)):
yield
rhs = CustomComponentConstructor(template_)
custom = variable(config[CONF_ID], rhs)
for i, comp in enumerate(config.get(CONF_COMPONENTS, [])):
setup_component(custom.get_component(i), comp)
BUILD_FLAGS = '-DUSE_CUSTOM_COMPONENT'

View File

@ -1,25 +1,27 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_PIN, CONF_UPDATE_INTERVAL from esphomeyaml.const import CONF_ID, CONF_PIN, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Pvariable, setup_component, PollingComponent from esphomeyaml.cpp_generator import Pvariable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, PollingComponent
DallasComponent = sensor.sensor_ns.class_('DallasComponent', PollingComponent) DallasComponent = sensor.sensor_ns.class_('DallasComponent', PollingComponent)
MULTI_CONF = True
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(DallasComponent), cv.GenerateID(): cv.declare_variable_id(DallasComponent),
vol.Required(CONF_PIN): pins.input_output_pin, vol.Required(CONF_PIN): pins.input_pullup_pin,
vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval,
}).extend(cv.COMPONENT_SCHEMA.schema)]) }).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config): def to_code(config):
for conf in config: rhs = App.make_dallas_component(config[CONF_PIN], config.get(CONF_UPDATE_INTERVAL))
rhs = App.make_dallas_component(conf[CONF_PIN], conf.get(CONF_UPDATE_INTERVAL)) var = Pvariable(config[CONF_ID], rhs)
var = Pvariable(conf[CONF_ID], rhs) setup_component(var, config)
setup_component(var, conf)
BUILD_FLAGS = '-DUSE_DALLAS_SENSOR' BUILD_FLAGS = '-DUSE_DALLAS_SENSOR'

View File

@ -1,6 +1,7 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.helpers import App, add from esphomeyaml.cpp_generator import add
from esphomeyaml.cpp_types import App
DEPENDENCIES = ['logger'] DEPENDENCIES = ['logger']

View File

@ -2,11 +2,11 @@ import voluptuous as vol
from esphomeyaml import config_validation as cv, pins from esphomeyaml import config_validation as cv, pins
from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_RUN_CYCLES, CONF_RUN_DURATION, \ from esphomeyaml.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_CYCLES, \
CONF_SLEEP_DURATION, CONF_WAKEUP_PIN, CONF_MODE, CONF_PINS CONF_RUN_DURATION, CONF_SLEEP_DURATION, CONF_WAKEUP_PIN
from esphomeyaml.helpers import Action, App, Component, Pvariable, TemplateArguments, add, \ from esphomeyaml.cpp_generator import Pvariable, StructInitializer, add, get_variable
esphomelib_ns, get_variable, gpio_input_pin_expression, setup_component, global_ns, \ from esphomeyaml.cpp_helpers import gpio_input_pin_expression, setup_component
StructInitializer from esphomeyaml.cpp_types import Action, App, Component, esphomelib_ns, global_ns
def validate_pin_number(value): def validate_pin_number(value):
@ -95,8 +95,7 @@ DEEP_SLEEP_ENTER_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DEEP_SLEEP_ENTER, DEEP_SLEEP_ENTER_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_DEEP_SLEEP_ENTER, DEEP_SLEEP_ENTER_ACTION_SCHEMA)
def deep_sleep_enter_to_code(config, action_id, arg_type): def deep_sleep_enter_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_enter_deep_sleep_action(template_arg) rhs = var.make_enter_deep_sleep_action(template_arg)
@ -111,8 +110,7 @@ DEEP_SLEEP_PREVENT_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_DEEP_SLEEP_PREVENT, DEEP_SLEEP_PREVENT_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_DEEP_SLEEP_PREVENT, DEEP_SLEEP_PREVENT_ACTION_SCHEMA)
def deep_sleep_prevent_to_code(config, action_id, arg_type): def deep_sleep_prevent_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_prevent_deep_sleep_action(template_arg) rhs = var.make_prevent_deep_sleep_action(template_arg)

View File

@ -3,7 +3,9 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_LAMBDA, CONF_ROTATION, CONF_UPDATE_INTERVAL from esphomeyaml.const import CONF_LAMBDA, CONF_ROTATION, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import add, add_job, esphomelib_ns from esphomeyaml.core import CORE
from esphomeyaml.cpp_generator import add
from esphomeyaml.cpp_types import esphomelib_ns
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -50,7 +52,7 @@ def setup_display_core_(display_var, config):
def setup_display(display_var, config): def setup_display(display_var, config):
add_job(setup_display_core_, display_var, config) CORE.add_job(setup_display_core_, display_var, config)
BUILD_FLAGS = '-DUSE_DISPLAY' BUILD_FLAGS = '-DUSE_DISPLAY'

View File

@ -1,12 +1,13 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import display from esphomeyaml.components import display
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_DATA_PINS, CONF_DIMENSIONS, CONF_ENABLE_PIN, CONF_ID, \ from esphomeyaml.const import CONF_DATA_PINS, CONF_DIMENSIONS, CONF_ENABLE_PIN, CONF_ID, \
CONF_LAMBDA, CONF_RS_PIN, CONF_RW_PIN CONF_LAMBDA, CONF_RS_PIN, CONF_RW_PIN
from esphomeyaml.helpers import App, Pvariable, add, gpio_output_pin_expression, process_lambda, \ from esphomeyaml.cpp_generator import Pvariable, add, process_lambda
setup_component, PollingComponent from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, PollingComponent
LCDDisplay = display.display_ns.class_('LCDDisplay', PollingComponent) LCDDisplay = display.display_ns.class_('LCDDisplay', PollingComponent)
LCDDisplayRef = LCDDisplay.operator('ref') LCDDisplayRef = LCDDisplay.operator('ref')

View File

@ -1,11 +1,13 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import display, i2c from esphomeyaml.components import display, i2c
from esphomeyaml.components.display.lcd_gpio import LCDDisplayRef, validate_lcd_dimensions, \ from esphomeyaml.components.display.lcd_gpio import LCDDisplay, LCDDisplayRef, \
LCDDisplay validate_lcd_dimensions
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADDRESS, CONF_DIMENSIONS, CONF_ID, CONF_LAMBDA from esphomeyaml.const import CONF_ADDRESS, CONF_DIMENSIONS, CONF_ID, CONF_LAMBDA
from esphomeyaml.helpers import App, Pvariable, add, process_lambda, setup_component from esphomeyaml.cpp_generator import Pvariable, add, process_lambda
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -1,13 +1,14 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import display, spi from esphomeyaml.components import display, spi
from esphomeyaml.components.spi import SPIComponent from esphomeyaml.components.spi import SPIComponent
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_INTENSITY, CONF_LAMBDA, CONF_NUM_CHIPS, \ from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_INTENSITY, CONF_LAMBDA, CONF_NUM_CHIPS, \
CONF_SPI_ID CONF_SPI_ID
from esphomeyaml.helpers import App, Pvariable, add, get_variable, gpio_output_pin_expression, \ from esphomeyaml.cpp_generator import Pvariable, add, get_variable, process_lambda
process_lambda, setup_component, PollingComponent from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, PollingComponent
DEPENDENCIES = ['spi'] DEPENDENCIES = ['spi']

View File

@ -2,9 +2,9 @@ from esphomeyaml.components import display, uart
from esphomeyaml.components.uart import UARTComponent from esphomeyaml.components.uart import UARTComponent
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_UART_ID from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_UART_ID
from esphomeyaml.helpers import App, PollingComponent, Pvariable, add, get_variable, \ from esphomeyaml.cpp_generator import Pvariable, add, get_variable, process_lambda
process_lambda, \ from esphomeyaml.cpp_helpers import setup_component
setup_component from esphomeyaml.cpp_types import App, PollingComponent
DEPENDENCIES = ['uart'] DEPENDENCIES = ['uart']

View File

@ -1,13 +1,14 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import display from esphomeyaml.components import display
from esphomeyaml.components.display import ssd1306_spi from esphomeyaml.components.display import ssd1306_spi
from esphomeyaml.const import CONF_ADDRESS, CONF_EXTERNAL_VCC, CONF_ID, \ import esphomeyaml.config_validation as cv
CONF_MODEL, CONF_RESET_PIN, CONF_LAMBDA from esphomeyaml.const import CONF_ADDRESS, CONF_EXTERNAL_VCC, CONF_ID, CONF_LAMBDA, CONF_MODEL, \
from esphomeyaml.helpers import App, Pvariable, add, \ CONF_RESET_PIN
gpio_output_pin_expression, process_lambda, setup_component from esphomeyaml.cpp_generator import Pvariable, add, process_lambda
from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -1,14 +1,14 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import display, spi from esphomeyaml.components import display, spi
from esphomeyaml.components.spi import SPIComponent from esphomeyaml.components.spi import SPIComponent
from esphomeyaml.const import CONF_CS_PIN, CONF_DC_PIN, CONF_EXTERNAL_VCC, \ import esphomeyaml.config_validation as cv
CONF_ID, CONF_MODEL, \ from esphomeyaml.const import CONF_CS_PIN, CONF_DC_PIN, CONF_EXTERNAL_VCC, CONF_ID, CONF_LAMBDA, \
CONF_RESET_PIN, CONF_SPI_ID, CONF_LAMBDA CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID
from esphomeyaml.helpers import App, Pvariable, add, get_variable, \ from esphomeyaml.cpp_generator import Pvariable, add, get_variable, process_lambda
gpio_output_pin_expression, process_lambda, setup_component, PollingComponent from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, PollingComponent
DEPENDENCIES = ['spi'] DEPENDENCIES = ['spi']

View File

@ -6,8 +6,10 @@ from esphomeyaml.components import display, spi
from esphomeyaml.components.spi import SPIComponent from esphomeyaml.components.spi import SPIComponent
from esphomeyaml.const import CONF_BUSY_PIN, CONF_CS_PIN, CONF_DC_PIN, CONF_FULL_UPDATE_EVERY, \ from esphomeyaml.const import CONF_BUSY_PIN, CONF_CS_PIN, CONF_DC_PIN, CONF_FULL_UPDATE_EVERY, \
CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN, CONF_SPI_ID
from esphomeyaml.helpers import App, Pvariable, add, get_variable, gpio_input_pin_expression, \ from esphomeyaml.cpp_generator import get_variable, Pvariable, process_lambda, add
gpio_output_pin_expression, process_lambda, setup_component, PollingComponent from esphomeyaml.cpp_helpers import gpio_output_pin_expression, gpio_input_pin_expression, \
setup_component
from esphomeyaml.cpp_types import PollingComponent, App
DEPENDENCIES = ['spi'] DEPENDENCIES = ['spi']

View File

@ -2,8 +2,9 @@ import voluptuous as vol
from esphomeyaml import config_validation as cv from esphomeyaml import config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, CONF_TYPE, CONF_UUID, ESP_PLATFORM_ESP32 from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, CONF_TYPE, CONF_UUID, ESP_PLATFORM_ESP32
from esphomeyaml.helpers import App, ArrayInitializer, Component, Pvariable, RawExpression, add, \ from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, RawExpression, add
esphomelib_ns, setup_component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]

View File

@ -4,8 +4,9 @@ from esphomeyaml import config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32 from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
from esphomeyaml.core import HexInt from esphomeyaml.core import HexInt
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, ArrayInitializer, \ from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, add
setup_component, Component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]

View File

@ -2,11 +2,13 @@ import voluptuous as vol
from esphomeyaml import config_validation as cv from esphomeyaml import config_validation as cv
from esphomeyaml.components import binary_sensor from esphomeyaml.components import binary_sensor
from esphomeyaml.const import CONF_ID, CONF_SETUP_MODE, CONF_IIR_FILTER, \ from esphomeyaml.const import CONF_HIGH_VOLTAGE_REFERENCE, CONF_ID, CONF_IIR_FILTER, \
CONF_SLEEP_DURATION, CONF_MEASUREMENT_DURATION, CONF_LOW_VOLTAGE_REFERENCE, \ CONF_LOW_VOLTAGE_REFERENCE, CONF_MEASUREMENT_DURATION, CONF_SETUP_MODE, CONF_SLEEP_DURATION, \
CONF_HIGH_VOLTAGE_REFERENCE, CONF_VOLTAGE_ATTENUATION, ESP_PLATFORM_ESP32 CONF_VOLTAGE_ATTENUATION, ESP_PLATFORM_ESP32
from esphomeyaml.core import TimePeriod from esphomeyaml.core import TimePeriod
from esphomeyaml.helpers import App, Pvariable, add, global_ns, setup_component, Component from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component, global_ns
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
@ -19,6 +21,7 @@ def validate_voltage(values):
if not value.endswith('V'): if not value.endswith('V'):
value += 'V' value += 'V'
return cv.one_of(*values)(value) return cv.one_of(*values)(value)
return validator return validator

View File

@ -1,13 +1,14 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.automation import maybe_simple_id, ACTION_REGISTRY from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.components.mqtt import setup_mqtt_component
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_OSCILLATION_COMMAND_TOPIC, \ from esphomeyaml.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_NAME, CONF_OSCILLATING, \
CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_INTERNAL, \ CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_OUTPUT, CONF_OSCILLATION_STATE_TOPIC, \
CONF_SPEED, CONF_OSCILLATING, CONF_OSCILLATION_OUTPUT, CONF_NAME CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC
from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component, \ from esphomeyaml.cpp_generator import add, Pvariable, get_variable, templatable
TemplateArguments, get_variable, templatable, bool_, Action, Nameable, Component from esphomeyaml.cpp_types import Application, Component, Nameable, esphomelib_ns, Action, bool_
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -38,7 +39,6 @@ FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema) FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema)
FAN_SPEEDS = { FAN_SPEEDS = {
'OFF': FAN_SPEED_OFF, 'OFF': FAN_SPEED_OFF,
'LOW': FAN_SPEED_LOW, 'LOW': FAN_SPEED_LOW,
@ -70,7 +70,6 @@ def setup_fan(fan_obj, mqtt_obj, config):
BUILD_FLAGS = '-DUSE_FAN' BUILD_FLAGS = '-DUSE_FAN'
CONF_FAN_TOGGLE = 'fan.toggle' CONF_FAN_TOGGLE = 'fan.toggle'
FAN_TOGGLE_ACTION_SCHEMA = maybe_simple_id({ FAN_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(FanState), vol.Required(CONF_ID): cv.use_variable_id(FanState),
@ -78,8 +77,7 @@ FAN_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TOGGLE, FAN_TOGGLE_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_FAN_TOGGLE, FAN_TOGGLE_ACTION_SCHEMA)
def fan_toggle_to_code(config, action_id, arg_type): def fan_toggle_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_toggle_action(template_arg) rhs = var.make_toggle_action(template_arg)
@ -94,8 +92,7 @@ FAN_TURN_OFF_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TURN_OFF, FAN_TURN_OFF_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_FAN_TURN_OFF, FAN_TURN_OFF_ACTION_SCHEMA)
def fan_turn_off_to_code(config, action_id, arg_type): def fan_turn_off_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_off_action(template_arg) rhs = var.make_turn_off_action(template_arg)
@ -112,8 +109,7 @@ FAN_TURN_ON_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_FAN_TURN_ON, FAN_TURN_ON_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_FAN_TURN_ON, FAN_TURN_ON_ACTION_SCHEMA)
def fan_turn_on_to_code(config, action_id, arg_type): def fan_turn_on_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_on_action(template_arg) rhs = var.make_turn_on_action(template_arg)

View File

@ -3,7 +3,9 @@ import voluptuous as vol
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import fan, output from esphomeyaml.components import fan, output
from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT
from esphomeyaml.helpers import App, add, get_variable, variable, setup_component from esphomeyaml.cpp_generator import get_variable, variable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),

View File

@ -5,7 +5,8 @@ from esphomeyaml.components import fan, mqtt, output
from esphomeyaml.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CONF_NAME, \ 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_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_SPEED, CONF_SPEED_COMMAND_TOPIC, \
CONF_SPEED_STATE_TOPIC CONF_SPEED_STATE_TOPIC
from esphomeyaml.helpers import App, add, get_variable, variable from esphomeyaml.cpp_generator import get_variable, variable, add
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan),

View File

@ -1,15 +1,16 @@
# coding=utf-8 # coding=utf-8
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import core from esphomeyaml import core
from esphomeyaml.components import display from esphomeyaml.components import display
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE from esphomeyaml.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE
from esphomeyaml.core import HexInt from esphomeyaml.core import CORE, HexInt
from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \ from esphomeyaml.cpp_generator import ArrayInitializer, MockObj, Pvariable, RawExpression, add
relative_path from esphomeyaml.cpp_types import App
DEPENDENCIES = ['display'] DEPENDENCIES = ['display']
MULTI_CONF = True
Font = display.display_ns.class_('Font') Font = display.display_ns.class_('Font')
Glyph = display.display_ns.class_('Glyph') Glyph = display.display_ns.class_('Glyph')
@ -76,46 +77,45 @@ FONT_SCHEMA = vol.Schema({
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None), cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None),
}) })
CONFIG_SCHEMA = vol.All(validate_pillow_installed, cv.ensure_list, [FONT_SCHEMA]) CONFIG_SCHEMA = vol.All(validate_pillow_installed, FONT_SCHEMA)
def to_code(config): def to_code(config):
from PIL import ImageFont from PIL import ImageFont
for conf in config: path = CORE.relative_path(config[CONF_FILE])
path = relative_path(conf[CONF_FILE]) try:
try: font = ImageFont.truetype(path, config[CONF_SIZE])
font = ImageFont.truetype(path, conf[CONF_SIZE]) except Exception as e:
except Exception as e: raise core.EsphomeyamlError(u"Could not load truetype file {}: {}".format(path, e))
raise core.ESPHomeYAMLError(u"Could not load truetype file {}: {}".format(path, e))
ascent, descent = font.getmetrics() ascent, descent = font.getmetrics()
glyph_args = {} glyph_args = {}
data = [] data = []
for glyph in conf[CONF_GLYPHS]: for glyph in config[CONF_GLYPHS]:
mask = font.getmask(glyph, mode='1') mask = font.getmask(glyph, mode='1')
_, (offset_x, offset_y) = font.font.getsize(glyph) _, (offset_x, offset_y) = font.font.getsize(glyph)
width, height = mask.size width, height = mask.size
width8 = ((width + 7) // 8) * 8 width8 = ((width + 7) // 8) * 8
glyph_data = [0 for _ in range(height * width8 // 8)] # noqa: F812 glyph_data = [0 for _ in range(height * width8 // 8)] # noqa: F812
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
if not mask.getpixel((x, y)): if not mask.getpixel((x, y)):
continue continue
pos = x + y * width8 pos = x + y * width8
glyph_data[pos // 8] |= 0x80 >> (pos % 8) glyph_data[pos // 8] |= 0x80 >> (pos % 8)
glyph_args[glyph] = (len(data), offset_x, offset_y, width, height) glyph_args[glyph] = (len(data), offset_x, offset_y, width, height)
data += glyph_data data += glyph_data
raw_data = MockObj(conf[CONF_RAW_DATA_ID]) raw_data = MockObj(config[CONF_RAW_DATA_ID])
add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format( add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format(
raw_data, len(data), raw_data, len(data),
ArrayInitializer(*[HexInt(x) for x in data], multiline=False)))) ArrayInitializer(*[HexInt(x) for x in data], multiline=False))))
glyphs = [] glyphs = []
for glyph in conf[CONF_GLYPHS]: for glyph in config[CONF_GLYPHS]:
glyphs.append(Glyph(glyph, raw_data, *glyph_args[glyph])) glyphs.append(Glyph(glyph, raw_data, *glyph_args[glyph]))
rhs = App.make_font(ArrayInitializer(*glyphs), ascent, ascent + descent) rhs = App.make_font(ArrayInitializer(*glyphs), ascent, ascent + descent)
Pvariable(conf[CONF_ID], rhs) Pvariable(config[CONF_ID], rhs)

View File

@ -2,34 +2,34 @@ import voluptuous as vol
from esphomeyaml import config_validation as cv from esphomeyaml import config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_TYPE from esphomeyaml.const import CONF_ID, CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_TYPE
from esphomeyaml.helpers import App, Component, Pvariable, RawExpression, TemplateArguments, add, \ from esphomeyaml.cpp_generator import Pvariable, RawExpression, TemplateArguments, add
esphomelib_ns, setup_component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
GlobalVariableComponent = esphomelib_ns.class_('GlobalVariableComponent', Component) GlobalVariableComponent = esphomelib_ns.class_('GlobalVariableComponent', Component)
GLOBAL_VAR_SCHEMA = vol.Schema({ MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(GlobalVariableComponent), vol.Required(CONF_ID): cv.declare_variable_id(GlobalVariableComponent),
vol.Required(CONF_TYPE): cv.string_strict, vol.Required(CONF_TYPE): cv.string_strict,
vol.Optional(CONF_INITIAL_VALUE): cv.string_strict, vol.Optional(CONF_INITIAL_VALUE): cv.string_strict,
vol.Optional(CONF_RESTORE_VALUE): cv.boolean, vol.Optional(CONF_RESTORE_VALUE): cv.boolean,
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [GLOBAL_VAR_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: type_ = RawExpression(config[CONF_TYPE])
type_ = RawExpression(conf[CONF_TYPE]) template_args = TemplateArguments(type_)
template_args = TemplateArguments(type_) res_type = GlobalVariableComponent.template(template_args)
res_type = GlobalVariableComponent.template(template_args) initial_value = None
initial_value = None if CONF_INITIAL_VALUE in config:
if CONF_INITIAL_VALUE in conf: initial_value = RawExpression(config[CONF_INITIAL_VALUE])
initial_value = RawExpression(conf[CONF_INITIAL_VALUE]) rhs = App.Pmake_global_variable(template_args, initial_value)
rhs = App.Pmake_global_variable(template_args, initial_value) glob = Pvariable(config[CONF_ID], rhs, type=res_type)
glob = Pvariable(conf[CONF_ID], rhs, type=res_type)
if conf.get(CONF_RESTORE_VALUE, False): if config.get(CONF_RESTORE_VALUE, False):
hash_ = hash(conf[CONF_ID].id) % 2**32 hash_ = hash(config[CONF_ID].id) % 2**32
add(glob.set_restore_value(hash_)) add(glob.set_restore_value(hash_))
setup_component(glob, conf) setup_component(glob, config)

View File

@ -1,18 +1,20 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CONF_ID, \ import esphomeyaml.config_validation as cv
CONF_RECEIVE_TIMEOUT from esphomeyaml.const import CONF_FREQUENCY, CONF_ID, CONF_RECEIVE_TIMEOUT, CONF_SCAN, CONF_SCL, \
from esphomeyaml.helpers import App, add, Pvariable, esphomelib_ns, setup_component, Component CONF_SDA
from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
I2CComponent = esphomelib_ns.class_('I2CComponent', Component) I2CComponent = esphomelib_ns.class_('I2CComponent', Component)
I2CDevice = pins.I2CDevice I2CDevice = pins.I2CDevice
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(I2CComponent), cv.GenerateID(): cv.declare_variable_id(I2CComponent),
vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin, vol.Optional(CONF_SDA, default='SDA'): pins.input_pullup_pin,
vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin, vol.Optional(CONF_SCL, default='SCL'): pins.input_pullup_pin,
vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)), vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)),
vol.Optional(CONF_SCAN): cv.boolean, vol.Optional(CONF_SCAN): cv.boolean,

View File

@ -3,17 +3,18 @@ import logging
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import core from esphomeyaml import core
from esphomeyaml.components import display, font from esphomeyaml.components import display, font
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE from esphomeyaml.const import CONF_FILE, CONF_ID, CONF_RESIZE
from esphomeyaml.core import HexInt from esphomeyaml.core import CORE, HexInt
from esphomeyaml.helpers import App, ArrayInitializer, MockObj, Pvariable, RawExpression, add, \ from esphomeyaml.cpp_generator import ArrayInitializer, MockObj, Pvariable, RawExpression, add
relative_path from esphomeyaml.cpp_types import App
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['display'] DEPENDENCIES = ['display']
MULTI_CONF = True
Image_ = display.display_ns.class_('Image') Image_ = display.display_ns.class_('Image')
@ -26,40 +27,39 @@ IMAGE_SCHEMA = vol.Schema({
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None), cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(None),
}) })
CONFIG_SCHEMA = vol.All(font.validate_pillow_installed, cv.ensure_list, [IMAGE_SCHEMA]) CONFIG_SCHEMA = vol.All(font.validate_pillow_installed, IMAGE_SCHEMA)
def to_code(config): def to_code(config):
from PIL import Image from PIL import Image
for conf in config: path = CORE.relative_path(config[CONF_FILE])
path = relative_path(conf[CONF_FILE]) try:
try: image = Image.open(path)
image = Image.open(path) except Exception as e:
except Exception as e: raise core.EsphomeyamlError(u"Could not load image file {}: {}".format(path, e))
raise core.ESPHomeYAMLError(u"Could not load image file {}: {}".format(path, e))
if CONF_RESIZE in conf: if CONF_RESIZE in config:
image.thumbnail(conf[CONF_RESIZE]) image.thumbnail(config[CONF_RESIZE])
image = image.convert('1', dither=Image.NONE) image = image.convert('1', dither=Image.NONE)
width, height = image.size width, height = image.size
if width > 500 or height > 500: if width > 500 or height > 500:
_LOGGER.warning("The image you requested is very big. Please consider using the resize " _LOGGER.warning("The image you requested is very big. Please consider using the resize "
"parameter") "parameter")
width8 = ((width + 7) // 8) * 8 width8 = ((width + 7) // 8) * 8
data = [0 for _ in range(height * width8 // 8)] data = [0 for _ in range(height * width8 // 8)]
for y in range(height): for y in range(height):
for x in range(width): for x in range(width):
if image.getpixel((x, y)): if image.getpixel((x, y)):
continue continue
pos = x + y * width8 pos = x + y * width8
data[pos // 8] |= 0x80 >> (pos % 8) data[pos // 8] |= 0x80 >> (pos % 8)
raw_data = MockObj(conf[CONF_RAW_DATA_ID]) raw_data = MockObj(config[CONF_RAW_DATA_ID])
add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format( add(RawExpression('static const uint8_t {}[{}] PROGMEM = {}'.format(
raw_data, len(data), raw_data, len(data),
ArrayInitializer(*[HexInt(x) for x in data], multiline=False)))) ArrayInitializer(*[HexInt(x) for x in data], multiline=False))))
rhs = App.make_image(raw_data, width, height) rhs = App.make_image(raw_data, width, height)
Pvariable(conf[CONF_ID], rhs) Pvariable(config[CONF_ID], rhs)

View File

@ -2,15 +2,19 @@ import voluptuous as vol
from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.components.mqtt import setup_mqtt_component
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ALPHA, CONF_BLUE, CONF_BRIGHTNESS, CONF_COLORS, \ from esphomeyaml.const import CONF_ALPHA, CONF_BLUE, CONF_BRIGHTNESS, CONF_COLORS, \
CONF_COLOR_TEMPERATURE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_DURATION, CONF_EFFECT, \ CONF_DEFAULT_TRANSITION_LENGTH, CONF_DURATION, CONF_EFFECTS, CONF_EFFECT_ID, \
CONF_EFFECTS, CONF_EFFECT_ID, CONF_FLASH_LENGTH, CONF_GAMMA_CORRECT, CONF_GREEN, CONF_ID, \ CONF_GAMMA_CORRECT, CONF_GREEN, CONF_ID, CONF_INTERNAL, CONF_LAMBDA, CONF_MQTT_ID, CONF_NAME, \
CONF_INTERNAL, CONF_LAMBDA, CONF_MQTT_ID, CONF_NAME, CONF_NUM_LEDS, CONF_RANDOM, CONF_RED, \ CONF_NUM_LEDS, CONF_RANDOM, CONF_RED, CONF_SPEED, CONF_STATE, CONF_TRANSITION_LENGTH, \
CONF_SPEED, CONF_STATE, CONF_TRANSITION_LENGTH, CONF_UPDATE_INTERVAL, CONF_WHITE, CONF_WIDTH CONF_UPDATE_INTERVAL, CONF_WHITE, CONF_WIDTH, CONF_FLASH_LENGTH, CONF_COLOR_TEMPERATURE, \
from esphomeyaml.helpers import Action, Application, ArrayInitializer, Component, Nameable, \ CONF_EFFECT
Pvariable, StructInitializer, TemplateArguments, add, add_job, esphomelib_ns, float_, \ from esphomeyaml.core import CORE
get_variable, process_lambda, setup_mqtt_component, std_string, templatable, uint32 from esphomeyaml.cpp_generator import process_lambda, Pvariable, add, StructInitializer, \
ArrayInitializer, get_variable, templatable
from esphomeyaml.cpp_types import esphomelib_ns, Application, Component, Nameable, Action, uint32, \
float_, std_string
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -173,26 +177,35 @@ EFFECTS_SCHEMA = vol.Schema({
def validate_effects(allowed_effects): def validate_effects(allowed_effects):
def validator(value): def validator(value):
is_list = isinstance(value, list)
value = cv.ensure_list(value) value = cv.ensure_list(value)
names = set() names = set()
ret = [] ret = []
for i, effect in enumerate(value): for i, effect in enumerate(value):
path = [i] if is_list else []
if not isinstance(effect, dict): if not isinstance(effect, dict):
raise vol.Invalid("Each effect must be a dictionary, not {}".format(type(value))) raise vol.Invalid("Each effect must be a dictionary, not {}".format(type(value)),
path)
if len(effect) > 1: if len(effect) > 1:
raise vol.Invalid("Each entry in the 'effects:' option must be a single effect.") raise vol.Invalid("Each entry in the 'effects:' option must be a single effect.",
path)
if not effect: if not effect:
raise vol.Invalid("Found no effect for the {}th entry in 'effects:'!".format(i)) raise vol.Invalid("Found no effect for the {}th entry in 'effects:'!".format(i),
path)
key = next(iter(effect.keys())) key = next(iter(effect.keys()))
if key not in allowed_effects: if key not in allowed_effects:
raise vol.Invalid("The effect '{}' does not exist or is not allowed for this " raise vol.Invalid("The effect '{}' does not exist or is not allowed for this "
"light type".format(key)) "light type".format(key), path)
effect[key] = effect[key] or {} effect[key] = effect[key] or {}
conf = EFFECTS_SCHEMA(effect) try:
conf = EFFECTS_SCHEMA(effect)
except vol.Invalid as err:
err.prepend(path)
raise err
name = conf[key][CONF_NAME] name = conf[key][CONF_NAME]
if name in names: if name in names:
raise vol.Invalid(u"Found the effect name '{}' twice. All effects must have " raise vol.Invalid(u"Found the effect name '{}' twice. All effects must have "
u"unique names".format(name)) u"unique names".format(name), [i])
names.add(name) names.add(name)
ret.append(conf) ret.append(conf)
return ret return ret
@ -346,7 +359,7 @@ def setup_light_core_(light_var, mqtt_var, config):
def setup_light(light_obj, mqtt_obj, config): def setup_light(light_obj, mqtt_obj, config):
light_var = Pvariable(config[CONF_ID], light_obj, has_side_effects=False) light_var = Pvariable(config[CONF_ID], light_obj, has_side_effects=False)
mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False) mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
add_job(setup_light_core_, light_var, mqtt_var, config) CORE.add_job(setup_light_core_, light_var, mqtt_var, config)
BUILD_FLAGS = '-DUSE_LIGHT' BUILD_FLAGS = '-DUSE_LIGHT'
@ -359,8 +372,7 @@ LIGHT_TOGGLE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TOGGLE, LIGHT_TOGGLE_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_LIGHT_TOGGLE, LIGHT_TOGGLE_ACTION_SCHEMA)
def light_toggle_to_code(config, action_id, arg_type): def light_toggle_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_toggle_action(template_arg) rhs = var.make_toggle_action(template_arg)
@ -381,8 +393,7 @@ LIGHT_TURN_OFF_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TURN_OFF, LIGHT_TURN_OFF_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_LIGHT_TURN_OFF, LIGHT_TURN_OFF_ACTION_SCHEMA)
def light_turn_off_to_code(config, action_id, arg_type): def light_turn_off_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_off_action(template_arg) rhs = var.make_turn_off_action(template_arg)
@ -413,8 +424,7 @@ LIGHT_TURN_ON_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_LIGHT_TURN_ON, LIGHT_TURN_ON_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_LIGHT_TURN_ON, LIGHT_TURN_ON_ACTION_SCHEMA)
def light_turn_on_to_code(config, action_id, arg_type): def light_turn_on_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_on_action(template_arg) rhs = var.make_turn_on_action(template_arg)

View File

@ -3,7 +3,9 @@ import voluptuous as vol
from esphomeyaml.components import light, output from esphomeyaml.components import light, output
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_EFFECTS, CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT from esphomeyaml.const import CONF_EFFECTS, CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
from esphomeyaml.helpers import App, get_variable, setup_component, variable from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),

View File

@ -7,7 +7,9 @@ from esphomeyaml.components.light.rgbww import validate_cold_white_colder, \
from esphomeyaml.const import CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \ from esphomeyaml.const import CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \ CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
CONF_NAME, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE CONF_NAME, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE
from esphomeyaml.helpers import App, get_variable, variable, setup_component from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),

View File

@ -1,14 +1,15 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import light from esphomeyaml.components import light
from esphomeyaml.components.power_supply import PowerSupplyComponent from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \ import esphomeyaml.config_validation as cv
CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, \ from esphomeyaml.const import CONF_CHIPSET, CONF_COLOR_CORRECT, CONF_DEFAULT_TRANSITION_LENGTH, \
CONF_RGB_ORDER, CONF_EFFECTS, CONF_COLOR_CORRECT CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, \
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \ CONF_NUM_LEDS, CONF_PIN, CONF_POWER_SUPPLY, CONF_RGB_ORDER
get_variable, variable, setup_component from esphomeyaml.cpp_generator import RawExpression, TemplateArguments, add, get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Application
TYPES = [ TYPES = [
'NEOPIXEL', 'NEOPIXEL',
@ -103,6 +104,8 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT' BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
LIB_DEPS = 'FastLED@3.2.0'
def to_hass_config(data, config): def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False, return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,

View File

@ -1,14 +1,15 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import light from esphomeyaml.components import light
from esphomeyaml.components.power_supply import PowerSupplyComponent from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \ import esphomeyaml.config_validation as cv
CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_MAKE_ID, CONF_MAX_REFRESH_RATE, \ from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_COLOR_CORRECT, CONF_DATA_PIN, \
CONF_NAME, CONF_NUM_LEDS, CONF_POWER_SUPPLY, CONF_RGB_ORDER, CONF_EFFECTS, CONF_COLOR_CORRECT CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_MAKE_ID, \
from esphomeyaml.helpers import App, Application, RawExpression, TemplateArguments, add, \ CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_POWER_SUPPLY, CONF_RGB_ORDER
get_variable, variable, setup_component from esphomeyaml.cpp_generator import RawExpression, TemplateArguments, add, get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Application
CHIPSETS = [ CHIPSETS = [
'LPD8806', 'LPD8806',
@ -83,6 +84,8 @@ def to_code(config):
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT' BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
LIB_DEPS = 'FastLED@3.2.0'
def to_hass_config(data, config): def to_hass_config(data, config):
return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False, return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False,

View File

@ -4,7 +4,9 @@ from esphomeyaml.components import light, output
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, \ from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, \
CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT
from esphomeyaml.helpers import App, get_variable, setup_component, variable from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),

View File

@ -1,10 +1,12 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import light, output from esphomeyaml.components import light, output
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \ import esphomeyaml.config_validation as cv
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_EFFECTS from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, \
from esphomeyaml.helpers import App, get_variable, variable, setup_component CONF_GAMMA_CORRECT, CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED
from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),

View File

@ -1,10 +1,12 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import light, output from esphomeyaml.components import light, output
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \ import esphomeyaml.config_validation as cv
CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE, CONF_EFFECTS from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, \
from esphomeyaml.helpers import App, get_variable, variable, setup_component CONF_GAMMA_CORRECT, CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE
from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({
cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight),

View File

@ -1,11 +1,13 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import light, output from esphomeyaml.components import light, output
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_BLUE, CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \ from esphomeyaml.const import CONF_BLUE, CONF_COLD_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_GREEN, CONF_MAKE_ID, \ CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_GREEN, CONF_MAKE_ID, \
CONF_NAME, CONF_RED, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE CONF_NAME, CONF_RED, CONF_WARM_WHITE, CONF_WARM_WHITE_COLOR_TEMPERATURE
from esphomeyaml.helpers import App, get_variable, variable, setup_component from esphomeyaml.cpp_generator import get_variable, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App
def validate_color_temperature(value): def validate_color_temperature(value):

View File

@ -6,9 +6,9 @@ from esphomeyaml.automation import ACTION_REGISTRY, LambdaAction
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_ID, CONF_LEVEL, \ from esphomeyaml.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_ID, CONF_LEVEL, \
CONF_LOGS, CONF_TAG, CONF_TX_BUFFER_SIZE CONF_LOGS, CONF_TAG, CONF_TX_BUFFER_SIZE
from esphomeyaml.core import ESPHomeYAMLError, Lambda from esphomeyaml.core import EsphomeyamlError, Lambda
from esphomeyaml.helpers import App, Pvariable, RawExpression, TemplateArguments, add, \ from esphomeyaml.cpp_generator import Pvariable, RawExpression, add, process_lambda, statement
esphomelib_ns, global_ns, process_lambda, statement, Component from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns
LOG_LEVELS = { LOG_LEVELS = {
'NONE': global_ns.ESPHOMELIB_LOG_LEVEL_NONE, 'NONE': global_ns.ESPHOMELIB_LOG_LEVEL_NONE,
@ -39,7 +39,7 @@ def validate_local_no_higher_than_global(value):
global_level = value.get(CONF_LEVEL, 'DEBUG') global_level = value.get(CONF_LEVEL, 'DEBUG')
for tag, level in value.get(CONF_LOGS, {}).iteritems(): for tag, level in value.get(CONF_LOGS, {}).iteritems():
if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level): 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 " raise EsphomeyamlError(u"The local log level {} for {} must be less severe than the "
u"global log level {}.".format(level, tag, global_level)) u"global log level {}.".format(level, tag, global_level))
return value return value
@ -115,8 +115,7 @@ LOGGER_LOG_ACTION_SCHEMA = vol.All(maybe_simple_message({
@ACTION_REGISTRY.register(CONF_LOGGER_LOG, LOGGER_LOG_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_LOGGER_LOG, LOGGER_LOG_ACTION_SCHEMA)
def logger_log_action_to_code(config, action_id, arg_type): def logger_log_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]] esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]]
args = [RawExpression(unicode(x)) for x in config[CONF_ARGS]] args = [RawExpression(unicode(x)) for x in config[CONF_ARGS]]

View File

@ -7,17 +7,18 @@ from esphomeyaml import automation
from esphomeyaml.automation import ACTION_REGISTRY from esphomeyaml.automation import ACTION_REGISTRY
from esphomeyaml.components import logger from esphomeyaml.components import logger
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, CONF_DISCOVERY, \ from esphomeyaml.const import CONF_AVAILABILITY, CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, \
CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, \ CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, \
CONF_LOG_TOPIC, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, \ CONF_ESPHOMEYAML, CONF_ID, CONF_INTERNAL, CONF_KEEPALIVE, CONF_LEVEL, CONF_LOG_TOPIC, \
CONF_REBOOT_TIMEOUT, CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, CONF_TOPIC, \ CONF_MQTT, CONF_NAME, CONF_ON_JSON_MESSAGE, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, \
CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, CONF_WILL_MESSAGE, CONF_ON_JSON_MESSAGE, \ CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, CONF_QOS, CONF_REBOOT_TIMEOUT, \
CONF_STATE_TOPIC, CONF_MQTT, CONF_ESPHOMEYAML, CONF_NAME, CONF_AVAILABILITY, \ CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, CONF_STATE_TOPIC, CONF_TOPIC, \
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_INTERNAL CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, CONF_WILL_MESSAGE
from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.core import EsphomeyamlError
from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, RawExpression, \ from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, RawExpression, \
StructInitializer, TemplateArguments, add, esphomelib_ns, optional, std_string, templatable, \ StructInitializer, TemplateArguments, add, process_lambda, templatable
uint8, bool_, JsonObjectRef, process_lambda, JsonObjectConstRef, Component, Action, Trigger from esphomeyaml.cpp_types import Action, App, Component, JsonObjectConstRef, JsonObjectRef, \
Trigger, bool_, esphomelib_ns, optional, std_string, uint8
def validate_message_just_topic(value): def validate_message_just_topic(value):
@ -48,12 +49,14 @@ MQTTJsonMessageTrigger = mqtt_ns.class_('MQTTJsonMessageTrigger',
MQTTComponent = mqtt_ns.class_('MQTTComponent', Component) MQTTComponent = mqtt_ns.class_('MQTTComponent', Component)
def validate_broker(value): def validate_config(value):
value = cv.string_strict(value) if CONF_PORT not in value:
if u':' in value: parts = value[CONF_BROKER].split(u':')
raise vol.Invalid(u"Please specify the port using the port: option") if len(parts) == 2:
if not value: value[CONF_BROKER] = parts[0]
raise vol.Invalid(u"Broker cannot be empty") value[CONF_PORT] = cv.port(parts[1])
else:
value[CONF_PORT] = 1883
return value return value
@ -64,10 +67,10 @@ def validate_fingerprint(value):
return value return value
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.All(vol.Schema({
cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent), cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent),
vol.Required(CONF_BROKER): validate_broker, vol.Required(CONF_BROKER): cv.string_strict,
vol.Optional(CONF_PORT, default=1883): cv.port, vol.Optional(CONF_PORT): cv.port,
vol.Optional(CONF_USERNAME, default=''): cv.string, vol.Optional(CONF_USERNAME, default=''): cv.string,
vol.Optional(CONF_PASSWORD, default=''): cv.string, vol.Optional(CONF_PASSWORD, default=''): cv.string,
vol.Optional(CONF_CLIENT_ID): vol.All(cv.string, vol.Length(max=23)), vol.Optional(CONF_CLIENT_ID): vol.All(cv.string, vol.Length(max=23)),
@ -88,14 +91,15 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_ON_MESSAGE): automation.validate_automation({ vol.Optional(CONF_ON_MESSAGE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger),
vol.Required(CONF_TOPIC): cv.subscribe_topic, vol.Required(CONF_TOPIC): cv.subscribe_topic,
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos, vol.Optional(CONF_QOS): cv.mqtt_qos,
vol.Optional(CONF_PAYLOAD): cv.string_strict,
}), }),
vol.Optional(CONF_ON_JSON_MESSAGE): automation.validate_automation({ vol.Optional(CONF_ON_JSON_MESSAGE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTJsonMessageTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTJsonMessageTrigger),
vol.Required(CONF_TOPIC): cv.subscribe_topic, vol.Required(CONF_TOPIC): cv.subscribe_topic,
vol.Optional(CONF_QOS, default=0): cv.mqtt_qos, vol.Optional(CONF_QOS, default=0): cv.mqtt_qos,
}), }),
}) }), validate_config)
def exp_mqtt_message(config): def exp_mqtt_message(config):
@ -169,8 +173,12 @@ def to_code(config):
add(mqtt.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) add(mqtt.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
for conf in config.get(CONF_ON_MESSAGE, []): for conf in config.get(CONF_ON_MESSAGE, []):
rhs = mqtt.make_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS]) rhs = mqtt.make_message_trigger(conf[CONF_TOPIC])
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
if CONF_QOS in conf:
add(trigger.set_qos(conf[CONF_QOS]))
if CONF_PAYLOAD in conf:
add(trigger.set_payload(conf[CONF_PAYLOAD]))
automation.build_automation(trigger, std_string, conf) automation.build_automation(trigger, std_string, conf)
for conf in config.get(CONF_ON_JSON_MESSAGE, []): for conf in config.get(CONF_ON_JSON_MESSAGE, []):
@ -189,8 +197,7 @@ MQTT_PUBLISH_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_MQTT_PUBLISH, MQTT_PUBLISH_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_MQTT_PUBLISH, MQTT_PUBLISH_ACTION_SCHEMA)
def mqtt_publish_action_to_code(config, action_id, arg_type): def mqtt_publish_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg) rhs = App.Pget_mqtt_client().Pmake_publish_action(template_arg)
type = MQTTPublishAction.template(template_arg) type = MQTTPublishAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type) action = Pvariable(action_id, rhs, type=type)
@ -222,8 +229,7 @@ MQTT_PUBLISH_JSON_ACTION_SCHEMA = vol.Schema({
@ACTION_REGISTRY.register(CONF_MQTT_PUBLISH_JSON, MQTT_PUBLISH_JSON_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_MQTT_PUBLISH_JSON, MQTT_PUBLISH_JSON_ACTION_SCHEMA)
def mqtt_publish_json_action_to_code(config, action_id, arg_type): def mqtt_publish_json_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
rhs = App.Pget_mqtt_client().Pmake_publish_json_action(template_arg) rhs = App.Pget_mqtt_client().Pmake_publish_json_action(template_arg)
type = MQTTPublishJsonAction.template(template_arg) type = MQTTPublishJsonAction.template(template_arg)
action = Pvariable(action_id, rhs, type=type) action = Pvariable(action_id, rhs, type=type)
@ -282,7 +288,7 @@ def build_hass_config(data, component_type, config, include_state=True, include_
class GenerateHassConfigData(object): class GenerateHassConfigData(object):
def __init__(self, config): def __init__(self, config):
if 'mqtt' not in config: if 'mqtt' not in config:
raise ESPHomeYAMLError("Cannot generate Home Assistant MQTT config if MQTT is not " raise EsphomeyamlError("Cannot generate Home Assistant MQTT config if MQTT is not "
"used!") "used!")
mqtt = config[CONF_MQTT] mqtt = config[CONF_MQTT]
self.topic_prefix = mqtt.get(CONF_TOPIC_PREFIX, config[CONF_ESPHOMEYAML][CONF_NAME]) self.topic_prefix = mqtt.get(CONF_TOPIC_PREFIX, config[CONF_ESPHOMEYAML][CONF_NAME])
@ -308,3 +314,21 @@ class GenerateHassConfigData(object):
CONF_PAYLOAD_AVAILABLE: birth_message[CONF_PAYLOAD], CONF_PAYLOAD_AVAILABLE: birth_message[CONF_PAYLOAD],
CONF_PAYLOAD_NOT_AVAILABLE: will_message[CONF_PAYLOAD], CONF_PAYLOAD_NOT_AVAILABLE: will_message[CONF_PAYLOAD],
} }
def setup_mqtt_component(obj, config):
if CONF_RETAIN in config:
add(obj.set_retain(config[CONF_RETAIN]))
if not config.get(CONF_DISCOVERY, True):
add(obj.disable_discovery())
if CONF_STATE_TOPIC in config:
add(obj.set_custom_state_topic(config[CONF_STATE_TOPIC]))
if CONF_COMMAND_TOPIC in config:
add(obj.set_custom_command_topic(config[CONF_COMMAND_TOPIC]))
if CONF_AVAILABILITY in config:
availability = config[CONF_AVAILABILITY]
if not availability:
add(obj.disable_availability())
else:
add(obj.set_availability(availability[CONF_TOPIC], availability[CONF_PAYLOAD_AVAILABLE],
availability[CONF_PAYLOAD_NOT_AVAILABLE]))

View File

@ -1,18 +1,18 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import output from esphomeyaml.components import output
from esphomeyaml.const import (CONF_DATA_PIN, CONF_CLOCK_PIN, CONF_NUM_CHANNELS, import esphomeyaml.config_validation as cv
CONF_NUM_CHIPS, CONF_BIT_DEPTH, CONF_ID, from esphomeyaml.const import (CONF_BIT_DEPTH, CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_ID,
CONF_UPDATE_ON_BOOT) CONF_NUM_CHANNELS, CONF_NUM_CHIPS, CONF_UPDATE_ON_BOOT)
from esphomeyaml.helpers import (gpio_output_pin_expression, App, Pvariable, from esphomeyaml.cpp_generator import Pvariable, add
add, setup_component, Component) from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component
MY9231OutputComponent = output.output_ns.class_('MY9231OutputComponent', Component) MY9231OutputComponent = output.output_ns.class_('MY9231OutputComponent', Component)
MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
MY9231_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(MY9231OutputComponent), cv.GenerateID(): cv.declare_variable_id(MY9231OutputComponent),
vol.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema,
vol.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema,
@ -24,28 +24,23 @@ MY9231_SCHEMA = vol.Schema({
vol.Optional(CONF_UPDATE_ON_BOOT): vol.Coerce(bool), vol.Optional(CONF_UPDATE_ON_BOOT): vol.Coerce(bool),
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [MY9231_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: for di in gpio_output_pin_expression(config[CONF_DATA_PIN]):
di = None yield
for di in gpio_output_pin_expression(conf[CONF_DATA_PIN]): for dcki in gpio_output_pin_expression(config[CONF_CLOCK_PIN]):
yield yield
dcki = None rhs = App.make_my9231_component(di, dcki)
for dcki in gpio_output_pin_expression(conf[CONF_CLOCK_PIN]): my9231 = Pvariable(config[CONF_ID], rhs)
yield if CONF_NUM_CHANNELS in config:
rhs = App.make_my9231_component(di, dcki) add(my9231.set_num_channels(config[CONF_NUM_CHANNELS]))
my9231 = Pvariable(conf[CONF_ID], rhs) if CONF_NUM_CHIPS in config:
if CONF_NUM_CHANNELS in conf: add(my9231.set_num_chips(config[CONF_NUM_CHIPS]))
add(my9231.set_num_channels(conf[CONF_NUM_CHANNELS])) if CONF_BIT_DEPTH in config:
if CONF_NUM_CHIPS in conf: add(my9231.set_bit_depth(config[CONF_BIT_DEPTH]))
add(my9231.set_num_chips(conf[CONF_NUM_CHIPS])) if CONF_UPDATE_ON_BOOT in config:
if CONF_BIT_DEPTH in conf: add(my9231.set_update(config[CONF_UPDATE_ON_BOOT]))
add(my9231.set_bit_depth(conf[CONF_BIT_DEPTH])) setup_component(my9231, config)
if CONF_UPDATE_ON_BOOT in conf:
add(my9231.set_update(conf[CONF_UPDATE_ON_BOOT]))
setup_component(my9231, conf)
BUILD_FLAGS = '-DUSE_MY9231_OUTPUT' BUILD_FLAGS = '-DUSE_MY9231_OUTPUT'

View File

@ -2,12 +2,11 @@ import logging
import voluptuous as vol import voluptuous as vol
from esphomeyaml import core
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_OTA, CONF_PASSWORD, CONF_PORT, CONF_SAFE_MODE, \ 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 CORE
from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, Component from esphomeyaml.cpp_types import App, Component, esphomelib_ns
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -35,11 +34,11 @@ def to_code(config):
def get_port(config): def get_port(config):
if CONF_PORT in config[CONF_OTA]: if CONF_PORT in config[CONF_OTA]:
return config[CONF_OTA][CONF_PORT] return config[CONF_OTA][CONF_PORT]
if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: if CORE.is_esp32:
return 3232 return 3232
elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266: elif CORE.is_esp8266:
return 8266 return 8266
raise ESPHomeYAMLError(u"Invalid ESP Platform for ESP OTA port.") raise NotImplementedError
def get_auth(config): def get_auth(config):
@ -51,6 +50,8 @@ REQUIRED_BUILD_FLAGS = '-DUSE_NEW_OTA'
def lib_deps(config): def lib_deps(config):
if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: if CORE.is_esp32:
return ['ArduinoOTA', 'Update', 'ESPmDNS'] return ['Update', 'ESPmDNS']
return ['Hash', 'ESP8266mDNS', 'ArduinoOTA'] elif CORE.is_esp8266:
return ['Hash', 'ESP8266mDNS']
raise NotImplementedError

View File

@ -4,8 +4,9 @@ from esphomeyaml.automation import maybe_simple_id, ACTION_REGISTRY
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components.power_supply import PowerSupplyComponent from esphomeyaml.components.power_supply import PowerSupplyComponent
from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY, CONF_ID, CONF_LEVEL from esphomeyaml.const import CONF_INVERTED, CONF_MAX_POWER, CONF_POWER_SUPPLY, CONF_ID, CONF_LEVEL
from esphomeyaml.helpers import add, esphomelib_ns, get_variable, TemplateArguments, Pvariable, \ from esphomeyaml.core import CORE
templatable, float_, add_job, Action from esphomeyaml.cpp_generator import add, get_variable, Pvariable, templatable
from esphomeyaml.cpp_types import esphomelib_ns, Action, float_
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -26,7 +27,9 @@ FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema
output_ns = esphomelib_ns.namespace('output') output_ns = esphomelib_ns.namespace('output')
BinaryOutput = output_ns.class_('BinaryOutput') BinaryOutput = output_ns.class_('BinaryOutput')
BinaryOutputPtr = BinaryOutput.operator('ptr')
FloatOutput = output_ns.class_('FloatOutput', BinaryOutput) FloatOutput = output_ns.class_('FloatOutput', BinaryOutput)
FloatOutputPtr = FloatOutput.operator('ptr')
# Actions # Actions
TurnOffAction = output_ns.class_('TurnOffAction', Action) TurnOffAction = output_ns.class_('TurnOffAction', Action)
@ -47,7 +50,12 @@ def setup_output_platform_(obj, config, skip_power_supply=False):
def setup_output_platform(obj, config, skip_power_supply=False): def setup_output_platform(obj, config, skip_power_supply=False):
add_job(setup_output_platform_, obj, config, skip_power_supply) CORE.add_job(setup_output_platform_, obj, config, skip_power_supply)
def register_output(var, config):
output_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
CORE.add_job(setup_output_platform_, output_var, config)
BUILD_FLAGS = '-DUSE_OUTPUT' BUILD_FLAGS = '-DUSE_OUTPUT'
@ -60,8 +68,7 @@ OUTPUT_TURN_ON_ACTION = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_ON, OUTPUT_TURN_ON_ACTION) @ACTION_REGISTRY.register(CONF_OUTPUT_TURN_ON, OUTPUT_TURN_ON_ACTION)
def output_turn_on_to_code(config, action_id, arg_type): def output_turn_on_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_on_action(template_arg) rhs = var.make_turn_on_action(template_arg)
@ -76,8 +83,7 @@ OUTPUT_TURN_OFF_ACTION = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_OUTPUT_TURN_OFF, OUTPUT_TURN_OFF_ACTION) @ACTION_REGISTRY.register(CONF_OUTPUT_TURN_OFF, OUTPUT_TURN_OFF_ACTION)
def output_turn_off_to_code(config, action_id, arg_type): def output_turn_off_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_turn_off_action(template_arg) rhs = var.make_turn_off_action(template_arg)
@ -93,8 +99,7 @@ OUTPUT_SET_LEVEL_ACTION = vol.Schema({
@ACTION_REGISTRY.register(CONF_OUTPUT_SET_LEVEL, OUTPUT_SET_LEVEL_ACTION) @ACTION_REGISTRY.register(CONF_OUTPUT_SET_LEVEL, OUTPUT_SET_LEVEL_ACTION)
def output_set_level_to_code(config, action_id, arg_type): def output_set_level_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_set_level_action(template_arg) rhs = var.make_set_level_action(template_arg)

View File

@ -0,0 +1,66 @@
import voluptuous as vol
from esphomeyaml.components import output
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE
from esphomeyaml.cpp_generator import process_lambda, variable
from esphomeyaml.cpp_types import std_vector
CustomBinaryOutputConstructor = output.output_ns.class_('CustomBinaryOutputConstructor')
CustomFloatOutputConstructor = output.output_ns.class_('CustomFloatOutputConstructor')
BINARY_SCHEMA = output.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomBinaryOutputConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_OUTPUTS):
vol.All(cv.ensure_list, [output.BINARY_OUTPUT_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.BinaryOutput),
})]),
})
FLOAT_SCHEMA = output.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomFloatOutputConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_OUTPUTS):
vol.All(cv.ensure_list, [output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(output.FloatOutput),
})]),
})
def validate_custom_output(value):
if not isinstance(value, dict):
raise vol.Invalid("Value must be dict")
if CONF_TYPE not in value:
raise vol.Invalid("type not specified!")
type = cv.string_strict(value[CONF_TYPE]).lower()
value[CONF_TYPE] = type
if type == 'binary':
return BINARY_SCHEMA(value)
elif type == 'float':
return FLOAT_SCHEMA(value)
raise vol.Invalid("type must either be binary or float, not {}!".format(type))
PLATFORM_SCHEMA = validate_custom_output
def to_code(config):
type = config[CONF_TYPE]
if type == 'binary':
ret_type = output.BinaryOutputPtr
klass = CustomBinaryOutputConstructor
else:
ret_type = output.FloatOutputPtr
klass = CustomFloatOutputConstructor
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=std_vector.template(ret_type)):
yield
rhs = klass(template_)
custom = variable(config[CONF_ID], rhs)
for i, sens in enumerate(config[CONF_OUTPUTS]):
output.register_output(custom.get_output(i), sens)
BUILD_FLAGS = '-DUSE_CUSTOM_OUTPUT'

View File

@ -3,9 +3,10 @@ import voluptuous as vol
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import output from esphomeyaml.components import output
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266, CONF_FREQUENCY from esphomeyaml.const import CONF_FREQUENCY, CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266
from esphomeyaml.helpers import App, Component, Pvariable, gpio_output_pin_expression, \ from esphomeyaml.cpp_generator import Pvariable, add
setup_component, add from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component
ESP_PLATFORMS = [ESP_PLATFORM_ESP8266] ESP_PLATFORMS = [ESP_PLATFORM_ESP8266]

View File

@ -1,11 +1,12 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml import pins from esphomeyaml import pins
import esphomeyaml.config_validation as cv
from esphomeyaml.components import output from esphomeyaml.components import output
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_PIN from esphomeyaml.const import CONF_ID, CONF_PIN
from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression, setup_component, \ from esphomeyaml.cpp_generator import Pvariable
Component from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component
GPIOBinaryOutputComponent = output.output_ns.class_('GPIOBinaryOutputComponent', GPIOBinaryOutputComponent = output.output_ns.class_('GPIOBinaryOutputComponent',
output.BinaryOutput, Component) output.BinaryOutput, Component)

View File

@ -1,11 +1,13 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import output from esphomeyaml.components import output
import esphomeyaml.config_validation as cv
from esphomeyaml.const import APB_CLOCK_FREQ, CONF_BIT_DEPTH, CONF_CHANNEL, CONF_FREQUENCY, \ from esphomeyaml.const import APB_CLOCK_FREQ, CONF_BIT_DEPTH, CONF_CHANNEL, CONF_FREQUENCY, \
CONF_ID, CONF_PIN, ESP_PLATFORM_ESP32 CONF_ID, CONF_PIN, ESP_PLATFORM_ESP32
from esphomeyaml.helpers import App, Pvariable, add, setup_component, Component from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component
ESP_PLATFORMS = [ESP_PLATFORM_ESP32] ESP_PLATFORMS = [ESP_PLATFORM_ESP32]

View File

@ -1,10 +1,11 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import output from esphomeyaml.components import output
from esphomeyaml.components.my9231 import MY9231OutputComponent from esphomeyaml.components.my9231 import MY9231OutputComponent
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_CHANNEL, CONF_ID, CONF_MY9231_ID, CONF_POWER_SUPPLY from esphomeyaml.const import CONF_CHANNEL, CONF_ID, CONF_MY9231_ID, CONF_POWER_SUPPLY
from esphomeyaml.helpers import Pvariable, get_variable, setup_component from esphomeyaml.cpp_generator import Pvariable, get_variable
from esphomeyaml.cpp_helpers import setup_component
DEPENDENCIES = ['my9231'] DEPENDENCIES = ['my9231']

View File

@ -1,10 +1,10 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import output from esphomeyaml.components import output
from esphomeyaml.components.pca9685 import PCA9685OutputComponent from esphomeyaml.components.pca9685 import PCA9685OutputComponent
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_CHANNEL, CONF_ID, CONF_PCA9685_ID, CONF_POWER_SUPPLY from esphomeyaml.const import CONF_CHANNEL, CONF_ID, CONF_PCA9685_ID, CONF_POWER_SUPPLY
from esphomeyaml.helpers import Pvariable, get_variable from esphomeyaml.cpp_generator import Pvariable, get_variable
DEPENDENCIES = ['pca9685'] DEPENDENCIES = ['pca9685']

View File

@ -1,37 +1,32 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.components import i2c, output
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import output, i2c from esphomeyaml.const import CONF_ADDRESS, CONF_FREQUENCY, CONF_ID
from esphomeyaml.const import CONF_ADDRESS, CONF_FREQUENCY, CONF_ID, CONF_PHASE_BALANCER from esphomeyaml.cpp_generator import Pvariable, add
from esphomeyaml.helpers import App, HexIntLiteral, Pvariable, add, setup_component, Component from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
MULTI_CONF = True
PCA9685OutputComponent = output.output_ns.class_('PCA9685OutputComponent', PCA9685OutputComponent = output.output_ns.class_('PCA9685OutputComponent',
Component, i2c.I2CDevice) Component, i2c.I2CDevice)
PHASE_BALANCER_MESSAGE = ("The phase_balancer option has been removed in version 1.5.0. " CONFIG_SCHEMA = vol.Schema({
"esphomelib will now automatically choose a suitable phase balancer.")
PCA9685_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent), cv.GenerateID(): cv.declare_variable_id(PCA9685OutputComponent),
vol.Required(CONF_FREQUENCY): vol.All(cv.frequency, vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
vol.Range(min=23.84, max=1525.88)), vol.Range(min=23.84, max=1525.88)),
vol.Optional(CONF_ADDRESS): cv.i2c_address, vol.Optional(CONF_ADDRESS): cv.i2c_address,
vol.Optional(CONF_PHASE_BALANCER): cv.invalid(PHASE_BALANCER_MESSAGE),
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCA9685_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: rhs = App.make_pca9685_component(config.get(CONF_FREQUENCY))
rhs = App.make_pca9685_component(conf.get(CONF_FREQUENCY)) pca9685 = Pvariable(config[CONF_ID], rhs)
pca9685 = Pvariable(conf[CONF_ID], rhs) if CONF_ADDRESS in config:
if CONF_ADDRESS in conf: add(pca9685.set_address(config[CONF_ADDRESS]))
add(pca9685.set_address(HexIntLiteral(conf[CONF_ADDRESS]))) setup_component(pca9685, config)
setup_component(pca9685, conf)
BUILD_FLAGS = '-DUSE_PCA9685_OUTPUT' BUILD_FLAGS = '-DUSE_PCA9685_OUTPUT'

View File

@ -3,9 +3,12 @@ import voluptuous as vol
from esphomeyaml import pins from esphomeyaml import pins
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_PCF8575 from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_PCF8575
from esphomeyaml.helpers import App, GPIOInputPin, GPIOOutputPin, Pvariable, io_ns, setup_component from esphomeyaml.cpp_generator import Pvariable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, GPIOInputPin, GPIOOutputPin, io_ns
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']
MULTI_CONF = True
PCF8574GPIOMode = io_ns.enum('PCF8574GPIOMode') PCF8574GPIOMode = io_ns.enum('PCF8574GPIOMode')
PCF8675_GPIO_MODES = { PCF8675_GPIO_MODES = {
@ -17,20 +20,17 @@ PCF8675_GPIO_MODES = {
PCF8574GPIOInputPin = io_ns.class_('PCF8574GPIOInputPin', GPIOInputPin) PCF8574GPIOInputPin = io_ns.class_('PCF8574GPIOInputPin', GPIOInputPin)
PCF8574GPIOOutputPin = io_ns.class_('PCF8574GPIOOutputPin', GPIOOutputPin) PCF8574GPIOOutputPin = io_ns.class_('PCF8574GPIOOutputPin', GPIOOutputPin)
PCF8574_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(pins.PCF8574Component), vol.Required(CONF_ID): cv.declare_variable_id(pins.PCF8574Component),
vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address, vol.Optional(CONF_ADDRESS, default=0x21): cv.i2c_address,
vol.Optional(CONF_PCF8575, default=False): cv.boolean, vol.Optional(CONF_PCF8575, default=False): cv.boolean,
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCF8574_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: rhs = App.make_pcf8574_component(config[CONF_ADDRESS], config[CONF_PCF8575])
rhs = App.make_pcf8574_component(conf[CONF_ADDRESS], conf[CONF_PCF8575]) var = Pvariable(config[CONF_ID], rhs)
var = Pvariable(conf[CONF_ID], rhs) setup_component(var, config)
setup_component(var, conf)
BUILD_FLAGS = '-DUSE_PCF8574' BUILD_FLAGS = '-DUSE_PCF8574'

View File

@ -1,21 +1,23 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv from esphomeyaml import automation, pins
from esphomeyaml import pins, automation
from esphomeyaml.components import binary_sensor, spi from esphomeyaml.components import binary_sensor, spi
from esphomeyaml.components.spi import SPIComponent from esphomeyaml.components.spi import SPIComponent
from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_SPI_ID, CONF_UPDATE_INTERVAL, \ import esphomeyaml.config_validation as cv
CONF_ON_TAG, CONF_TRIGGER_ID from esphomeyaml.const import CONF_CS_PIN, CONF_ID, CONF_ON_TAG, CONF_SPI_ID, CONF_TRIGGER_ID, \
from esphomeyaml.helpers import App, Pvariable, get_variable, gpio_output_pin_expression, \ CONF_UPDATE_INTERVAL
std_string, setup_component, PollingComponent, Trigger from esphomeyaml.cpp_generator import Pvariable, get_variable
from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, PollingComponent, Trigger, std_string
DEPENDENCIES = ['spi'] DEPENDENCIES = ['spi']
MULTI_CONF = True
PN532Component = binary_sensor.binary_sensor_ns.class_('PN532Component', PollingComponent, PN532Component = binary_sensor.binary_sensor_ns.class_('PN532Component', PollingComponent,
spi.SPIDevice) spi.SPIDevice)
PN532Trigger = binary_sensor.binary_sensor_ns.class_('PN532Trigger', Trigger.template(std_string)) PN532Trigger = binary_sensor.binary_sensor_ns.class_('PN532Trigger', Trigger.template(std_string))
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(PN532Component), cv.GenerateID(): cv.declare_variable_id(PN532Component),
cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent), cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent),
vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema,
@ -23,23 +25,22 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
vol.Optional(CONF_ON_TAG): automation.validate_automation({ vol.Optional(CONF_ON_TAG): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PN532Trigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PN532Trigger),
}), }),
}).extend(cv.COMPONENT_SCHEMA.schema)]) }).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config): def to_code(config):
for conf in config: for spi_ in get_variable(config[CONF_SPI_ID]):
for spi_ in get_variable(conf[CONF_SPI_ID]): yield
yield for cs in gpio_output_pin_expression(config[CONF_CS_PIN]):
for cs in gpio_output_pin_expression(conf[CONF_CS_PIN]): yield
yield rhs = App.make_pn532_component(spi_, cs, config.get(CONF_UPDATE_INTERVAL))
rhs = App.make_pn532_component(spi_, cs, conf.get(CONF_UPDATE_INTERVAL)) pn532 = Pvariable(config[CONF_ID], rhs)
pn532 = Pvariable(conf[CONF_ID], rhs)
for conf_ in conf.get(CONF_ON_TAG, []): for conf_ in config.get(CONF_ON_TAG, []):
trigger = Pvariable(conf_[CONF_TRIGGER_ID], pn532.make_trigger()) trigger = Pvariable(conf_[CONF_TRIGGER_ID], pn532.make_trigger())
automation.build_automation(trigger, std_string, conf_) automation.build_automation(trigger, std_string, conf_)
setup_component(pn532, conf) setup_component(pn532, config)
BUILD_FLAGS = '-DUSE_PN532' BUILD_FLAGS = '-DUSE_PN532'

View File

@ -1,36 +1,36 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN from esphomeyaml.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression, \ from esphomeyaml.cpp_generator import Pvariable, add
setup_component, Component from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
PowerSupplyComponent = esphomelib_ns.class_('PowerSupplyComponent', Component) PowerSupplyComponent = esphomelib_ns.class_('PowerSupplyComponent', Component)
POWER_SUPPLY_SCHEMA = vol.Schema({ MULTI_CONF = True
CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent), vol.Required(CONF_ID): cv.declare_variable_id(PowerSupplyComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds, vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds, vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
}).extend(cv.COMPONENT_SCHEMA.schema) }).extend(cv.COMPONENT_SCHEMA.schema)
CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
def to_code(config): def to_code(config):
for conf in config: for pin in gpio_output_pin_expression(config[CONF_PIN]):
for pin in gpio_output_pin_expression(conf[CONF_PIN]): yield
yield
rhs = App.make_power_supply(pin) rhs = App.make_power_supply(pin)
psu = Pvariable(conf[CONF_ID], rhs) psu = Pvariable(config[CONF_ID], rhs)
if CONF_ENABLE_TIME in conf: if CONF_ENABLE_TIME in config:
add(psu.set_enable_time(conf[CONF_ENABLE_TIME])) add(psu.set_enable_time(config[CONF_ENABLE_TIME]))
if CONF_KEEP_ON_TIME in conf: if CONF_KEEP_ON_TIME in config:
add(psu.set_keep_on_time(conf[CONF_KEEP_ON_TIME])) add(psu.set_keep_on_time(config[CONF_KEEP_ON_TIME]))
setup_component(psu, conf) setup_component(psu, config)
BUILD_FLAGS = '-DUSE_OUTPUT' BUILD_FLAGS = '-DUSE_OUTPUT'

View File

@ -1,28 +1,29 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import binary_sensor, uart from esphomeyaml.components import binary_sensor, uart
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_UART_ID from esphomeyaml.const import CONF_ID, CONF_UART_ID
from esphomeyaml.helpers import App, Pvariable, get_variable, setup_component, Component from esphomeyaml.cpp_generator import Pvariable, get_variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Component
DEPENDENCIES = ['uart'] DEPENDENCIES = ['uart']
RDM6300Component = binary_sensor.binary_sensor_ns.class_('RDM6300Component', Component, RDM6300Component = binary_sensor.binary_sensor_ns.class_('RDM6300Component', Component,
uart.UARTDevice) uart.UARTDevice)
CONFIG_SCHEMA = vol.All(cv.ensure_list_not_empty, [vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(RDM6300Component), cv.GenerateID(): cv.declare_variable_id(RDM6300Component),
cv.GenerateID(CONF_UART_ID): cv.use_variable_id(uart.UARTComponent), cv.GenerateID(CONF_UART_ID): cv.use_variable_id(uart.UARTComponent),
}).extend(cv.COMPONENT_SCHEMA.schema)]) }).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config): def to_code(config):
for conf in config: for uart_ in get_variable(config[CONF_UART_ID]):
for uart_ in get_variable(conf[CONF_UART_ID]): yield
yield rhs = App.make_rdm6300_component(uart_)
rhs = App.make_rdm6300_component(uart_) var = Pvariable(config[CONF_ID], rhs)
var = Pvariable(conf[CONF_ID], rhs) setup_component(var, config)
setup_component(var, conf)
BUILD_FLAGS = '-DUSE_RDM6300' BUILD_FLAGS = '-DUSE_RDM6300'

View File

@ -1,13 +1,15 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID, CONF_IDLE, \ from esphomeyaml.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID, CONF_IDLE, \
CONF_PIN, CONF_TOLERANCE CONF_PIN, CONF_TOLERANCE
from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_input_pin_expression, \ from esphomeyaml.cpp_generator import Pvariable, add
setup_component, Component from esphomeyaml.cpp_helpers import gpio_input_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component, esphomelib_ns
remote_ns = esphomelib_ns.namespace('remote') remote_ns = esphomelib_ns.namespace('remote')
MULTI_CONF = True
RemoteControlComponentBase = remote_ns.class_('RemoteControlComponentBase') RemoteControlComponentBase = remote_ns.class_('RemoteControlComponentBase')
RemoteReceiverComponent = remote_ns.class_('RemoteReceiverComponent', RemoteReceiverComponent = remote_ns.class_('RemoteReceiverComponent',
@ -35,7 +37,7 @@ def validate_dumpers_all(value):
raise vol.Invalid("Not valid dumpers") raise vol.Invalid("Not valid dumpers")
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent), cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent),
vol.Required(CONF_PIN): pins.gpio_input_pin_schema, vol.Required(CONF_PIN): pins.gpio_input_pin_schema,
vol.Optional(CONF_DUMP, default=[]): vol.Optional(CONF_DUMP, default=[]):
@ -45,28 +47,27 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes, vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes,
vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds, vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds,
vol.Optional(CONF_IDLE): cv.positive_time_period_microseconds, vol.Optional(CONF_IDLE): cv.positive_time_period_microseconds,
}).extend(cv.COMPONENT_SCHEMA.schema)]) }).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config): def to_code(config):
for conf in config: for pin in gpio_input_pin_expression(config[CONF_PIN]):
for pin in gpio_input_pin_expression(conf[CONF_PIN]): yield
yield rhs = App.make_remote_receiver_component(pin)
rhs = App.make_remote_receiver_component(pin) receiver = Pvariable(config[CONF_ID], rhs)
receiver = Pvariable(conf[CONF_ID], rhs)
for dumper in conf[CONF_DUMP]: for dumper in config[CONF_DUMP]:
add(receiver.add_dumper(DUMPERS[dumper].new())) add(receiver.add_dumper(DUMPERS[dumper].new()))
if CONF_TOLERANCE in conf: if CONF_TOLERANCE in config:
add(receiver.set_tolerance(conf[CONF_TOLERANCE])) add(receiver.set_tolerance(config[CONF_TOLERANCE]))
if CONF_BUFFER_SIZE in conf: if CONF_BUFFER_SIZE in config:
add(receiver.set_buffer_size(conf[CONF_BUFFER_SIZE])) add(receiver.set_buffer_size(config[CONF_BUFFER_SIZE]))
if CONF_FILTER in conf: if CONF_FILTER in config:
add(receiver.set_filter_us(conf[CONF_FILTER])) add(receiver.set_filter_us(config[CONF_FILTER]))
if CONF_IDLE in conf: if CONF_IDLE in config:
add(receiver.set_idle_us(conf[CONF_IDLE])) add(receiver.set_idle_us(config[CONF_IDLE]))
setup_component(receiver, conf) setup_component(receiver, config)
BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER' BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER'

View File

@ -7,14 +7,17 @@ from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_DUTY_PERCENT, CONF_CHAN
CONF_DEVICE, CONF_FAMILY, CONF_GROUP, CONF_ID, CONF_INVERTED, CONF_ONE, CONF_PIN, \ CONF_DEVICE, CONF_FAMILY, CONF_GROUP, CONF_ID, CONF_INVERTED, CONF_ONE, CONF_PIN, \
CONF_PROTOCOL, CONF_PULSE_LENGTH, CONF_STATE, CONF_SYNC, CONF_ZERO CONF_PROTOCOL, CONF_PULSE_LENGTH, CONF_STATE, CONF_SYNC, CONF_ZERO
from esphomeyaml.core import HexInt from esphomeyaml.core import HexInt
from esphomeyaml.helpers import App, Component, Pvariable, add, gpio_output_pin_expression, \ from esphomeyaml.cpp_generator import Pvariable, add
setup_component from esphomeyaml.cpp_helpers import gpio_output_pin_expression, setup_component
from esphomeyaml.cpp_types import App, Component
RemoteTransmitterComponent = remote_ns.class_('RemoteTransmitterComponent', RemoteTransmitterComponent = remote_ns.class_('RemoteTransmitterComponent',
RemoteControlComponentBase, Component) RemoteControlComponentBase, Component)
RCSwitchProtocol = remote_ns.class_('RCSwitchProtocol') RCSwitchProtocol = remote_ns.class_('RCSwitchProtocol')
rc_switch_protocols = remote_ns.rc_switch_protocols rc_switch_protocols = remote_ns.rc_switch_protocols
MULTI_CONF = True
def validate_rc_switch_code(value): def validate_rc_switch_code(value):
if not isinstance(value, (str, unicode)): if not isinstance(value, (str, unicode)):
@ -75,12 +78,12 @@ RC_SWITCH_TYPE_D_SCHEMA = vol.Schema({
vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, vol.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA,
}) })
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ CONFIG_SCHEMA = vol.Schema({
cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent), cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent),
vol.Required(CONF_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_PIN): pins.gpio_output_pin_schema,
vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(cv.percentage_int, vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(cv.percentage_int,
vol.Range(min=1, max=100)), vol.Range(min=1, max=100)),
}).extend(cv.COMPONENT_SCHEMA.schema)]) }).extend(cv.COMPONENT_SCHEMA.schema)
def build_rc_switch_protocol(config): def build_rc_switch_protocol(config):
@ -102,16 +105,15 @@ def binary_code(value):
def to_code(config): def to_code(config):
for conf in config: for pin in gpio_output_pin_expression(config[CONF_PIN]):
for pin in gpio_output_pin_expression(conf[CONF_PIN]): yield
yield rhs = App.make_remote_transmitter_component(pin)
rhs = App.make_remote_transmitter_component(pin) transmitter = Pvariable(config[CONF_ID], rhs)
transmitter = Pvariable(conf[CONF_ID], rhs)
if CONF_CARRIER_DUTY_PERCENT in conf: if CONF_CARRIER_DUTY_PERCENT in config:
add(transmitter.set_carrier_duty_percent(conf[CONF_CARRIER_DUTY_PERCENT])) add(transmitter.set_carrier_duty_percent(config[CONF_CARRIER_DUTY_PERCENT]))
setup_component(transmitter, conf) setup_component(transmitter, config)
BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER' BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER'

View File

@ -4,11 +4,12 @@ from esphomeyaml import automation
from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id from esphomeyaml.automation import ACTION_REGISTRY, maybe_simple_id
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID from esphomeyaml.const import CONF_ID
from esphomeyaml.helpers import NoArg, Pvariable, TemplateArguments, esphomelib_ns, get_variable, \ from esphomeyaml.cpp_generator import Pvariable, get_variable
Trigger, Action from esphomeyaml.cpp_types import Action, NoArg, Trigger, esphomelib_ns
Script = esphomelib_ns.class_('Script', Trigger.template(NoArg)) Script = esphomelib_ns.class_('Script', Trigger.template(NoArg))
ScriptExecuteAction = esphomelib_ns.class_('ScriptExecuteAction', Action) ScriptExecuteAction = esphomelib_ns.class_('ScriptExecuteAction', Action)
ScriptStopAction = esphomelib_ns.class_('ScriptStopAction', Action)
CONFIG_SCHEMA = automation.validate_automation({ CONFIG_SCHEMA = automation.validate_automation({
vol.Required(CONF_ID): cv.declare_variable_id(Script), vol.Required(CONF_ID): cv.declare_variable_id(Script),
@ -28,10 +29,24 @@ SCRIPT_EXECUTE_ACTION_SCHEMA = maybe_simple_id({
@ACTION_REGISTRY.register(CONF_SCRIPT_EXECUTE, SCRIPT_EXECUTE_ACTION_SCHEMA) @ACTION_REGISTRY.register(CONF_SCRIPT_EXECUTE, SCRIPT_EXECUTE_ACTION_SCHEMA)
def script_execute_action_to_code(config, action_id, arg_type): def script_execute_action_to_code(config, action_id, arg_type, template_arg):
template_arg = TemplateArguments(arg_type)
for var in get_variable(config[CONF_ID]): for var in get_variable(config[CONF_ID]):
yield None yield None
rhs = var.make_execute_action(template_arg) rhs = var.make_execute_action(template_arg)
type = ScriptExecuteAction.template(arg_type) type = ScriptExecuteAction.template(arg_type)
yield Pvariable(action_id, rhs, type=type) yield Pvariable(action_id, rhs, type=type)
CONF_SCRIPT_STOP = 'script.stop'
SCRIPT_STOP_ACTION_SCHEMA = maybe_simple_id({
vol.Required(CONF_ID): cv.use_variable_id(Script),
})
@ACTION_REGISTRY.register(CONF_SCRIPT_STOP, SCRIPT_STOP_ACTION_SCHEMA)
def script_stop_action_to_code(config, action_id, arg_type, template_arg):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_stop_action(template_arg)
type = ScriptStopAction.template(arg_type)
yield Pvariable(action_id, rhs, type=type)

View File

@ -1,7 +1,9 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml import automation from esphomeyaml import automation
from esphomeyaml.automation import CONDITION_REGISTRY
from esphomeyaml.components import mqtt from esphomeyaml.components import mqtt
from esphomeyaml.components.mqtt import setup_mqtt_component
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \ from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \
CONF_DEBOUNCE, CONF_DELTA, CONF_EXPIRE_AFTER, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, \ CONF_DEBOUNCE, CONF_DELTA, CONF_EXPIRE_AFTER, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, \
@ -10,9 +12,11 @@ from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CO
CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \ CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \
CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, \ CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, \
CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE
from esphomeyaml.helpers import App, ArrayInitializer, Component, Nameable, PollingComponent, \ from esphomeyaml.core import CORE
Pvariable, Trigger, add, add_job, esphomelib_ns, float_, process_lambda, setup_mqtt_component, \ from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, add, process_lambda, \
templatable templatable, get_variable
from esphomeyaml.cpp_types import App, Component, Nameable, PollingComponent, Trigger, \
esphomelib_ns, float_
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
@ -37,9 +41,9 @@ FILTER_KEYS = [CONF_OFFSET, CONF_MULTIPLY, CONF_FILTER_OUT, CONF_FILTER_NAN,
CONF_THROTTLE, CONF_DELTA, CONF_UNIQUE, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR] CONF_THROTTLE, CONF_DELTA, CONF_UNIQUE, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR]
FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
vol.Optional(CONF_OFFSET): vol.Coerce(float), vol.Optional(CONF_OFFSET): cv.float_,
vol.Optional(CONF_MULTIPLY): vol.Coerce(float), vol.Optional(CONF_MULTIPLY): cv.float_,
vol.Optional(CONF_FILTER_OUT): vol.Coerce(float), vol.Optional(CONF_FILTER_OUT): cv.float_,
vol.Optional(CONF_FILTER_NAN): None, vol.Optional(CONF_FILTER_NAN): None,
vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({ vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({
vol.Required(CONF_WINDOW_SIZE): cv.positive_not_null_int, vol.Required(CONF_WINDOW_SIZE): cv.positive_not_null_int,
@ -52,7 +56,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
}), }),
vol.Optional(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_LAMBDA): cv.lambda_,
vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds, vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds,
vol.Optional(CONF_DELTA): vol.Coerce(float), vol.Optional(CONF_DELTA): cv.float_,
vol.Optional(CONF_UNIQUE): None, vol.Optional(CONF_UNIQUE): None,
vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds, vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds,
vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds, vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds,
@ -62,6 +66,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({
# Base # Base
sensor_ns = esphomelib_ns.namespace('sensor') sensor_ns = esphomelib_ns.namespace('sensor')
Sensor = sensor_ns.class_('Sensor', Nameable) Sensor = sensor_ns.class_('Sensor', Nameable)
SensorPtr = Sensor.operator('ptr')
MQTTSensorComponent = sensor_ns.class_('MQTTSensorComponent', mqtt.MQTTComponent) MQTTSensorComponent = sensor_ns.class_('MQTTSensorComponent', mqtt.MQTTComponent)
PollingSensorComponent = sensor_ns.class_('PollingSensorComponent', PollingComponent, Sensor) PollingSensorComponent = sensor_ns.class_('PollingSensorComponent', PollingComponent, Sensor)
@ -71,7 +76,7 @@ EmptyPollingParentSensor = sensor_ns.class_('EmptyPollingParentSensor', EmptySen
# Triggers # Triggers
SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', Trigger.template(float_)) SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', Trigger.template(float_))
SensorRawStateTrigger = sensor_ns.class_('SensorRawStateTrigger', Trigger.template(float_)) SensorRawStateTrigger = sensor_ns.class_('SensorRawStateTrigger', Trigger.template(float_))
ValueRangeTrigger = sensor_ns.class_('ValueRangeTrigger', Trigger.template(float_)) ValueRangeTrigger = sensor_ns.class_('ValueRangeTrigger', Trigger.template(float_), Component)
# Filters # Filters
Filter = sensor_ns.class_('Filter') Filter = sensor_ns.class_('Filter')
@ -88,6 +93,7 @@ HeartbeatFilter = sensor_ns.class_('HeartbeatFilter', Filter, Component)
DeltaFilter = sensor_ns.class_('DeltaFilter', Filter) DeltaFilter = sensor_ns.class_('DeltaFilter', Filter)
OrFilter = sensor_ns.class_('OrFilter', Filter) OrFilter = sensor_ns.class_('OrFilter', Filter)
UniqueFilter = sensor_ns.class_('UniqueFilter', Filter) UniqueFilter = sensor_ns.class_('UniqueFilter', Filter)
SensorInRangeCondition = sensor_ns.class_('SensorInRangeCondition', Filter)
SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent), cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTSensorComponent),
@ -104,8 +110,8 @@ SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
}), }),
vol.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation({ vol.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation({
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ValueRangeTrigger), cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ValueRangeTrigger),
vol.Optional(CONF_ABOVE): vol.Coerce(float), vol.Optional(CONF_ABOVE): cv.float_,
vol.Optional(CONF_BELOW): vol.Coerce(float), vol.Optional(CONF_BELOW): cv.float_,
}, cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)), }, cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)),
}) })
@ -186,13 +192,12 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
for conf in config.get(CONF_ON_VALUE_RANGE, []): for conf in config.get(CONF_ON_VALUE_RANGE, []):
rhs = sensor_var.make_value_range_trigger() rhs = sensor_var.make_value_range_trigger()
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
add(App.register_component(trigger))
if CONF_ABOVE in conf: if CONF_ABOVE in conf:
template_ = None
for template_ in templatable(conf[CONF_ABOVE], float_, float_): for template_ in templatable(conf[CONF_ABOVE], float_, float_):
yield yield
add(trigger.set_min(template_)) add(trigger.set_min(template_))
if CONF_BELOW in conf: if CONF_BELOW in conf:
template_ = None
for template_ in templatable(conf[CONF_BELOW], float_, float_): for template_ in templatable(conf[CONF_BELOW], float_, float_):
yield yield
add(trigger.set_max(template_)) add(trigger.set_max(template_))
@ -209,19 +214,43 @@ def setup_sensor_core_(sensor_var, mqtt_var, config):
def setup_sensor(sensor_obj, mqtt_obj, config): def setup_sensor(sensor_obj, mqtt_obj, config):
sensor_var = Pvariable(config[CONF_ID], sensor_obj, has_side_effects=False) 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) mqtt_var = Pvariable(config[CONF_MQTT_ID], mqtt_obj, has_side_effects=False)
add_job(setup_sensor_core_, sensor_var, mqtt_var, config) CORE.add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
def register_sensor(var, config): def register_sensor(var, config):
sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True) sensor_var = Pvariable(config[CONF_ID], var, has_side_effects=True)
rhs = App.register_sensor(sensor_var) rhs = App.register_sensor(sensor_var)
mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True) mqtt_var = Pvariable(config[CONF_MQTT_ID], rhs, has_side_effects=True)
add_job(setup_sensor_core_, sensor_var, mqtt_var, config) CORE.add_job(setup_sensor_core_, sensor_var, mqtt_var, config)
BUILD_FLAGS = '-DUSE_SENSOR' BUILD_FLAGS = '-DUSE_SENSOR'
CONF_SENSOR_IN_RANGE = 'sensor.in_range'
SENSOR_IN_RANGE_CONDITION_SCHEMA = vol.All({
vol.Required(CONF_ID): cv.use_variable_id(Sensor),
vol.Optional(CONF_ABOVE): cv.float_,
vol.Optional(CONF_BELOW): cv.float_,
}, cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))
@CONDITION_REGISTRY.register(CONF_SENSOR_IN_RANGE, SENSOR_IN_RANGE_CONDITION_SCHEMA)
def sensor_in_range_to_code(config, condition_id, arg_type, template_arg):
for var in get_variable(config[CONF_ID]):
yield None
rhs = var.make_sensor_in_range_condition(template_arg)
type = SensorInRangeCondition.template(arg_type)
cond = Pvariable(condition_id, rhs, type=type)
if CONF_ABOVE in config:
add(cond.set_min(config[CONF_ABOVE]))
if CONF_BELOW in config:
add(cond.set_max(config[CONF_BELOW]))
yield cond
def core_to_hass_config(data, config): def core_to_hass_config(data, config):
ret = mqtt.build_hass_config(data, 'sensor', config, include_state=True, include_command=False) ret = mqtt.build_hass_config(data, 'sensor', config, include_state=True, include_command=False)
if ret is None: if ret is None:

View File

@ -1,11 +1,13 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml import pins from esphomeyaml import pins
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ATTENUATION, CONF_MAKE_ID, CONF_NAME, CONF_PIN, \ from esphomeyaml.const import CONF_ATTENUATION, CONF_MAKE_ID, CONF_NAME, CONF_PIN, \
CONF_UPDATE_INTERVAL CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, add, global_ns, variable, setup_component from esphomeyaml.cpp_generator import add, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Application, global_ns
ATTENUATION_MODES = { ATTENUATION_MODES = {
'0db': global_ns.ADC_0db, '0db': global_ns.ADC_0db,
@ -60,3 +62,9 @@ def required_build_flags(config):
def to_hass_config(data, config): def to_hass_config(data, config):
return sensor.core_to_hass_config(data, config) return sensor.core_to_hass_config(data, config)
def includes(config):
if config[CONF_PIN] == 'VCC':
return 'ADC_MODE(ADC_VCC);'
return None

View File

@ -1,11 +1,11 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
from esphomeyaml.components.ads1115 import ADS1115Component from esphomeyaml.components.ads1115 import ADS1115Component
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADS1115_ID, CONF_GAIN, CONF_MULTIPLEXER, CONF_NAME, \ from esphomeyaml.const import CONF_ADS1115_ID, CONF_GAIN, CONF_MULTIPLEXER, CONF_NAME, \
CONF_UPDATE_INTERVAL CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import get_variable from esphomeyaml.cpp_generator import get_variable
DEPENDENCIES = ['ads1115'] DEPENDENCIES = ['ads1115']
@ -59,7 +59,6 @@ PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({
def to_code(config): def to_code(config):
hub = None
for hub in get_variable(config[CONF_ADS1115_ID]): for hub in get_variable(config[CONF_ADS1115_ID]):
yield yield

View File

@ -1,10 +1,12 @@
import voluptuous as vol import voluptuous as vol
from esphomeyaml.components import i2c, sensor
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor, i2c
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_RESOLUTION, \ from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_RESOLUTION, \
CONF_UPDATE_INTERVAL CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, add, variable, setup_component from esphomeyaml.cpp_generator import add, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Application
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -1,11 +1,12 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \ from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \
make_address_array make_address_array
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME
from esphomeyaml.helpers import get_variable, esphomelib_ns from esphomeyaml.cpp_generator import get_variable
from esphomeyaml.cpp_types import esphomelib_ns
DEPENDENCIES = ['esp32_ble_tracker'] DEPENDENCIES = ['esp32_ble_tracker']

View File

@ -4,7 +4,9 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, CONF_IIR_FILTER, CONF_MAKE_ID, \ 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 CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, add, variable, setup_component from esphomeyaml.cpp_generator import variable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, App
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -6,7 +6,9 @@ from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ADDRESS, CONF_GAS_RESISTANCE, CONF_HUMIDITY, CONF_IIR_FILTER, \ from esphomeyaml.const import CONF_ADDRESS, CONF_GAS_RESISTANCE, CONF_HUMIDITY, CONF_IIR_FILTER, \
CONF_MAKE_ID, CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, \ CONF_MAKE_ID, CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, \
CONF_UPDATE_INTERVAL, CONF_HEATER, CONF_DURATION CONF_UPDATE_INTERVAL, CONF_HEATER, CONF_DURATION
from esphomeyaml.helpers import App, Application, add, variable, setup_component from esphomeyaml.cpp_generator import variable, add
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, App
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -4,7 +4,9 @@ import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \ from esphomeyaml.const import CONF_ADDRESS, CONF_MAKE_ID, CONF_NAME, CONF_PRESSURE, \
CONF_TEMPERATURE, CONF_UPDATE_INTERVAL CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, HexIntLiteral, add, variable, setup_component from esphomeyaml.cpp_generator import variable, add, HexIntLiteral
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import Application, App
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -1,10 +1,12 @@
import voluptuous as vol import voluptuous as vol
import esphomeyaml.config_validation as cv
from esphomeyaml.components import sensor from esphomeyaml.components import sensor
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ADDRESS, CONF_IIR_FILTER, CONF_MAKE_ID, \ from esphomeyaml.const import CONF_ADDRESS, CONF_IIR_FILTER, CONF_MAKE_ID, \
CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL CONF_NAME, CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
from esphomeyaml.helpers import App, Application, add, variable, setup_component from esphomeyaml.cpp_generator import add, variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, Application
DEPENDENCIES = ['i2c'] DEPENDENCIES = ['i2c']

View File

@ -5,7 +5,9 @@ from esphomeyaml.components.uart import UARTComponent
import esphomeyaml.config_validation as cv import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_CURRENT, CONF_ID, CONF_NAME, CONF_POWER, CONF_UART_ID, \ from esphomeyaml.const import CONF_CURRENT, CONF_ID, CONF_NAME, CONF_POWER, CONF_UART_ID, \
CONF_UPDATE_INTERVAL, CONF_VOLTAGE CONF_UPDATE_INTERVAL, CONF_VOLTAGE
from esphomeyaml.helpers import App, PollingComponent, Pvariable, get_variable, setup_component from esphomeyaml.cpp_generator import Pvariable, get_variable
from esphomeyaml.cpp_helpers import setup_component
from esphomeyaml.cpp_types import App, PollingComponent
DEPENDENCIES = ['uart'] DEPENDENCIES = ['uart']

View File

@ -0,0 +1,35 @@
import voluptuous as vol
from esphomeyaml.components import sensor
import esphomeyaml.config_validation as cv
from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_SENSORS
from esphomeyaml.cpp_generator import process_lambda, variable
from esphomeyaml.cpp_types import std_vector
CustomSensorConstructor = sensor.sensor_ns.class_('CustomSensorConstructor')
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(CustomSensorConstructor),
vol.Required(CONF_LAMBDA): cv.lambda_,
vol.Required(CONF_SENSORS): vol.All(cv.ensure_list, [sensor.SENSOR_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(sensor.Sensor),
})]),
})
def to_code(config):
for template_ in process_lambda(config[CONF_LAMBDA], [],
return_type=std_vector.template(sensor.SensorPtr)):
yield
rhs = CustomSensorConstructor(template_)
custom = variable(config[CONF_ID], rhs)
for i, sens in enumerate(config[CONF_SENSORS]):
sensor.register_sensor(custom.get_sensor(i), sens)
BUILD_FLAGS = '-DUSE_CUSTOM_SENSOR'
def to_hass_config(data, config):
return [sensor.core_to_hass_config(data, sens) for sens in config[CONF_SENSORS]]

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