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