mirror of
https://github.com/esphome/esphome.git
synced 2025-03-15 07:08:20 +00:00
Merge pull request #10 from esphome/dev
update sx1509 with remote dev branch
This commit is contained in:
commit
7c3403bf9f
185
.gitlab-ci.yml
185
.gitlab-ci.yml
@ -3,6 +3,8 @@
|
|||||||
variables:
|
variables:
|
||||||
DOCKER_DRIVER: overlay2
|
DOCKER_DRIVER: overlay2
|
||||||
DOCKER_HOST: tcp://docker:2375/
|
DOCKER_HOST: tcp://docker:2375/
|
||||||
|
BASE_VERSION: '1.5.1'
|
||||||
|
TZ: UTC
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- lint
|
- lint
|
||||||
@ -10,23 +12,20 @@ stages:
|
|||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
.lint: &lint
|
.lint: &lint
|
||||||
image: esphome/esphome-base-amd64
|
image: esphome/esphome-lint:latest
|
||||||
stage: lint
|
stage: lint
|
||||||
before_script:
|
before_script:
|
||||||
- pip install -e .
|
- script/setup
|
||||||
- pip install flake8==3.6.0 pylint==1.9.4 pillow
|
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
.test: &test
|
.test: &test
|
||||||
image: esphome/esphome-base-amd64
|
image: esphome/esphome-lint:latest
|
||||||
stage: test
|
stage: test
|
||||||
before_script:
|
before_script:
|
||||||
- pip install -e .
|
- script/setup
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
variables:
|
|
||||||
TZ: UTC
|
|
||||||
|
|
||||||
.docker-base: &docker-base
|
.docker-base: &docker-base
|
||||||
image: esphome/esphome-base-builder
|
image: esphome/esphome-base-builder
|
||||||
@ -41,11 +40,11 @@ stages:
|
|||||||
|
|
||||||
- |
|
- |
|
||||||
if [[ "${IS_HASSIO}" == "YES" ]]; then
|
if [[ "${IS_HASSIO}" == "YES" ]]; then
|
||||||
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.5.1
|
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:${BASE_VERSION}
|
||||||
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
|
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
|
||||||
DOCKERFILE=docker/Dockerfile.hassio
|
DOCKERFILE=docker/Dockerfile.hassio
|
||||||
else
|
else
|
||||||
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.5.1
|
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:${BASE_VERSION}
|
||||||
if [[ "${BUILD_ARCH}" == "amd64" ]]; then
|
if [[ "${BUILD_ARCH}" == "amd64" ]]; then
|
||||||
BUILD_TO=esphome/esphome
|
BUILD_TO=esphome/esphome
|
||||||
else
|
else
|
||||||
@ -94,15 +93,32 @@ stages:
|
|||||||
- docker
|
- docker
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
|
||||||
flake8:
|
lint-custom:
|
||||||
<<: *lint
|
<<: *lint
|
||||||
script:
|
script:
|
||||||
- flake8 esphome
|
- script/ci-custom.py
|
||||||
|
|
||||||
pylint:
|
lint-python:
|
||||||
<<: *lint
|
<<: *lint
|
||||||
script:
|
script:
|
||||||
- pylint esphome
|
- script/lint-python
|
||||||
|
|
||||||
|
lint-tidy:
|
||||||
|
<<: *lint
|
||||||
|
script:
|
||||||
|
- pio init --ide atom
|
||||||
|
- |
|
||||||
|
if ! patch -R -p0 -s -f --dry-run <script/.neopixelbus.patch; then
|
||||||
|
patch -p0 < script/.neopixelbus.patch
|
||||||
|
fi
|
||||||
|
- script/clang-tidy --all-headers --fix
|
||||||
|
- script/ci-suggest-changes
|
||||||
|
|
||||||
|
lint-format:
|
||||||
|
<<: *lint
|
||||||
|
script:
|
||||||
|
- script/clang-format -i
|
||||||
|
- script/ci-suggest-changes
|
||||||
|
|
||||||
test1:
|
test1:
|
||||||
<<: *test
|
<<: *test
|
||||||
@ -120,16 +136,12 @@ test3:
|
|||||||
- esphome tests/test3.yaml compile
|
- esphome tests/test3.yaml compile
|
||||||
|
|
||||||
.deploy-pypi: &deploy-pypi
|
.deploy-pypi: &deploy-pypi
|
||||||
|
<<: *lint
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: python:2.7
|
|
||||||
before_script:
|
|
||||||
- pip install -e .
|
|
||||||
- pip install twine
|
|
||||||
script:
|
script:
|
||||||
- python setup.py sdist bdist_wheel
|
- pip install twine wheel
|
||||||
- twine upload dist/*
|
- python setup.py sdist bdist_wheel
|
||||||
tags:
|
- twine upload dist/*
|
||||||
- docker
|
|
||||||
|
|
||||||
deploy-release:pypi:
|
deploy-release:pypi:
|
||||||
<<: *deploy-pypi
|
<<: *deploy-pypi
|
||||||
@ -148,77 +160,64 @@ deploy-beta:pypi:
|
|||||||
.latest: &latest
|
.latest: &latest
|
||||||
<<: *docker-base
|
<<: *docker-base
|
||||||
only:
|
only:
|
||||||
- /^v([0-9\.]+)$/
|
- /^v([0-9\.]+)$/
|
||||||
except:
|
except:
|
||||||
- branches
|
- branches
|
||||||
|
|
||||||
.latest-vars: &latest-vars
|
|
||||||
RELEASE: YES
|
|
||||||
LATEST: YES
|
|
||||||
# Also push to beta tag
|
|
||||||
BETA: YES
|
|
||||||
|
|
||||||
.beta: &beta
|
.beta: &beta
|
||||||
<<: *docker-base
|
<<: *docker-base
|
||||||
only:
|
only:
|
||||||
- /^v([0-9\.]+b\d+)$/
|
- /^v([0-9\.]+b\d+)$/
|
||||||
except:
|
except:
|
||||||
- branches
|
- branches
|
||||||
|
|
||||||
.beta-vars: &beta-vars
|
|
||||||
RELEASE: YES
|
|
||||||
BETA: YES
|
|
||||||
|
|
||||||
.dev: &dev
|
.dev: &dev
|
||||||
<<: *docker-base
|
<<: *docker-base
|
||||||
only:
|
only:
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
.dev-vars: &dev-vars
|
aarch64-beta-docker:
|
||||||
DEV: YES
|
<<: *beta
|
||||||
|
variables:
|
||||||
#aarch64-beta-docker:
|
BETA: "YES"
|
||||||
# <<: *beta
|
BUILD_ARCH: aarch64
|
||||||
# variables:
|
IS_HASSIO: "NO"
|
||||||
# BETA: "YES"
|
RELEASE: "YES"
|
||||||
# BUILD_ARCH: aarch64
|
aarch64-beta-hassio:
|
||||||
# IS_HASSIO: "NO"
|
<<: *beta
|
||||||
# RELEASE: "YES"
|
variables:
|
||||||
#aarch64-beta-hassio:
|
BETA: "YES"
|
||||||
# <<: *beta
|
BUILD_ARCH: aarch64
|
||||||
# variables:
|
IS_HASSIO: "YES"
|
||||||
# BETA: "YES"
|
RELEASE: "YES"
|
||||||
# BUILD_ARCH: aarch64
|
aarch64-dev-docker:
|
||||||
# IS_HASSIO: "YES"
|
<<: *dev
|
||||||
# RELEASE: "YES"
|
variables:
|
||||||
#aarch64-dev-docker:
|
BUILD_ARCH: aarch64
|
||||||
# <<: *dev
|
DEV: "YES"
|
||||||
# variables:
|
IS_HASSIO: "NO"
|
||||||
# BUILD_ARCH: aarch64
|
aarch64-dev-hassio:
|
||||||
# DEV: "YES"
|
<<: *dev
|
||||||
# IS_HASSIO: "NO"
|
variables:
|
||||||
#aarch64-dev-hassio:
|
BUILD_ARCH: aarch64
|
||||||
# <<: *dev
|
DEV: "YES"
|
||||||
# variables:
|
IS_HASSIO: "YES"
|
||||||
# BUILD_ARCH: aarch64
|
aarch64-latest-docker:
|
||||||
# DEV: "YES"
|
<<: *latest
|
||||||
# IS_HASSIO: "YES"
|
variables:
|
||||||
#aarch64-latest-docker:
|
BETA: "YES"
|
||||||
# <<: *latest
|
BUILD_ARCH: aarch64
|
||||||
# variables:
|
IS_HASSIO: "NO"
|
||||||
# BETA: "YES"
|
LATEST: "YES"
|
||||||
# BUILD_ARCH: aarch64
|
RELEASE: "YES"
|
||||||
# IS_HASSIO: "NO"
|
aarch64-latest-hassio:
|
||||||
# LATEST: "YES"
|
<<: *latest
|
||||||
# RELEASE: "YES"
|
variables:
|
||||||
#aarch64-latest-hassio:
|
BETA: "YES"
|
||||||
# <<: *latest
|
BUILD_ARCH: aarch64
|
||||||
# variables:
|
IS_HASSIO: "YES"
|
||||||
# BETA: "YES"
|
LATEST: "YES"
|
||||||
# BUILD_ARCH: aarch64
|
RELEASE: "YES"
|
||||||
# IS_HASSIO: "YES"
|
|
||||||
# LATEST: "YES"
|
|
||||||
# RELEASE: "YES"
|
|
||||||
amd64-beta-docker:
|
amd64-beta-docker:
|
||||||
<<: *beta
|
<<: *beta
|
||||||
variables:
|
variables:
|
||||||
@ -261,45 +260,45 @@ amd64-latest-hassio:
|
|||||||
IS_HASSIO: "YES"
|
IS_HASSIO: "YES"
|
||||||
LATEST: "YES"
|
LATEST: "YES"
|
||||||
RELEASE: "YES"
|
RELEASE: "YES"
|
||||||
armhf-beta-docker:
|
armv7-beta-docker:
|
||||||
<<: *beta
|
<<: *beta
|
||||||
variables:
|
variables:
|
||||||
BETA: "YES"
|
BETA: "YES"
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
IS_HASSIO: "NO"
|
IS_HASSIO: "NO"
|
||||||
RELEASE: "YES"
|
RELEASE: "YES"
|
||||||
armhf-beta-hassio:
|
armv7-beta-hassio:
|
||||||
<<: *beta
|
<<: *beta
|
||||||
variables:
|
variables:
|
||||||
BETA: "YES"
|
BETA: "YES"
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
IS_HASSIO: "YES"
|
IS_HASSIO: "YES"
|
||||||
RELEASE: "YES"
|
RELEASE: "YES"
|
||||||
armhf-dev-docker:
|
armv7-dev-docker:
|
||||||
<<: *dev
|
<<: *dev
|
||||||
variables:
|
variables:
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
DEV: "YES"
|
DEV: "YES"
|
||||||
IS_HASSIO: "NO"
|
IS_HASSIO: "NO"
|
||||||
armhf-dev-hassio:
|
armv7-dev-hassio:
|
||||||
<<: *dev
|
<<: *dev
|
||||||
variables:
|
variables:
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
DEV: "YES"
|
DEV: "YES"
|
||||||
IS_HASSIO: "YES"
|
IS_HASSIO: "YES"
|
||||||
armhf-latest-docker:
|
armv7-latest-docker:
|
||||||
<<: *latest
|
<<: *latest
|
||||||
variables:
|
variables:
|
||||||
BETA: "YES"
|
BETA: "YES"
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
IS_HASSIO: "NO"
|
IS_HASSIO: "NO"
|
||||||
LATEST: "YES"
|
LATEST: "YES"
|
||||||
RELEASE: "YES"
|
RELEASE: "YES"
|
||||||
armhf-latest-hassio:
|
armv7-latest-hassio:
|
||||||
<<: *latest
|
<<: *latest
|
||||||
variables:
|
variables:
|
||||||
BETA: "YES"
|
BETA: "YES"
|
||||||
BUILD_ARCH: armhf
|
BUILD_ARCH: armv7
|
||||||
IS_HASSIO: "YES"
|
IS_HASSIO: "YES"
|
||||||
LATEST: "YES"
|
LATEST: "YES"
|
||||||
RELEASE: "YES"
|
RELEASE: "YES"
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
FROM python:2.7
|
FROM esphome/esphome-base-amd64:1.5.1
|
||||||
|
|
||||||
COPY requirements.txt /requirements.txt
|
RUN \
|
||||||
|
apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
clang-format-7 \
|
||||||
|
clang-tidy-7 \
|
||||||
|
patch \
|
||||||
|
&& rm -rf \
|
||||||
|
/tmp/* \
|
||||||
|
/var/{cache,log}/* \
|
||||||
|
/var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN pip install -r /requirements.txt && \
|
COPY requirements_test.txt /requirements_test.txt
|
||||||
pip install flake8==3.6.0 pylint==1.9.4 pillow
|
RUN pip2 install -r /requirements_test.txt
|
||||||
|
|
||||||
|
VOLUME ["/esphome"]
|
||||||
|
WORKDIR /esphome
|
||||||
|
@ -127,7 +127,10 @@ def wrap_to_code(name, comp):
|
|||||||
def wrapped(conf):
|
def wrapped(conf):
|
||||||
cg.add(cg.LineComment(u"{}:".format(name)))
|
cg.add(cg.LineComment(u"{}:".format(name)))
|
||||||
if comp.config_schema is not None:
|
if comp.config_schema is not None:
|
||||||
cg.add(cg.LineComment(indent(yaml_util.dump(conf).decode('utf-8'))))
|
conf_str = yaml_util.dump(conf)
|
||||||
|
if IS_PY2:
|
||||||
|
conf_str = conf_str.decode('utf-8')
|
||||||
|
cg.add(cg.LineComment(indent(conf_str)))
|
||||||
yield coro(conf)
|
yield coro(conf)
|
||||||
|
|
||||||
return wrapped
|
return wrapped
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/adc/adc_sensor.h"
|
#include "adc_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#ifdef USE_ADC_SENSOR_VCC
|
#ifdef USE_ADC_SENSOR_VCC
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor, voltage_sampler
|
from esphome.components import sensor, voltage_sampler
|
||||||
from esphome.components.ads1115 import ADS1115Component
|
|
||||||
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
|
from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID
|
||||||
from esphome.py_compat import string_types
|
from esphome.py_compat import string_types
|
||||||
from . import ads1115_ns
|
from . import ads1115_ns, ADS1115Component
|
||||||
|
|
||||||
DEPENDENCIES = ['ads1115']
|
DEPENDENCIES = ['ads1115']
|
||||||
|
|
||||||
|
0
esphome/components/am2320/__init__.py
Normal file
0
esphome/components/am2320/__init__.py
Normal file
107
esphome/components/am2320/am2320.cpp
Normal file
107
esphome/components/am2320/am2320.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Implementation based on:
|
||||||
|
// - ESPEasy: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P034_DHT12.ino
|
||||||
|
// - DHT12_sensor_library: https://github.com/xreef/DHT12_sensor_library/blob/master/DHT12.cpp
|
||||||
|
// - Arduino - AM2320: https://github.com/EngDial/AM2320/blob/master/src/AM2320.cpp
|
||||||
|
|
||||||
|
#include "am2320.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace am2320 {
|
||||||
|
|
||||||
|
static const char *TAG = "am2320";
|
||||||
|
|
||||||
|
// ---=== Calc CRC16 ===---
|
||||||
|
uint16_t crc_16(uint8_t *ptr, uint8_t length) {
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
uint8_t i;
|
||||||
|
//------------------------------
|
||||||
|
while (length--) {
|
||||||
|
crc ^= *ptr++;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
if ((crc & 0x01) != 0) {
|
||||||
|
crc >>= 1;
|
||||||
|
crc ^= 0xA001;
|
||||||
|
} else
|
||||||
|
crc >>= 1;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AM2320Component::update() {
|
||||||
|
uint8_t data[8];
|
||||||
|
data[0] = 0;
|
||||||
|
data[1] = 4;
|
||||||
|
if (!this->read_data_(data)) {
|
||||||
|
this->status_set_warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float temperature = (((data[4] & 0x7F) << 8) + data[5]) / 10.0;
|
||||||
|
temperature = (data[4] & 0x80) ? -temperature : temperature;
|
||||||
|
float humidity = ((data[2] << 8) + data[3]) / 10.0;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temperature, humidity);
|
||||||
|
if (this->temperature_sensor_ != nullptr)
|
||||||
|
this->temperature_sensor_->publish_state(temperature);
|
||||||
|
if (this->humidity_sensor_ != nullptr)
|
||||||
|
this->humidity_sensor_->publish_state(humidity);
|
||||||
|
this->status_clear_warning();
|
||||||
|
}
|
||||||
|
void AM2320Component::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up AM2320...");
|
||||||
|
uint8_t data[8];
|
||||||
|
data[0] = 0;
|
||||||
|
data[1] = 4;
|
||||||
|
if (!this->read_data_(data)) {
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void AM2320Component::dump_config() {
|
||||||
|
ESP_LOGD(TAG, "AM2320:");
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
if (this->is_failed()) {
|
||||||
|
ESP_LOGE(TAG, "Communication with AM2320 failed!");
|
||||||
|
}
|
||||||
|
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
|
||||||
|
}
|
||||||
|
float AM2320Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
bool AM2320Component::read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion) {
|
||||||
|
if (!this->write_bytes(a_register, data, 2)) {
|
||||||
|
ESP_LOGW(TAG, "Writing bytes for AM2320 failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversion > 0)
|
||||||
|
delay(conversion);
|
||||||
|
return this->parent_->raw_receive(this->address_, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM2320Component::read_data_(uint8_t *data) {
|
||||||
|
// Wake up
|
||||||
|
this->write_bytes(0, data, 0);
|
||||||
|
|
||||||
|
// Write instruction 3, 2 bytes, get 8 bytes back (2 preamble, 2 bytes temperature, 2 bytes humidity, 2 bytes CRC)
|
||||||
|
if (!this->read_bytes_(3, data, 8, 2)) {
|
||||||
|
ESP_LOGW(TAG, "Updating AM2320 failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t checksum;
|
||||||
|
|
||||||
|
checksum = data[7] << 8;
|
||||||
|
checksum += data[6];
|
||||||
|
|
||||||
|
if (crc_16(data, 6) != checksum) {
|
||||||
|
ESP_LOGW(TAG, "AM2320 Checksum invalid!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace am2320
|
||||||
|
} // namespace esphome
|
29
esphome/components/am2320/am2320.h
Normal file
29
esphome/components/am2320/am2320.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace am2320 {
|
||||||
|
|
||||||
|
class AM2320Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
|
public:
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||||
|
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool read_data_(uint8_t *data);
|
||||||
|
bool read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion = 0);
|
||||||
|
|
||||||
|
sensor::Sensor *temperature_sensor_;
|
||||||
|
sensor::Sensor *humidity_sensor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace am2320
|
||||||
|
} // namespace esphome
|
30
esphome/components/am2320/sensor.py
Normal file
30
esphome/components/am2320/sensor.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c, sensor
|
||||||
|
from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, \
|
||||||
|
UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT
|
||||||
|
|
||||||
|
DEPENDENCIES = ['i2c']
|
||||||
|
|
||||||
|
am2320_ns = cg.esphome_ns.namespace('am2320')
|
||||||
|
AM2320Component = am2320_ns.class_('AM2320Component', cg.PollingComponent, i2c.I2CDevice)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
|
cv.GenerateID(): cv.declare_id(AM2320Component),
|
||||||
|
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1),
|
||||||
|
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1),
|
||||||
|
}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5C))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
yield i2c.register_i2c_device(var, config)
|
||||||
|
|
||||||
|
if CONF_TEMPERATURE in config:
|
||||||
|
sens = yield sensor.new_sensor(config[CONF_TEMPERATURE])
|
||||||
|
cg.add(var.set_temperature_sensor(sens))
|
||||||
|
|
||||||
|
if CONF_HUMIDITY in config:
|
||||||
|
sens = yield sensor.new_sensor(config[CONF_HUMIDITY])
|
||||||
|
cg.add(var.set_humidity_sensor(sens))
|
@ -7,7 +7,7 @@ from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \
|
|||||||
CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR
|
CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR
|
||||||
|
|
||||||
bang_bang_ns = cg.esphome_ns.namespace('bang_bang')
|
bang_bang_ns = cg.esphome_ns.namespace('bang_bang')
|
||||||
BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.Climate)
|
BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.Climate, cg.Component)
|
||||||
BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig')
|
BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig')
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
|
CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "binary_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "esphome/components/binary_sensor/filter.h"
|
#include "filter.h"
|
||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "binary_sensor.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ namespace climate {
|
|||||||
const char *climate_mode_to_string(ClimateMode mode) {
|
const char *climate_mode_to_string(ClimateMode mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CLIMATE_MODE_OFF:
|
case CLIMATE_MODE_OFF:
|
||||||
return "off";
|
return "OFF";
|
||||||
case CLIMATE_MODE_AUTO:
|
case CLIMATE_MODE_AUTO:
|
||||||
return "auto";
|
return "AUTO";
|
||||||
case CLIMATE_MODE_COOL:
|
case CLIMATE_MODE_COOL:
|
||||||
return "cool";
|
return "COOL";
|
||||||
case CLIMATE_MODE_HEAT:
|
case CLIMATE_MODE_HEAT:
|
||||||
return "heat";
|
return "HEAT";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
0
esphome/components/coolix/__init__.py
Normal file
0
esphome/components/coolix/__init__.py
Normal file
36
esphome/components/coolix/climate.py
Normal file
36
esphome/components/coolix/climate.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import climate, remote_transmitter, sensor
|
||||||
|
from esphome.const import CONF_ID, CONF_SENSOR
|
||||||
|
|
||||||
|
AUTO_LOAD = ['sensor']
|
||||||
|
|
||||||
|
coolix_ns = cg.esphome_ns.namespace('coolix')
|
||||||
|
CoolixClimate = coolix_ns.class_('CoolixClimate', climate.Climate, cg.Component)
|
||||||
|
|
||||||
|
CONF_TRANSMITTER_ID = 'transmitter_id'
|
||||||
|
CONF_SUPPORTS_HEAT = 'supports_heat'
|
||||||
|
CONF_SUPPORTS_COOL = 'supports_cool'
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_id(CoolixClimate),
|
||||||
|
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent),
|
||||||
|
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||||
|
}).extend(cv.COMPONENT_SCHEMA))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
yield climate.register_climate(var, config)
|
||||||
|
|
||||||
|
cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
|
||||||
|
cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
|
||||||
|
if CONF_SENSOR in config:
|
||||||
|
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_sensor(sens))
|
||||||
|
|
||||||
|
transmitter = yield cg.get_variable(config[CONF_TRANSMITTER_ID])
|
||||||
|
cg.add(var.set_transmitter(transmitter))
|
170
esphome/components/coolix/coolix.cpp
Normal file
170
esphome/components/coolix/coolix.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include "coolix.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace coolix {
|
||||||
|
|
||||||
|
static const char *TAG = "coolix.climate";
|
||||||
|
|
||||||
|
const uint32_t COOLIX_OFF = 0xB27BE0;
|
||||||
|
// On, 25C, Mode: Auto, Fan: Auto, Zone Follow: Off, Sensor Temp: Ignore.
|
||||||
|
const uint32_t COOLIX_DEFAULT_STATE = 0xB2BFC8;
|
||||||
|
const uint32_t COOLIX_DEFAULT_STATE_AUTO_24_FAN = 0xB21F48;
|
||||||
|
const uint8_t COOLIX_COOL = 0b00;
|
||||||
|
const uint8_t COOLIX_DRY = 0b01;
|
||||||
|
const uint8_t COOLIX_AUTO = 0b10;
|
||||||
|
const uint8_t COOLIX_HEAT = 0b11;
|
||||||
|
const uint8_t COOLIX_FAN = 4; // Synthetic.
|
||||||
|
const uint32_t COOLIX_MODE_MASK = 0b000000000000000000001100; // 0xC
|
||||||
|
|
||||||
|
// Temperature
|
||||||
|
const uint8_t COOLIX_TEMP_MIN = 17; // Celsius
|
||||||
|
const uint8_t COOLIX_TEMP_MAX = 30; // Celsius
|
||||||
|
const uint8_t COOLIX_TEMP_RANGE = COOLIX_TEMP_MAX - COOLIX_TEMP_MIN + 1;
|
||||||
|
const uint8_t COOLIX_FAN_TEMP_CODE = 0b1110; // Part of Fan Mode.
|
||||||
|
const uint32_t COOLIX_TEMP_MASK = 0b11110000;
|
||||||
|
const uint8_t COOLIX_TEMP_MAP[COOLIX_TEMP_RANGE] = {
|
||||||
|
0b0000, // 17C
|
||||||
|
0b0001, // 18c
|
||||||
|
0b0011, // 19C
|
||||||
|
0b0010, // 20C
|
||||||
|
0b0110, // 21C
|
||||||
|
0b0111, // 22C
|
||||||
|
0b0101, // 23C
|
||||||
|
0b0100, // 24C
|
||||||
|
0b1100, // 25C
|
||||||
|
0b1101, // 26C
|
||||||
|
0b1001, // 27C
|
||||||
|
0b1000, // 28C
|
||||||
|
0b1010, // 29C
|
||||||
|
0b1011 // 30C
|
||||||
|
};
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
// Pulse parms are *50-100 for the Mark and *50+100 for the space
|
||||||
|
// First MARK is the one after the long gap
|
||||||
|
// pulse parameters in usec
|
||||||
|
const uint16_t COOLIX_TICK = 560; // Approximately 21 cycles at 38kHz
|
||||||
|
const uint16_t COOLIX_BIT_MARK_TICKS = 1;
|
||||||
|
const uint16_t COOLIX_BIT_MARK = COOLIX_BIT_MARK_TICKS * COOLIX_TICK;
|
||||||
|
const uint16_t COOLIX_ONE_SPACE_TICKS = 3;
|
||||||
|
const uint16_t COOLIX_ONE_SPACE = COOLIX_ONE_SPACE_TICKS * COOLIX_TICK;
|
||||||
|
const uint16_t COOLIX_ZERO_SPACE_TICKS = 1;
|
||||||
|
const uint16_t COOLIX_ZERO_SPACE = COOLIX_ZERO_SPACE_TICKS * COOLIX_TICK;
|
||||||
|
const uint16_t COOLIX_HEADER_MARK_TICKS = 8;
|
||||||
|
const uint16_t COOLIX_HEADER_MARK = COOLIX_HEADER_MARK_TICKS * COOLIX_TICK;
|
||||||
|
const uint16_t COOLIX_HEADER_SPACE_TICKS = 8;
|
||||||
|
const uint16_t COOLIX_HEADER_SPACE = COOLIX_HEADER_SPACE_TICKS * COOLIX_TICK;
|
||||||
|
const uint16_t COOLIX_MIN_GAP_TICKS = COOLIX_HEADER_MARK_TICKS + COOLIX_ZERO_SPACE_TICKS;
|
||||||
|
const uint16_t COOLIX_MIN_GAP = COOLIX_MIN_GAP_TICKS * COOLIX_TICK;
|
||||||
|
|
||||||
|
const uint16_t COOLIX_BITS = 24;
|
||||||
|
|
||||||
|
climate::ClimateTraits CoolixClimate::traits() {
|
||||||
|
auto traits = climate::ClimateTraits();
|
||||||
|
traits.set_supports_current_temperature(this->sensor_ != nullptr);
|
||||||
|
traits.set_supports_auto_mode(true);
|
||||||
|
traits.set_supports_cool_mode(this->supports_cool_);
|
||||||
|
traits.set_supports_heat_mode(this->supports_heat_);
|
||||||
|
traits.set_supports_two_point_target_temperature(false);
|
||||||
|
traits.set_supports_away(false);
|
||||||
|
traits.set_visual_min_temperature(17);
|
||||||
|
traits.set_visual_max_temperature(30);
|
||||||
|
traits.set_visual_temperature_step(1);
|
||||||
|
return traits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoolixClimate::setup() {
|
||||||
|
if (this->sensor_) {
|
||||||
|
this->sensor_->add_on_state_callback([this](float state) {
|
||||||
|
this->current_temperature = state;
|
||||||
|
// current temperature changed, publish state
|
||||||
|
this->publish_state();
|
||||||
|
});
|
||||||
|
this->current_temperature = this->sensor_->state;
|
||||||
|
} else
|
||||||
|
this->current_temperature = NAN;
|
||||||
|
// restore set points
|
||||||
|
auto restore = this->restore_state_();
|
||||||
|
if (restore.has_value()) {
|
||||||
|
restore->apply(this);
|
||||||
|
} else {
|
||||||
|
// restore from defaults
|
||||||
|
this->mode = climate::CLIMATE_MODE_AUTO;
|
||||||
|
// initialize target temperature to some value so that it's not NAN
|
||||||
|
this->target_temperature = roundf(this->current_temperature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoolixClimate::control(const climate::ClimateCall &call) {
|
||||||
|
if (call.get_mode().has_value())
|
||||||
|
this->mode = *call.get_mode();
|
||||||
|
if (call.get_target_temperature().has_value())
|
||||||
|
this->target_temperature = *call.get_target_temperature();
|
||||||
|
|
||||||
|
this->transmit_state_();
|
||||||
|
this->publish_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoolixClimate::transmit_state_() {
|
||||||
|
uint32_t remote_state;
|
||||||
|
|
||||||
|
switch (this->mode) {
|
||||||
|
case climate::CLIMATE_MODE_COOL:
|
||||||
|
remote_state = (COOLIX_DEFAULT_STATE & ~COOLIX_MODE_MASK) | (COOLIX_COOL << 2);
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_HEAT:
|
||||||
|
remote_state = (COOLIX_DEFAULT_STATE & ~COOLIX_MODE_MASK) | (COOLIX_HEAT << 2);
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_AUTO:
|
||||||
|
remote_state = COOLIX_DEFAULT_STATE_AUTO_24_FAN;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_OFF:
|
||||||
|
default:
|
||||||
|
remote_state = COOLIX_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this->mode != climate::CLIMATE_MODE_OFF) {
|
||||||
|
auto temp = (uint8_t) roundf(clamp(this->target_temperature, COOLIX_TEMP_MIN, COOLIX_TEMP_MAX));
|
||||||
|
remote_state &= ~COOLIX_TEMP_MASK; // Clear the old temp.
|
||||||
|
remote_state |= (COOLIX_TEMP_MAP[temp - COOLIX_TEMP_MIN] << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "Sending coolix code: %u", remote_state);
|
||||||
|
|
||||||
|
auto transmit = this->transmitter_->transmit();
|
||||||
|
auto data = transmit.get_data();
|
||||||
|
|
||||||
|
data->set_carrier_frequency(38000);
|
||||||
|
uint16_t repeat = 1;
|
||||||
|
for (uint16_t r = 0; r <= repeat; r++) {
|
||||||
|
// Header
|
||||||
|
data->mark(COOLIX_HEADER_MARK);
|
||||||
|
data->space(COOLIX_HEADER_SPACE);
|
||||||
|
// Data
|
||||||
|
// Break data into byte segments, starting at the Most Significant
|
||||||
|
// Byte. Each byte then being sent normal, then followed inverted.
|
||||||
|
for (uint16_t i = 8; i <= COOLIX_BITS; i += 8) {
|
||||||
|
// Grab a bytes worth of data.
|
||||||
|
uint8_t segment = (remote_state >> (COOLIX_BITS - i)) & 0xFF;
|
||||||
|
// Normal
|
||||||
|
for (uint64_t mask = 1ULL << 7; mask; mask >>= 1) {
|
||||||
|
data->mark(COOLIX_BIT_MARK);
|
||||||
|
data->space((segment & mask) ? COOLIX_ONE_SPACE : COOLIX_ZERO_SPACE);
|
||||||
|
}
|
||||||
|
// Inverted
|
||||||
|
for (uint64_t mask = 1ULL << 7; mask; mask >>= 1) {
|
||||||
|
data->mark(COOLIX_BIT_MARK);
|
||||||
|
data->space(!(segment & mask) ? COOLIX_ONE_SPACE : COOLIX_ZERO_SPACE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Footer
|
||||||
|
data->mark(COOLIX_BIT_MARK);
|
||||||
|
data->space(COOLIX_MIN_GAP); // Pause before repeating
|
||||||
|
}
|
||||||
|
|
||||||
|
transmit.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace coolix
|
||||||
|
} // namespace esphome
|
40
esphome/components/coolix/coolix.h
Normal file
40
esphome/components/coolix/coolix.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/components/climate/climate.h"
|
||||||
|
#include "esphome/components/remote_base/remote_base.h"
|
||||||
|
#include "esphome/components/remote_transmitter/remote_transmitter.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace coolix {
|
||||||
|
|
||||||
|
class CoolixClimate : public climate::Climate, public Component {
|
||||||
|
public:
|
||||||
|
void setup() override;
|
||||||
|
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
|
||||||
|
this->transmitter_ = transmitter;
|
||||||
|
}
|
||||||
|
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||||
|
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||||
|
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Override control to change settings of the climate device.
|
||||||
|
void control(const climate::ClimateCall &call) override;
|
||||||
|
/// Return the traits of this controller.
|
||||||
|
climate::ClimateTraits traits() override;
|
||||||
|
|
||||||
|
/// Transmit via IR the state of this climate controller.
|
||||||
|
void transmit_state_();
|
||||||
|
|
||||||
|
bool supports_cool_{true};
|
||||||
|
bool supports_heat_{true};
|
||||||
|
|
||||||
|
remote_transmitter::RemoteTransmitterComponent *transmitter_;
|
||||||
|
sensor::Sensor *sensor_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace coolix
|
||||||
|
} // namespace esphome
|
@ -19,7 +19,8 @@ void DeepSleepComponent::setup() {
|
|||||||
void DeepSleepComponent::dump_config() {
|
void DeepSleepComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
|
ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
|
||||||
if (this->sleep_duration_.has_value()) {
|
if (this->sleep_duration_.has_value()) {
|
||||||
ESP_LOGCONFIG(TAG, " Sleep Duration: %llu ms", *this->sleep_duration_ / 1000);
|
uint32_t duration = *this->sleep_duration_ / 1000;
|
||||||
|
ESP_LOGCONFIG(TAG, " Sleep Duration: %u ms", duration);
|
||||||
}
|
}
|
||||||
if (this->run_duration_.has_value()) {
|
if (this->run_duration_.has_value()) {
|
||||||
ESP_LOGCONFIG(TAG, " Run Duration: %u ms", *this->run_duration_);
|
ESP_LOGCONFIG(TAG, " Run Duration: %u ms", *this->run_duration_);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/dht/dht.h"
|
#include "dht.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import binary_sensor
|
from esphome.components import binary_sensor
|
||||||
from esphome.components.esp32_touch import ESP32TouchComponent
|
|
||||||
from esphome.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32, CONF_ID
|
from esphome.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32, CONF_ID
|
||||||
from esphome.pins import validate_gpio_pin
|
from esphome.pins import validate_gpio_pin
|
||||||
from . import esp32_touch_ns
|
from . import esp32_touch_ns, ESP32TouchComponent
|
||||||
|
|
||||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||||
DEPENDENCIES = ['esp32_touch']
|
DEPENDENCIES = ['esp32_touch']
|
||||||
|
@ -67,7 +67,7 @@ CONFIG_SCHEMA = cv.All(cv.Schema({
|
|||||||
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
|
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
|
||||||
|
|
||||||
cv.Optional('hostname'): cv.invalid("The hostname option has been removed in 1.11.0"),
|
cv.Optional('hostname'): cv.invalid("The hostname option has been removed in 1.11.0"),
|
||||||
}), validate)
|
}).extend(cv.COMPONENT_SCHEMA), validate)
|
||||||
|
|
||||||
|
|
||||||
def manual_ip(config):
|
def manual_ip(config):
|
||||||
@ -84,6 +84,7 @@ def manual_ip(config):
|
|||||||
@coroutine_with_priority(60.0)
|
@coroutine_with_priority(60.0)
|
||||||
def to_code(config):
|
def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
|
||||||
cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
cg.add(var.set_phy_addr(config[CONF_PHY_ADDR]))
|
||||||
cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
cg.add(var.set_mdc_pin(config[CONF_MDC_PIN]))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/gpio/binary_sensor/gpio_binary_sensor.h"
|
#include "gpio_binary_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/gpio/switch/gpio_switch.h"
|
#include "gpio_switch.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -6,7 +6,8 @@ from .. import homeassistant_ns
|
|||||||
|
|
||||||
DEPENDENCIES = ['api']
|
DEPENDENCIES = ['api']
|
||||||
HomeassistantBinarySensor = homeassistant_ns.class_('HomeassistantBinarySensor',
|
HomeassistantBinarySensor = homeassistant_ns.class_('HomeassistantBinarySensor',
|
||||||
binary_sensor.BinarySensor)
|
binary_sensor.BinarySensor,
|
||||||
|
cg.Component)
|
||||||
|
|
||||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||||
cv.GenerateID(): cv.declare_id(HomeassistantBinarySensor),
|
cv.GenerateID(): cv.declare_id(HomeassistantBinarySensor),
|
||||||
|
@ -6,7 +6,8 @@ from .. import homeassistant_ns
|
|||||||
|
|
||||||
DEPENDENCIES = ['api']
|
DEPENDENCIES = ['api']
|
||||||
|
|
||||||
HomeassistantSensor = homeassistant_ns.class_('HomeassistantSensor', sensor.Sensor)
|
HomeassistantSensor = homeassistant_ns.class_('HomeassistantSensor', sensor.Sensor,
|
||||||
|
cg.Component)
|
||||||
|
|
||||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({
|
||||||
cv.GenerateID(): cv.declare_id(HomeassistantSensor),
|
cv.GenerateID(): cv.declare_id(HomeassistantSensor),
|
||||||
|
@ -71,3 +71,5 @@ def to_code(config):
|
|||||||
yield output.register_output(var, config)
|
yield output.register_output(var, config)
|
||||||
if CONF_CHANNEL in config:
|
if CONF_CHANNEL in config:
|
||||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||||
|
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
|
||||||
|
cg.add(var.set_bit_depth(config[CONF_BIT_DEPTH]))
|
||||||
|
@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.components import mqtt, power_supply
|
from esphome.components import mqtt, power_supply
|
||||||
from esphome.const import CONF_COLOR_CORRECT, \
|
from esphome.const import CONF_COLOR_CORRECT, \
|
||||||
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_ID, \
|
CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_ID, \
|
||||||
CONF_INTERNAL, CONF_NAME, CONF_MQTT_ID, CONF_POWER_SUPPLY
|
CONF_INTERNAL, CONF_NAME, CONF_MQTT_ID, CONF_POWER_SUPPLY, CONF_RESTORE_MODE
|
||||||
from esphome.core import coroutine, coroutine_with_priority
|
from esphome.core import coroutine, coroutine_with_priority
|
||||||
from .automation import light_control_to_code # noqa
|
from .automation import light_control_to_code # noqa
|
||||||
from .effects import validate_effects, BINARY_EFFECTS, \
|
from .effects import validate_effects, BINARY_EFFECTS, \
|
||||||
@ -12,9 +12,20 @@ from .types import ( # noqa
|
|||||||
LightState, AddressableLightState, light_ns, LightOutput, AddressableLight)
|
LightState, AddressableLightState, light_ns, LightOutput, AddressableLight)
|
||||||
|
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
|
|
||||||
|
LightRestoreMode = light_ns.enum('LightRestoreMode')
|
||||||
|
RESTORE_MODES = {
|
||||||
|
'RESTORE_DEFAULT_OFF': LightRestoreMode.LIGHT_RESTORE_DEFAULT_OFF,
|
||||||
|
'RESTORE_DEFAULT_ON': LightRestoreMode.LIGHT_RESTORE_DEFAULT_ON,
|
||||||
|
'ALWAYS_OFF': LightRestoreMode.LIGHT_ALWAYS_OFF,
|
||||||
|
'ALWAYS_ON': LightRestoreMode.LIGHT_ALWAYS_ON,
|
||||||
|
}
|
||||||
|
|
||||||
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({
|
||||||
cv.GenerateID(): cv.declare_id(LightState),
|
cv.GenerateID(): cv.declare_id(LightState),
|
||||||
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTJSONLightComponent),
|
cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTJSONLightComponent),
|
||||||
|
cv.Optional(CONF_RESTORE_MODE, default='restore_default_off'):
|
||||||
|
cv.enum(RESTORE_MODES, upper=True, space='_'),
|
||||||
})
|
})
|
||||||
|
|
||||||
BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend({
|
BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend({
|
||||||
@ -41,6 +52,7 @@ ADDRESSABLE_LIGHT_SCHEMA = RGB_LIGHT_SCHEMA.extend({
|
|||||||
|
|
||||||
@coroutine
|
@coroutine
|
||||||
def setup_light_core_(light_var, output_var, config):
|
def setup_light_core_(light_var, output_var, config):
|
||||||
|
cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||||
if CONF_INTERNAL in config:
|
if CONF_INTERNAL in config:
|
||||||
cg.add(light_var.set_internal(config[CONF_INTERNAL]))
|
cg.add(light_var.set_internal(config[CONF_INTERNAL]))
|
||||||
if CONF_DEFAULT_TRANSITION_LENGTH in config:
|
if CONF_DEFAULT_TRANSITION_LENGTH in config:
|
||||||
|
@ -4,7 +4,7 @@ from esphome import automation
|
|||||||
from esphome.const import CONF_NAME, CONF_LAMBDA, CONF_UPDATE_INTERVAL, CONF_TRANSITION_LENGTH, \
|
from esphome.const import CONF_NAME, CONF_LAMBDA, CONF_UPDATE_INTERVAL, CONF_TRANSITION_LENGTH, \
|
||||||
CONF_COLORS, CONF_STATE, CONF_DURATION, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, \
|
CONF_COLORS, CONF_STATE, CONF_DURATION, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, \
|
||||||
CONF_WHITE, CONF_ALPHA, CONF_INTENSITY, CONF_SPEED, CONF_WIDTH, CONF_NUM_LEDS, CONF_RANDOM, \
|
CONF_WHITE, CONF_ALPHA, CONF_INTENSITY, CONF_SPEED, CONF_WIDTH, CONF_NUM_LEDS, CONF_RANDOM, \
|
||||||
CONF_THEN
|
CONF_SEQUENCE
|
||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
from .types import LambdaLightEffect, RandomLightEffect, StrobeLightEffect, \
|
from .types import LambdaLightEffect, RandomLightEffect, StrobeLightEffect, \
|
||||||
StrobeLightEffectColor, LightColorValues, AddressableLightRef, AddressableLambdaLightEffect, \
|
StrobeLightEffectColor, LightColorValues, AddressableLightRef, AddressableLambdaLightEffect, \
|
||||||
@ -63,11 +63,11 @@ def lambda_effect_to_code(config, effect_id):
|
|||||||
|
|
||||||
|
|
||||||
@register_effect('automation', AutomationLightEffect, "Automation", {
|
@register_effect('automation', AutomationLightEffect, "Automation", {
|
||||||
cv.Required(CONF_THEN): automation.validate_automation(single=True),
|
cv.Required(CONF_SEQUENCE): automation.validate_automation(single=True),
|
||||||
})
|
})
|
||||||
def automation_effect_to_code(config, effect_id):
|
def automation_effect_to_code(config, effect_id):
|
||||||
var = yield cg.new_Pvariable(effect_id, config[CONF_NAME])
|
var = yield cg.new_Pvariable(effect_id, config[CONF_NAME])
|
||||||
yield automation.build_automation(var.get_trig(), [], config[CONF_THEN])
|
yield automation.build_automation(var.get_trig(), [], config[CONF_SEQUENCE])
|
||||||
yield var
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,12 +98,25 @@ void LightState::setup() {
|
|||||||
effect->init_internal(this);
|
effect->init_internal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rtc_ = global_preferences.make_preference<LightStateRTCState>(this->get_object_id_hash());
|
|
||||||
LightStateRTCState recovered{};
|
|
||||||
// Attempt to load from preferences, else fall back to default values from struct
|
|
||||||
this->rtc_.load(&recovered);
|
|
||||||
|
|
||||||
auto call = this->make_call();
|
auto call = this->make_call();
|
||||||
|
LightStateRTCState recovered{};
|
||||||
|
switch (this->restore_mode_) {
|
||||||
|
case LIGHT_RESTORE_DEFAULT_OFF:
|
||||||
|
case LIGHT_RESTORE_DEFAULT_ON:
|
||||||
|
this->rtc_ = global_preferences.make_preference<LightStateRTCState>(this->get_object_id_hash());
|
||||||
|
// Attempt to load from preferences, else fall back to default values from struct
|
||||||
|
if (!this->rtc_.load(&recovered)) {
|
||||||
|
recovered.state = this->restore_mode_ == LIGHT_RESTORE_DEFAULT_ON;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LIGHT_ALWAYS_OFF:
|
||||||
|
recovered.state = false;
|
||||||
|
break;
|
||||||
|
case LIGHT_ALWAYS_ON:
|
||||||
|
recovered.state = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
call.set_state(recovered.state);
|
call.set_state(recovered.state);
|
||||||
call.set_brightness_if_supported(recovered.brightness);
|
call.set_brightness_if_supported(recovered.brightness);
|
||||||
call.set_red_if_supported(recovered.red);
|
call.set_red_if_supported(recovered.red);
|
||||||
|
@ -160,6 +160,13 @@ class LightCall {
|
|||||||
bool save_{true};
|
bool save_{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LightRestoreMode {
|
||||||
|
LIGHT_RESTORE_DEFAULT_OFF,
|
||||||
|
LIGHT_RESTORE_DEFAULT_ON,
|
||||||
|
LIGHT_ALWAYS_OFF,
|
||||||
|
LIGHT_ALWAYS_ON,
|
||||||
|
};
|
||||||
|
|
||||||
/** This class represents the communication layer between the front-end MQTT layer and the
|
/** This class represents the communication layer between the front-end MQTT layer and the
|
||||||
* hardware output layer.
|
* hardware output layer.
|
||||||
*/
|
*/
|
||||||
@ -249,6 +256,7 @@ class LightState : public Nameable, public Component {
|
|||||||
/// Set the gamma correction factor
|
/// Set the gamma correction factor
|
||||||
void set_gamma_correct(float gamma_correct);
|
void set_gamma_correct(float gamma_correct);
|
||||||
float get_gamma_correct() const { return this->gamma_correct_; }
|
float get_gamma_correct() const { return this->gamma_correct_; }
|
||||||
|
void set_restore_mode(LightRestoreMode restore_mode) { restore_mode_ = restore_mode; }
|
||||||
|
|
||||||
const std::vector<LightEffect *> &get_effects() const;
|
const std::vector<LightEffect *> &get_effects() const;
|
||||||
|
|
||||||
@ -292,6 +300,8 @@ class LightState : public Nameable, public Component {
|
|||||||
|
|
||||||
/// Object used to store the persisted values of the light.
|
/// Object used to store the persisted values of the light.
|
||||||
ESPPreferenceObject rtc_;
|
ESPPreferenceObject rtc_;
|
||||||
|
/// Restore mode of the light.
|
||||||
|
LightRestoreMode restore_mode_;
|
||||||
/// Default transition length for all transitions in ms.
|
/// Default transition length for all transitions in ms.
|
||||||
uint32_t default_transition_length_{};
|
uint32_t default_transition_length_{};
|
||||||
/// Value for storing the index of the currently active effect. 0 if no effect is active
|
/// Value for storing the index of the currently active effect. 0 if no effect is active
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/logger/logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
|
@ -24,12 +24,12 @@ void MQTTClimateComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryC
|
|||||||
JsonArray &modes = root.createNestedArray("modes");
|
JsonArray &modes = root.createNestedArray("modes");
|
||||||
// sort array for nice UI in HA
|
// sort array for nice UI in HA
|
||||||
if (traits.supports_mode(CLIMATE_MODE_AUTO))
|
if (traits.supports_mode(CLIMATE_MODE_AUTO))
|
||||||
modes.add(climate_mode_to_string(CLIMATE_MODE_AUTO));
|
modes.add("auto");
|
||||||
modes.add(climate_mode_to_string(CLIMATE_MODE_OFF));
|
modes.add("off");
|
||||||
if (traits.supports_mode(CLIMATE_MODE_COOL))
|
if (traits.supports_mode(CLIMATE_MODE_COOL))
|
||||||
modes.add(climate_mode_to_string(CLIMATE_MODE_COOL));
|
modes.add("cool");
|
||||||
if (traits.supports_mode(CLIMATE_MODE_HEAT))
|
if (traits.supports_mode(CLIMATE_MODE_HEAT))
|
||||||
modes.add(climate_mode_to_string(CLIMATE_MODE_HEAT));
|
modes.add("heat");
|
||||||
|
|
||||||
if (traits.get_supports_two_point_target_temperature()) {
|
if (traits.get_supports_two_point_target_temperature()) {
|
||||||
// temperature_low_command_topic
|
// temperature_low_command_topic
|
||||||
|
@ -72,11 +72,13 @@ bool MQTTComponent::send_discovery_() {
|
|||||||
root["command_topic"] = this->get_command_topic_();
|
root["command_topic"] = this->get_command_topic_();
|
||||||
|
|
||||||
if (this->availability_ == nullptr) {
|
if (this->availability_ == nullptr) {
|
||||||
root["availability_topic"] = global_mqtt_client->get_availability().topic;
|
if (!global_mqtt_client->get_availability().topic.empty()) {
|
||||||
if (global_mqtt_client->get_availability().payload_available != "online")
|
root["availability_topic"] = global_mqtt_client->get_availability().topic;
|
||||||
root["payload_available"] = global_mqtt_client->get_availability().payload_available;
|
if (global_mqtt_client->get_availability().payload_available != "online")
|
||||||
if (global_mqtt_client->get_availability().payload_not_available != "offline")
|
root["payload_available"] = global_mqtt_client->get_availability().payload_available;
|
||||||
root["payload_not_available"] = global_mqtt_client->get_availability().payload_not_available;
|
if (global_mqtt_client->get_availability().payload_not_available != "offline")
|
||||||
|
root["payload_not_available"] = global_mqtt_client->get_availability().payload_not_available;
|
||||||
|
}
|
||||||
} else if (!this->availability_->topic.empty()) {
|
} else if (!this->availability_->topic.empty()) {
|
||||||
root["availability_topic"] = this->availability_->topic;
|
root["availability_topic"] = this->availability_->topic;
|
||||||
if (this->availability_->payload_available != "online")
|
if (this->availability_->payload_available != "online")
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import output
|
from esphome.components import output
|
||||||
from esphome.components.my9231 import MY9231OutputComponent
|
|
||||||
from esphome.const import CONF_CHANNEL, CONF_ID
|
from esphome.const import CONF_CHANNEL, CONF_ID
|
||||||
|
from . import MY9231OutputComponent
|
||||||
|
|
||||||
DEPENDENCIES = ['my9231']
|
DEPENDENCIES = ['my9231']
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* Set the text of a component to a static string.
|
* Set the text of a component to a static string.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param text The static text to set.
|
* @param text The static text to set.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_text("textview", "Hello World!");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will set the `txt` property of the component `textview` to `Hello World`.
|
||||||
*/
|
*/
|
||||||
void set_component_text(const char *component, const char *text);
|
void set_component_text(const char *component, const char *text);
|
||||||
/**
|
/**
|
||||||
@ -30,18 +37,41 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param format The printf-style format string.
|
* @param format The printf-style format string.
|
||||||
* @param ... The arguments to the format.
|
* @param ... The arguments to the format.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_text_printf("textview", "The uptime is: %.0f", id(uptime_sensor).state);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the text on the component named `textview` to `The uptime is:` Then the value of `uptime_sensor`.
|
||||||
|
* with zero decimals of accuracy (whole number).
|
||||||
|
* For example when `uptime_sensor` = 506, then, `The uptime is: 506` will be displayed.
|
||||||
*/
|
*/
|
||||||
void set_component_text_printf(const char *component, const char *format, ...) __attribute__((format(printf, 3, 4)));
|
void set_component_text_printf(const char *component, const char *format, ...) __attribute__((format(printf, 3, 4)));
|
||||||
/**
|
/**
|
||||||
* Set the integer value of a component
|
* Set the integer value of a component
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param value The value to set.
|
* @param value The value to set.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_value("gauge", 50);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the property `value` of the component `gauge` to 50.
|
||||||
*/
|
*/
|
||||||
void set_component_value(const char *component, int value);
|
void set_component_value(const char *component, int value);
|
||||||
/**
|
/**
|
||||||
* Set the picture of an image component.
|
* Set the picture of an image component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param value The picture name.
|
* @param value The picture name.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_picture("pic", "4");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the image of the component `pic` to the image with ID `4`.
|
||||||
*/
|
*/
|
||||||
void set_component_picture(const char *component, const char *picture) {
|
void set_component_picture(const char *component, const char *picture) {
|
||||||
this->send_command_printf("%s.val=%s", component, picture);
|
this->send_command_printf("%s.val=%s", component, picture);
|
||||||
@ -50,24 +80,61 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* Set the background color of a component.
|
* Set the background color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param color The color (as a string).
|
* @param color The color (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_background_color("button", "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the background color of the component `button` to blue.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_background_color(const char *component, const char *color);
|
void set_component_background_color(const char *component, const char *color);
|
||||||
/**
|
/**
|
||||||
* Set the pressed background color of a component.
|
* Set the pressed background color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param color The color (as a string).
|
* @param color The color (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_background_color("button", "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed background color of the component `button` to blue. This is the background color that
|
||||||
|
* is shown when the component is pressed. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
*/
|
*/
|
||||||
void set_component_pressed_background_color(const char *component, const char *color);
|
void set_component_pressed_background_color(const char *component, const char *color);
|
||||||
/**
|
/**
|
||||||
* Set the font color of a component.
|
* Set the font color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param color The color (as a string).
|
* @param color The color (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_font_color("textview", "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the font color of the component `textview` to a blue color.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_font_color(const char *component, const char *color);
|
void set_component_font_color(const char *component, const char *color);
|
||||||
/**
|
/**
|
||||||
* Set the pressed font color of a component.
|
* Set the pressed font color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param color The color (as a string).
|
* @param color The color (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_font_color("button", "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed font color of the component `button` to a blue color.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_pressed_font_color(const char *component, const char *color);
|
void set_component_pressed_font_color(const char *component, const char *color);
|
||||||
/**
|
/**
|
||||||
@ -75,12 +142,26 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_coordinates("pic", 55, 100);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will move the position of the component `pic` to the x coordinate `55` and y coordinate `100`.
|
||||||
*/
|
*/
|
||||||
void set_component_coordinates(const char *component, int x, int y);
|
void set_component_coordinates(const char *component, int x, int y);
|
||||||
/**
|
/**
|
||||||
* Set the font id for a component.
|
* Set the font id for a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
* @param font_id The ID of the font (number).
|
* @param font_id The ID of the font (number).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_font("textview", "3");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Changes the font of the component named `textveiw`. Font IDs are set in the Nextion Editor.
|
||||||
*/
|
*/
|
||||||
void set_component_font(const char *component, uint8_t font_id);
|
void set_component_font(const char *component, uint8_t font_id);
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
@ -94,26 +175,61 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
/**
|
/**
|
||||||
* Show the page with a given name.
|
* Show the page with a given name.
|
||||||
* @param page The name of the page.
|
* @param page The name of the page.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.goto_page("main");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Switches to the page named `main`. Pages are named in the Nextion Editor.
|
||||||
*/
|
*/
|
||||||
void goto_page(const char *page);
|
void goto_page(const char *page);
|
||||||
/**
|
/**
|
||||||
* Hide a component.
|
* Hide a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* hide_component("button");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Hides the component named `button`.
|
||||||
*/
|
*/
|
||||||
void hide_component(const char *component);
|
void hide_component(const char *component);
|
||||||
/**
|
/**
|
||||||
* Show a component.
|
* Show a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* show_component("button");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Shows the component named `button`.
|
||||||
*/
|
*/
|
||||||
void show_component(const char *component);
|
void show_component(const char *component);
|
||||||
/**
|
/**
|
||||||
* Enable touch for a component.
|
* Enable touch for a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* enable_component_touch("button");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Enables touch for component named `button`.
|
||||||
*/
|
*/
|
||||||
void enable_component_touch(const char *component);
|
void enable_component_touch(const char *component);
|
||||||
/**
|
/**
|
||||||
* Disable touch for a component.
|
* Disable touch for a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* disable_component_touch("button");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Disables touch for component named `button`.
|
||||||
*/
|
*/
|
||||||
void disable_component_touch(const char *component);
|
void disable_component_touch(const char *component);
|
||||||
/**
|
/**
|
||||||
@ -128,6 +244,13 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param picture_id The picture id.
|
* @param picture_id The picture id.
|
||||||
* @param x1 The x coordinate.
|
* @param x1 The x coordinate.
|
||||||
* @param y1 The y coordniate.
|
* @param y1 The y coordniate.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* display_picture(2, 15, 25);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Displays the picture who has the id `2` at the x coordinates `15` and y coordinates `25`.
|
||||||
*/
|
*/
|
||||||
void display_picture(int picture_id, int x_start, int y_start);
|
void display_picture(int picture_id, int x_start, int y_start);
|
||||||
/**
|
/**
|
||||||
@ -137,6 +260,15 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param width The width to draw.
|
* @param width The width to draw.
|
||||||
* @param height The height to draw.
|
* @param height The height to draw.
|
||||||
* @param color The color to draw with (as a string).
|
* @param color The color to draw with (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* fill_area(50, 50, 100, 100, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fills an area that starts at x coordiante `50` and y coordinate `50` with a height of `100` and width of `100` with
|
||||||
|
* the color of blue. Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to
|
||||||
|
* convert color codes to Nextion HMI colors
|
||||||
*/
|
*/
|
||||||
void fill_area(int x1, int y1, int width, int height, const char *color);
|
void fill_area(int x1, int y1, int width, int height, const char *color);
|
||||||
/**
|
/**
|
||||||
@ -146,6 +278,16 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param x2 The ending x coordinate.
|
* @param x2 The ending x coordinate.
|
||||||
* @param y2 The ending y coordinate.
|
* @param y2 The ending y coordinate.
|
||||||
* @param color The color to draw with (as a string).
|
* @param color The color to draw with (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.line(50, 50, 75, 75, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a line that starts at x coordinate `50` and y coordinate `50` and ends at x coordinate `75` and y coordinate
|
||||||
|
* `75` with the color of blue. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
*/
|
*/
|
||||||
void line(int x1, int y1, int x2, int y2, const char *color);
|
void line(int x1, int y1, int x2, int y2, const char *color);
|
||||||
/**
|
/**
|
||||||
@ -155,6 +297,16 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param width The width of the rectangle.
|
* @param width The width of the rectangle.
|
||||||
* @param height The height of the rectangle.
|
* @param height The height of the rectangle.
|
||||||
* @param color The color to draw with (as a string).
|
* @param color The color to draw with (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.rectangle(25, 35, 40, 50, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a outline of a rectangle that starts at x coordinate `25` and y coordinate `35` and has a width of `40` and a
|
||||||
|
* length of `50` with color of blue. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
*/
|
*/
|
||||||
void rectangle(int x1, int y1, int width, int height, const char *color);
|
void rectangle(int x1, int y1, int width, int height, const char *color);
|
||||||
/**
|
/**
|
||||||
@ -171,17 +323,41 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
|||||||
* @param center_y The center y coordinate.
|
* @param center_y The center y coordinate.
|
||||||
* @param radius The circle radius.
|
* @param radius The circle radius.
|
||||||
* @param color The color to draw with (as a string).
|
* @param color The color to draw with (as a string).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.filled_cricle(25, 25, 10, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a filled circle at the x cordinates `25` and y coordinate `25` with a radius of `10` with a color of blue.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void filled_circle(int center_x, int center_y, int radius, const char *color);
|
void filled_circle(int center_x, int center_y, int radius, const char *color);
|
||||||
|
|
||||||
/** Set the brightness of the backlight.
|
/** Set the brightness of the backlight.
|
||||||
*
|
*
|
||||||
* @param brightness The brightness, from 0 to 100.
|
* @param brightness The brightness, from 0 to 100.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_backlight_brightness(30);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Changes the brightness of the display to 30%.
|
||||||
*/
|
*/
|
||||||
void set_backlight_brightness(uint8_t brightness);
|
void set_backlight_brightness(uint8_t brightness);
|
||||||
/**
|
/**
|
||||||
* Set the touch sleep timeout of the display.
|
* Set the touch sleep timeout of the display.
|
||||||
* @param timeout Timeout in seconds.
|
* @param timeout Timeout in seconds.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_touch_sleep_timeout(30);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* After 30 seconds the display will go to sleep. Note: the display will only wakeup by a restart or by setting up
|
||||||
|
* `thup`.
|
||||||
*/
|
*/
|
||||||
void set_touch_sleep_timeout(uint16_t timeout);
|
void set_touch_sleep_timeout(uint16_t timeout);
|
||||||
|
|
||||||
|
0
esphome/components/ntc/__init__.py
Normal file
0
esphome/components/ntc/__init__.py
Normal file
31
esphome/components/ntc/ntc.cpp
Normal file
31
esphome/components/ntc/ntc.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "ntc.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ntc {
|
||||||
|
|
||||||
|
static const char *TAG = "ntc";
|
||||||
|
|
||||||
|
void NTC::setup() {
|
||||||
|
this->sensor_->add_on_state_callback([this](float value) { this->process_(value); });
|
||||||
|
if (this->sensor_->has_state())
|
||||||
|
this->process_(this->sensor_->state);
|
||||||
|
}
|
||||||
|
void NTC::dump_config() { LOG_SENSOR("", "NTC Sensor", this) }
|
||||||
|
float NTC::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
void NTC::process_(float value) {
|
||||||
|
if (isnan(value)) {
|
||||||
|
this->publish_state(NAN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float lr = logf(value);
|
||||||
|
float v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr;
|
||||||
|
float temp = 1 / v - 273.15f;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp);
|
||||||
|
this->publish_state(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ntc
|
||||||
|
} // namespace esphome
|
29
esphome/components/ntc/ntc.h
Normal file
29
esphome/components/ntc/ntc.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ntc {
|
||||||
|
|
||||||
|
class NTC : public Component, public sensor::Sensor {
|
||||||
|
public:
|
||||||
|
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
||||||
|
void set_a(float a) { a_ = a; }
|
||||||
|
void set_b(float b) { b_ = b; }
|
||||||
|
void set_c(float c) { c_ = c; }
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void process_(float value);
|
||||||
|
|
||||||
|
sensor::Sensor *sensor_;
|
||||||
|
float a_;
|
||||||
|
float b_;
|
||||||
|
float c_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ntc
|
||||||
|
} // namespace esphome
|
120
esphome/components/ntc/sensor.py
Normal file
120
esphome/components/ntc/sensor.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from math import log
|
||||||
|
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.const import UNIT_CELSIUS, ICON_THERMOMETER, CONF_SENSOR, CONF_TEMPERATURE, \
|
||||||
|
CONF_VALUE, CONF_CALIBRATION, CONF_ID
|
||||||
|
|
||||||
|
ntc_ns = cg.esphome_ns.namespace('ntc')
|
||||||
|
NTC = ntc_ns.class_('NTC', cg.Component, sensor.Sensor)
|
||||||
|
|
||||||
|
CONF_B_CONSTANT = 'b_constant'
|
||||||
|
CONF_REFERENCE_TEMPERATURE = 'reference_temperature'
|
||||||
|
CONF_REFERENCE_RESISTANCE = 'reference_resistance'
|
||||||
|
CONF_A = 'a'
|
||||||
|
CONF_B = 'b'
|
||||||
|
CONF_C = 'c'
|
||||||
|
ZERO_POINT = 273.15
|
||||||
|
|
||||||
|
|
||||||
|
def validate_calibration_parameter(value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return cv.Schema({
|
||||||
|
cv.Required(CONF_TEMPERATURE): cv.float_,
|
||||||
|
cv.Required(CONF_VALUE): cv.float_,
|
||||||
|
})
|
||||||
|
|
||||||
|
value = cv.string(value)
|
||||||
|
parts = value.split('->')
|
||||||
|
if len(parts) != 2:
|
||||||
|
raise cv.Invalid(u"Calibration parameter must be of form 3000 -> 23°C")
|
||||||
|
voltage = cv.resistance(parts[0].strip())
|
||||||
|
temperature = cv.temperature(parts[1].strip())
|
||||||
|
return validate_calibration_parameter({
|
||||||
|
CONF_TEMPERATURE: temperature,
|
||||||
|
CONF_VALUE: voltage,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def calc_steinhart_hart(value):
|
||||||
|
r1 = value[0][CONF_VALUE]
|
||||||
|
r2 = value[1][CONF_VALUE]
|
||||||
|
r3 = value[2][CONF_VALUE]
|
||||||
|
t1 = value[0][CONF_TEMPERATURE] + ZERO_POINT
|
||||||
|
t2 = value[1][CONF_TEMPERATURE] + ZERO_POINT
|
||||||
|
t3 = value[2][CONF_TEMPERATURE] + ZERO_POINT
|
||||||
|
|
||||||
|
l1 = log(r1)
|
||||||
|
l2 = log(r2)
|
||||||
|
l3 = log(r3)
|
||||||
|
|
||||||
|
y1 = 1/t1
|
||||||
|
y2 = 1/t2
|
||||||
|
y3 = 1/t3
|
||||||
|
|
||||||
|
g2 = (y2-y1)/(l2-l1)
|
||||||
|
g3 = (y3-y1)/(l3-l1)
|
||||||
|
|
||||||
|
c = (g3-g2)/(l3-l2) * 1/(l1+l2+l3)
|
||||||
|
b = g2 - c*(l1*l1 + l1*l2 + l2*l2)
|
||||||
|
a = y1 - (b + l1*l1*c) * l1
|
||||||
|
return a, b, c
|
||||||
|
|
||||||
|
|
||||||
|
def calc_b(value):
|
||||||
|
beta = value[CONF_B_CONSTANT]
|
||||||
|
t0 = value[CONF_REFERENCE_TEMPERATURE] + ZERO_POINT
|
||||||
|
r0 = value[CONF_REFERENCE_RESISTANCE]
|
||||||
|
|
||||||
|
a = (1/t0) - (1/beta) * log(r0)
|
||||||
|
b = 1/beta
|
||||||
|
c = 0
|
||||||
|
|
||||||
|
return a, b, c
|
||||||
|
|
||||||
|
|
||||||
|
def process_calibration(value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
value = cv.Schema({
|
||||||
|
cv.Required(CONF_B_CONSTANT): cv.float_,
|
||||||
|
cv.Required(CONF_REFERENCE_TEMPERATURE): cv.temperature,
|
||||||
|
cv.Required(CONF_REFERENCE_RESISTANCE): cv.resistance,
|
||||||
|
})(value)
|
||||||
|
a, b, c = calc_b(value)
|
||||||
|
elif isinstance(value, list):
|
||||||
|
if len(value) != 3:
|
||||||
|
raise cv.Invalid("Steinhart–Hart Calibration must consist of exactly three values")
|
||||||
|
value = cv.Schema([validate_calibration_parameter])(value)
|
||||||
|
a, b, c = calc_steinhart_hart(value)
|
||||||
|
else:
|
||||||
|
raise cv.Invalid("Calibration parameter accepts either a list for steinhart-hart "
|
||||||
|
"calibration, or mapping for b-constant calibration, "
|
||||||
|
"not {}".format(type(value)))
|
||||||
|
|
||||||
|
return {
|
||||||
|
CONF_A: a,
|
||||||
|
CONF_B: b,
|
||||||
|
CONF_C: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({
|
||||||
|
cv.GenerateID(): cv.declare_id(NTC),
|
||||||
|
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||||
|
cv.Required(CONF_CALIBRATION): process_calibration,
|
||||||
|
}).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
yield sensor.register_sensor(var, config)
|
||||||
|
|
||||||
|
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_sensor(sens))
|
||||||
|
calib = config[CONF_CALIBRATION]
|
||||||
|
cg.add(var.set_a(calib[CONF_A]))
|
||||||
|
cg.add(var.set_b(calib[CONF_B]))
|
||||||
|
cg.add(var.set_c(calib[CONF_C]))
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/ota/ota_component.h"
|
#include "ota_component.h"
|
||||||
|
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
@ -10,7 +10,7 @@ PulseWidthSensor = pulse_width_ns.class_('PulseWidthSensor', sensor.Sensor, cg.P
|
|||||||
|
|
||||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 3).extend({
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 3).extend({
|
||||||
cv.GenerateID(): cv.declare_id(PulseWidthSensor),
|
cv.GenerateID(): cv.declare_id(PulseWidthSensor),
|
||||||
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pullup_pin_schema,
|
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema,
|
||||||
pins.validate_has_interrupt),
|
pins.validate_has_interrupt),
|
||||||
}).extend(cv.polling_component_schema('60s'))
|
}).extend(cv.polling_component_schema('60s'))
|
||||||
|
|
||||||
|
0
esphome/components/resistance/__init__.py
Normal file
0
esphome/components/resistance/__init__.py
Normal file
42
esphome/components/resistance/resistance_sensor.cpp
Normal file
42
esphome/components/resistance/resistance_sensor.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "resistance_sensor.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace resistance {
|
||||||
|
|
||||||
|
static const char *TAG = "resistance";
|
||||||
|
|
||||||
|
void ResistanceSensor::dump_config() {
|
||||||
|
LOG_SENSOR("", "Resistance Sensor", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Configuration: %s", this->configuration_ == UPSTREAM ? "UPSTREAM" : "DOWNSTREAM");
|
||||||
|
ESP_LOGCONFIG(TAG, " Resistor: %.2fΩ", this->resistor_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Reference Voltage: %.1fV", this->reference_voltage_);
|
||||||
|
}
|
||||||
|
void ResistanceSensor::process_(float value) {
|
||||||
|
if (isnan(value)) {
|
||||||
|
this->publish_state(NAN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float res = 0;
|
||||||
|
switch (this->configuration_) {
|
||||||
|
case UPSTREAM:
|
||||||
|
if (value == 0.0f)
|
||||||
|
res = NAN;
|
||||||
|
else
|
||||||
|
res = (this->reference_voltage_ - value) / value;
|
||||||
|
break;
|
||||||
|
case DOWNSTREAM:
|
||||||
|
if (value == this->reference_voltage_)
|
||||||
|
res = NAN;
|
||||||
|
else
|
||||||
|
res = value / (this->reference_voltage_ - value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res *= this->resistor_;
|
||||||
|
ESP_LOGD(TAG, "'%s' - Resistance %.1fΩ", this->name_.c_str(), res);
|
||||||
|
this->publish_state(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace resistance
|
||||||
|
} // namespace esphome
|
38
esphome/components/resistance/resistance_sensor.h
Normal file
38
esphome/components/resistance/resistance_sensor.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace resistance {
|
||||||
|
|
||||||
|
enum ResistanceConfiguration {
|
||||||
|
UPSTREAM,
|
||||||
|
DOWNSTREAM,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResistanceSensor : public Component, public sensor::Sensor {
|
||||||
|
public:
|
||||||
|
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
||||||
|
void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; }
|
||||||
|
void set_resistor(float resistor) { resistor_ = resistor; }
|
||||||
|
void set_reference_voltage(float reference_voltage) { reference_voltage_ = reference_voltage; }
|
||||||
|
|
||||||
|
void setup() override {
|
||||||
|
this->sensor_->add_on_state_callback([this](float value) { this->process_(value); });
|
||||||
|
if (this->sensor_->has_state())
|
||||||
|
this->process_(this->sensor_->state);
|
||||||
|
}
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void process_(float value);
|
||||||
|
sensor::Sensor *sensor_;
|
||||||
|
ResistanceConfiguration configuration_;
|
||||||
|
float resistor_;
|
||||||
|
float reference_voltage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace resistance
|
||||||
|
} // namespace esphome
|
37
esphome/components/resistance/sensor.py
Normal file
37
esphome/components/resistance/sensor.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.const import CONF_SENSOR, UNIT_OHM, ICON_FLASH, CONF_ID
|
||||||
|
|
||||||
|
resistance_ns = cg.esphome_ns.namespace('resistance')
|
||||||
|
ResistanceSensor = resistance_ns.class_('ResistanceSensor', cg.Component, sensor.Sensor)
|
||||||
|
|
||||||
|
CONF_REFERENCE_VOLTAGE = 'reference_voltage'
|
||||||
|
CONF_CONFIGURATION = 'configuration'
|
||||||
|
CONF_RESISTOR = 'resistor'
|
||||||
|
|
||||||
|
ResistanceConfiguration = resistance_ns.enum('ResistanceConfiguration')
|
||||||
|
CONFIGURATIONS = {
|
||||||
|
'DOWNSTREAM': ResistanceConfiguration.DOWNSTREAM,
|
||||||
|
'UPSTREAM': ResistanceConfiguration.UPSTREAM,
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_OHM, ICON_FLASH, 1).extend({
|
||||||
|
cv.GenerateID(): cv.declare_id(ResistanceSensor),
|
||||||
|
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||||
|
cv.Required(CONF_CONFIGURATION): cv.enum(CONFIGURATIONS, upper=True),
|
||||||
|
cv.Required(CONF_RESISTOR): cv.resistance,
|
||||||
|
cv.Optional(CONF_REFERENCE_VOLTAGE, default='3.3V'): cv.voltage,
|
||||||
|
}).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
yield sensor.register_sensor(var, config)
|
||||||
|
|
||||||
|
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_sensor(sens))
|
||||||
|
cg.add(var.set_configuration(config[CONF_CONFIGURATION]))
|
||||||
|
cg.add(var.set_resistor(config[CONF_RESISTOR]))
|
||||||
|
cg.add(var.set_reference_voltage(config[CONF_REFERENCE_VOLTAGE]))
|
@ -1,5 +1,5 @@
|
|||||||
#include "esphome/components/sensor/filter.h"
|
#include "filter.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/sensor/sensor.h"
|
#include "sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "status_binary_sensor.h"
|
#include "status_binary_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/core/util.h"
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
|
||||||
#ifdef USE_MQTT
|
#ifdef USE_MQTT
|
||||||
#include "esphome/components/mqtt/mqtt_client.h"
|
#include "esphome/components/mqtt/mqtt_client.h"
|
||||||
@ -18,19 +19,16 @@ void StatusBinarySensor::loop() {
|
|||||||
bool status = network_is_connected();
|
bool status = network_is_connected();
|
||||||
#ifdef USE_MQTT
|
#ifdef USE_MQTT
|
||||||
if (mqtt::global_mqtt_client != nullptr) {
|
if (mqtt::global_mqtt_client != nullptr) {
|
||||||
status = mqtt::global_mqtt_client->is_connected();
|
status = status && mqtt::global_mqtt_client->is_connected();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_API
|
#ifdef USE_API
|
||||||
if (api::global_api_server != nullptr) {
|
if (api::global_api_server != nullptr) {
|
||||||
status = api::global_api_server->is_connected();
|
status = status && api::global_api_server->is_connected();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (this->last_status_ != status) {
|
this->publish_state(status);
|
||||||
this->publish_state(status);
|
|
||||||
this->last_status_ = status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void StatusBinarySensor::setup() { this->publish_state(false); }
|
void StatusBinarySensor::setup() { this->publish_state(false); }
|
||||||
void StatusBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "Status Binary Sensor", this); }
|
void StatusBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "Status Binary Sensor", this); }
|
||||||
|
@ -16,9 +16,6 @@ class StatusBinarySensor : public binary_sensor::BinarySensor, public Component
|
|||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
bool is_status_binary_sensor() const override { return true; }
|
bool is_status_binary_sensor() const override { return true; }
|
||||||
|
|
||||||
protected:
|
|
||||||
bool last_status_{false};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace status
|
} // namespace status
|
||||||
|
@ -83,13 +83,13 @@ def switch_toggle_to_code(config, action_id, template_arg, args):
|
|||||||
@automation.register_condition('switch.is_on', SwitchCondition, SWITCH_ACTION_SCHEMA)
|
@automation.register_condition('switch.is_on', SwitchCondition, SWITCH_ACTION_SCHEMA)
|
||||||
def switch_is_on_to_code(config, condition_id, template_arg, args):
|
def switch_is_on_to_code(config, condition_id, template_arg, args):
|
||||||
paren = yield cg.get_variable(config[CONF_ID])
|
paren = yield cg.get_variable(config[CONF_ID])
|
||||||
yield cg.new_Pvariable(condition_id, template_arg, paren)
|
yield cg.new_Pvariable(condition_id, template_arg, paren, True)
|
||||||
|
|
||||||
|
|
||||||
@automation.register_condition('switch.is_off', SwitchCondition, SWITCH_ACTION_SCHEMA)
|
@automation.register_condition('switch.is_off', SwitchCondition, SWITCH_ACTION_SCHEMA)
|
||||||
def switch_is_off_to_code(config, condition_id, template_arg, args):
|
def switch_is_off_to_code(config, condition_id, template_arg, args):
|
||||||
paren = yield cg.get_variable(config[CONF_ID])
|
paren = yield cg.get_variable(config[CONF_ID])
|
||||||
yield cg.new_Pvariable(condition_id, template_arg, paren)
|
yield cg.new_Pvariable(condition_id, template_arg, paren, False)
|
||||||
|
|
||||||
|
|
||||||
@coroutine_with_priority(100.0)
|
@coroutine_with_priority(100.0)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/switch/switch.h"
|
#include "switch.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
0
esphome/components/tcl112/__init__.py
Normal file
0
esphome/components/tcl112/__init__.py
Normal file
36
esphome/components/tcl112/climate.py
Normal file
36
esphome/components/tcl112/climate.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import climate, remote_transmitter, sensor
|
||||||
|
from esphome.const import CONF_ID, CONF_SENSOR
|
||||||
|
|
||||||
|
AUTO_LOAD = ['sensor']
|
||||||
|
|
||||||
|
tcl112_ns = cg.esphome_ns.namespace('tcl112')
|
||||||
|
Tcl112Climate = tcl112_ns.class_('Tcl112Climate', climate.Climate, cg.Component)
|
||||||
|
|
||||||
|
CONF_TRANSMITTER_ID = 'transmitter_id'
|
||||||
|
CONF_SUPPORTS_HEAT = 'supports_heat'
|
||||||
|
CONF_SUPPORTS_COOL = 'supports_cool'
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
|
||||||
|
cv.GenerateID(): cv.declare_id(Tcl112Climate),
|
||||||
|
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent),
|
||||||
|
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||||
|
}).extend(cv.COMPONENT_SCHEMA))
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
yield climate.register_climate(var, config)
|
||||||
|
|
||||||
|
cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
|
||||||
|
cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
|
||||||
|
if CONF_SENSOR in config:
|
||||||
|
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_sensor(sens))
|
||||||
|
|
||||||
|
transmitter = yield cg.get_variable(config[CONF_TRANSMITTER_ID])
|
||||||
|
cg.add(var.set_transmitter(transmitter))
|
152
esphome/components/tcl112/tcl112.cpp
Normal file
152
esphome/components/tcl112/tcl112.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include "tcl112.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace tcl112 {
|
||||||
|
|
||||||
|
static const char *TAG = "tcl112.climate";
|
||||||
|
|
||||||
|
const uint16_t TCL112_STATE_LENGTH = 14;
|
||||||
|
const uint16_t TCL112_BITS = TCL112_STATE_LENGTH * 8;
|
||||||
|
|
||||||
|
const uint8_t TCL112_HEAT = 1;
|
||||||
|
const uint8_t TCL112_DRY = 2;
|
||||||
|
const uint8_t TCL112_COOL = 3;
|
||||||
|
const uint8_t TCL112_FAN = 7;
|
||||||
|
const uint8_t TCL112_AUTO = 8;
|
||||||
|
|
||||||
|
const uint8_t TCL112_POWER_MASK = 0x04;
|
||||||
|
|
||||||
|
const uint8_t TCL112_HALF_DEGREE = 0b00100000;
|
||||||
|
const float TCL112_TEMP_MAX = 31.0;
|
||||||
|
const float TCL112_TEMP_MIN = 16.0;
|
||||||
|
|
||||||
|
const uint16_t TCL112_HEADER_MARK = 3000;
|
||||||
|
const uint16_t TCL112_HEADER_SPACE = 1650;
|
||||||
|
const uint16_t TCL112_BIT_MARK = 500;
|
||||||
|
const uint16_t TCL112_ONE_SPACE = 1050;
|
||||||
|
const uint16_t TCL112_ZERO_SPACE = 325;
|
||||||
|
const uint32_t TCL112_GAP = TCL112_HEADER_SPACE;
|
||||||
|
|
||||||
|
climate::ClimateTraits Tcl112Climate::traits() {
|
||||||
|
auto traits = climate::ClimateTraits();
|
||||||
|
traits.set_supports_current_temperature(this->sensor_ != nullptr);
|
||||||
|
traits.set_supports_auto_mode(true);
|
||||||
|
traits.set_supports_cool_mode(this->supports_cool_);
|
||||||
|
traits.set_supports_heat_mode(this->supports_heat_);
|
||||||
|
traits.set_supports_two_point_target_temperature(false);
|
||||||
|
traits.set_supports_away(false);
|
||||||
|
traits.set_visual_min_temperature(TCL112_TEMP_MIN);
|
||||||
|
traits.set_visual_max_temperature(TCL112_TEMP_MAX);
|
||||||
|
traits.set_visual_temperature_step(.5f);
|
||||||
|
return traits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tcl112Climate::setup() {
|
||||||
|
if (this->sensor_) {
|
||||||
|
this->sensor_->add_on_state_callback([this](float state) {
|
||||||
|
this->current_temperature = state;
|
||||||
|
// current temperature changed, publish state
|
||||||
|
this->publish_state();
|
||||||
|
});
|
||||||
|
this->current_temperature = this->sensor_->state;
|
||||||
|
} else
|
||||||
|
this->current_temperature = NAN;
|
||||||
|
// restore set points
|
||||||
|
auto restore = this->restore_state_();
|
||||||
|
if (restore.has_value()) {
|
||||||
|
restore->apply(this);
|
||||||
|
} else {
|
||||||
|
// restore from defaults
|
||||||
|
this->mode = climate::CLIMATE_MODE_OFF;
|
||||||
|
this->target_temperature = 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tcl112Climate::control(const climate::ClimateCall &call) {
|
||||||
|
if (call.get_mode().has_value())
|
||||||
|
this->mode = *call.get_mode();
|
||||||
|
if (call.get_target_temperature().has_value())
|
||||||
|
this->target_temperature = *call.get_target_temperature();
|
||||||
|
|
||||||
|
this->transmit_state_();
|
||||||
|
this->publish_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tcl112Climate::transmit_state_() {
|
||||||
|
uint8_t remote_state[TCL112_STATE_LENGTH] = {0};
|
||||||
|
|
||||||
|
// A known good state. (On, Cool, 24C)
|
||||||
|
remote_state[0] = 0x23;
|
||||||
|
remote_state[1] = 0xCB;
|
||||||
|
remote_state[2] = 0x26;
|
||||||
|
remote_state[3] = 0x01;
|
||||||
|
remote_state[5] = 0x24;
|
||||||
|
remote_state[6] = 0x03;
|
||||||
|
remote_state[7] = 0x07;
|
||||||
|
remote_state[8] = 0x40;
|
||||||
|
|
||||||
|
// Set mode
|
||||||
|
switch (this->mode) {
|
||||||
|
case climate::CLIMATE_MODE_AUTO:
|
||||||
|
remote_state[6] &= 0xF0;
|
||||||
|
remote_state[6] |= TCL112_AUTO;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_COOL:
|
||||||
|
remote_state[6] &= 0xF0;
|
||||||
|
remote_state[6] |= TCL112_COOL;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_HEAT:
|
||||||
|
remote_state[6] &= 0xF0;
|
||||||
|
remote_state[6] |= TCL112_HEAT;
|
||||||
|
break;
|
||||||
|
case climate::CLIMATE_MODE_OFF:
|
||||||
|
default:
|
||||||
|
remote_state[5] &= ~TCL112_POWER_MASK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set temperature
|
||||||
|
// Make sure we have desired temp in the correct range.
|
||||||
|
float safecelsius = std::max(this->target_temperature, TCL112_TEMP_MIN);
|
||||||
|
safecelsius = std::min(safecelsius, TCL112_TEMP_MAX);
|
||||||
|
// Convert to integer nr. of half degrees.
|
||||||
|
auto half_degrees = static_cast<uint8_t>(safecelsius * 2);
|
||||||
|
if (half_degrees & 1) // Do we have a half degree celsius?
|
||||||
|
remote_state[12] |= TCL112_HALF_DEGREE; // Add 0.5 degrees
|
||||||
|
else
|
||||||
|
remote_state[12] &= ~TCL112_HALF_DEGREE; // Clear the half degree.
|
||||||
|
remote_state[7] &= 0xF0; // Clear temp bits.
|
||||||
|
remote_state[7] |= ((uint8_t) TCL112_TEMP_MAX - half_degrees / 2);
|
||||||
|
|
||||||
|
// Calculate & set the checksum for the current internal state of the remote.
|
||||||
|
// Stored the checksum value in the last byte.
|
||||||
|
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
|
||||||
|
remote_state[TCL112_STATE_LENGTH - 1] += remote_state[checksum_byte];
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "Sending tcl code: %u", remote_state[7]);
|
||||||
|
|
||||||
|
auto transmit = this->transmitter_->transmit();
|
||||||
|
auto data = transmit.get_data();
|
||||||
|
|
||||||
|
data->set_carrier_frequency(38000);
|
||||||
|
|
||||||
|
// Header
|
||||||
|
data->mark(TCL112_HEADER_MARK);
|
||||||
|
data->space(TCL112_HEADER_SPACE);
|
||||||
|
// Data
|
||||||
|
for (uint8_t i : remote_state)
|
||||||
|
for (uint8_t j = 0; j < 8; j++) {
|
||||||
|
data->mark(TCL112_BIT_MARK);
|
||||||
|
bool bit = i & (1 << j);
|
||||||
|
data->space(bit ? TCL112_ONE_SPACE : TCL112_ZERO_SPACE);
|
||||||
|
}
|
||||||
|
// Footer
|
||||||
|
data->mark(TCL112_BIT_MARK);
|
||||||
|
data->space(TCL112_GAP);
|
||||||
|
|
||||||
|
transmit.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tcl112
|
||||||
|
} // namespace esphome
|
40
esphome/components/tcl112/tcl112.h
Normal file
40
esphome/components/tcl112/tcl112.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/components/climate/climate.h"
|
||||||
|
#include "esphome/components/remote_base/remote_base.h"
|
||||||
|
#include "esphome/components/remote_transmitter/remote_transmitter.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace tcl112 {
|
||||||
|
|
||||||
|
class Tcl112Climate : public climate::Climate, public Component {
|
||||||
|
public:
|
||||||
|
void setup() override;
|
||||||
|
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
|
||||||
|
this->transmitter_ = transmitter;
|
||||||
|
}
|
||||||
|
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||||
|
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||||
|
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Override control to change settings of the climate device.
|
||||||
|
void control(const climate::ClimateCall &call) override;
|
||||||
|
/// Return the traits of this controller.
|
||||||
|
climate::ClimateTraits traits() override;
|
||||||
|
|
||||||
|
/// Transmit via IR the state of this climate controller.
|
||||||
|
void transmit_state_();
|
||||||
|
|
||||||
|
bool supports_cool_{true};
|
||||||
|
bool supports_heat_{true};
|
||||||
|
|
||||||
|
remote_transmitter::RemoteTransmitterComponent *transmitter_;
|
||||||
|
sensor::Sensor *sensor_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tcl112
|
||||||
|
} // namespace esphome
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/uptime/uptime_sensor.h"
|
#include "uptime_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/wifi/wifi_component.h"
|
#include "wifi_component.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/wifi/wifi_component.h"
|
#include "wifi_component.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "esphome/components/wifi/wifi_component.h"
|
#include "wifi_component.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
|
||||||
|
@ -450,7 +450,9 @@ def validate_config(config):
|
|||||||
result.remove_output_path([domain], domain)
|
result.remove_output_path([domain], domain)
|
||||||
|
|
||||||
# Ensure conf is a list
|
# Ensure conf is a list
|
||||||
if not isinstance(conf, list) and conf:
|
if not conf:
|
||||||
|
result[domain] = conf = []
|
||||||
|
elif not isinstance(conf, list):
|
||||||
result[domain] = conf = [conf]
|
result[domain] = conf = [conf]
|
||||||
|
|
||||||
for i, p_config in enumerate(conf):
|
for i, p_config in enumerate(conf):
|
||||||
|
@ -1092,6 +1092,7 @@ def typed_schema(schemas, **kwargs):
|
|||||||
key_v = key_validator(value.pop(key))
|
key_v = key_validator(value.pop(key))
|
||||||
value = schemas[key_v](value)
|
value = schemas[key_v](value)
|
||||||
value[key] = key_v
|
value[key] = key_v
|
||||||
|
return value
|
||||||
|
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
MAJOR_VERSION = 1
|
MAJOR_VERSION = 1
|
||||||
MINOR_VERSION = 13
|
MINOR_VERSION = 14
|
||||||
PATCH_VERSION = '0-dev'
|
PATCH_VERSION = '0-dev'
|
||||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||||
@ -19,6 +19,7 @@ ARDUINO_VERSION_ESP8266_DEV = 'https://github.com/platformio/platform-espressif8
|
|||||||
'/stage'
|
'/stage'
|
||||||
ARDUINO_VERSION_ESP8266_2_5_0 = 'espressif8266@2.0.0'
|
ARDUINO_VERSION_ESP8266_2_5_0 = 'espressif8266@2.0.0'
|
||||||
ARDUINO_VERSION_ESP8266_2_5_1 = 'espressif8266@2.1.0'
|
ARDUINO_VERSION_ESP8266_2_5_1 = 'espressif8266@2.1.0'
|
||||||
|
ARDUINO_VERSION_ESP8266_2_5_2 = 'espressif8266@2.2.0'
|
||||||
ARDUINO_VERSION_ESP8266_2_3_0 = 'espressif8266@1.5.0'
|
ARDUINO_VERSION_ESP8266_2_3_0 = 'espressif8266@1.5.0'
|
||||||
SOURCE_FILE_EXTENSIONS = {'.cpp', '.hpp', '.h', '.c', '.tcc', '.ino'}
|
SOURCE_FILE_EXTENSIONS = {'.cpp', '.hpp', '.h', '.c', '.tcc', '.ino'}
|
||||||
HEADER_FILE_EXTENSIONS = {'.h', '.hpp', '.tcc'}
|
HEADER_FILE_EXTENSIONS = {'.h', '.hpp', '.tcc'}
|
||||||
@ -61,6 +62,7 @@ CONF_BUILD_PATH = 'build_path'
|
|||||||
CONF_BUSY_PIN = 'busy_pin'
|
CONF_BUSY_PIN = 'busy_pin'
|
||||||
CONF_BUS_VOLTAGE = 'bus_voltage'
|
CONF_BUS_VOLTAGE = 'bus_voltage'
|
||||||
CONF_CALIBRATE_LINEAR = 'calibrate_linear'
|
CONF_CALIBRATE_LINEAR = 'calibrate_linear'
|
||||||
|
CONF_CALIBRATION = 'calibration'
|
||||||
CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent'
|
CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent'
|
||||||
CONF_CARRIER_FREQUENCY = 'carrier_frequency'
|
CONF_CARRIER_FREQUENCY = 'carrier_frequency'
|
||||||
CONF_CHANGE_MODE_EVERY = 'change_mode_every'
|
CONF_CHANGE_MODE_EVERY = 'change_mode_every'
|
||||||
@ -200,6 +202,7 @@ CONF_LEVEL = 'level'
|
|||||||
CONF_LG = 'lg'
|
CONF_LG = 'lg'
|
||||||
CONF_LIBRARIES = 'libraries'
|
CONF_LIBRARIES = 'libraries'
|
||||||
CONF_LIGHT = 'light'
|
CONF_LIGHT = 'light'
|
||||||
|
CONF_LOADED_INTEGRATIONS = 'loaded_integrations'
|
||||||
CONF_LOCAL = 'local'
|
CONF_LOCAL = 'local'
|
||||||
CONF_LOGGER = 'logger'
|
CONF_LOGGER = 'logger'
|
||||||
CONF_LOGS = 'logs'
|
CONF_LOGS = 'logs'
|
||||||
@ -365,6 +368,7 @@ CONF_SERVICE = 'service'
|
|||||||
CONF_SERVICES = 'services'
|
CONF_SERVICES = 'services'
|
||||||
CONF_SETUP_MODE = 'setup_mode'
|
CONF_SETUP_MODE = 'setup_mode'
|
||||||
CONF_SETUP_PRIORITY = 'setup_priority'
|
CONF_SETUP_PRIORITY = 'setup_priority'
|
||||||
|
CONF_SEQUENCE = 'sequence'
|
||||||
CONF_SHUNT_RESISTANCE = 'shunt_resistance'
|
CONF_SHUNT_RESISTANCE = 'shunt_resistance'
|
||||||
CONF_SHUNT_VOLTAGE = 'shunt_voltage'
|
CONF_SHUNT_VOLTAGE = 'shunt_voltage'
|
||||||
CONF_SHUTDOWN_MESSAGE = 'shutdown_message'
|
CONF_SHUTDOWN_MESSAGE = 'shutdown_message'
|
||||||
|
@ -257,7 +257,7 @@ std::string to_string(long double val) {
|
|||||||
optional<float> parse_float(const std::string &str) {
|
optional<float> parse_float(const std::string &str) {
|
||||||
char *end;
|
char *end;
|
||||||
float value = ::strtof(str.c_str(), &end);
|
float value = ::strtof(str.c_str(), &end);
|
||||||
if (end == nullptr)
|
if (end == nullptr || end != str.end().base())
|
||||||
return {};
|
return {};
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ from esphome.const import ARDUINO_VERSION_ESP32_DEV, ARDUINO_VERSION_ESP8266_DEV
|
|||||||
CONF_NAME, CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, CONF_PLATFORM, \
|
CONF_NAME, CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, CONF_PLATFORM, \
|
||||||
CONF_PLATFORMIO_OPTIONS, CONF_PRIORITY, CONF_TRIGGER_ID, \
|
CONF_PLATFORMIO_OPTIONS, CONF_PRIORITY, CONF_TRIGGER_ID, \
|
||||||
CONF_ESP8266_RESTORE_FROM_FLASH, __version__, ARDUINO_VERSION_ESP8266_2_3_0, \
|
CONF_ESP8266_RESTORE_FROM_FLASH, __version__, ARDUINO_VERSION_ESP8266_2_3_0, \
|
||||||
ARDUINO_VERSION_ESP8266_2_5_0, ARDUINO_VERSION_ESP8266_2_5_1
|
ARDUINO_VERSION_ESP8266_2_5_0, ARDUINO_VERSION_ESP8266_2_5_1, ARDUINO_VERSION_ESP8266_2_5_2
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS
|
from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS
|
||||||
|
|
||||||
@ -44,6 +44,7 @@ def validate_board(value):
|
|||||||
validate_platform = cv.one_of('ESP32', 'ESP8266', upper=True)
|
validate_platform = cv.one_of('ESP32', 'ESP8266', upper=True)
|
||||||
|
|
||||||
PLATFORMIO_ESP8266_LUT = {
|
PLATFORMIO_ESP8266_LUT = {
|
||||||
|
'2.5.2': 'espressif8266@2.2.0',
|
||||||
'2.5.1': 'espressif8266@2.1.0',
|
'2.5.1': 'espressif8266@2.1.0',
|
||||||
'2.5.0': 'espressif8266@2.0.1',
|
'2.5.0': 'espressif8266@2.0.1',
|
||||||
'2.4.2': 'espressif8266@1.8.0',
|
'2.4.2': 'espressif8266@1.8.0',
|
||||||
@ -193,7 +194,7 @@ def to_code(config):
|
|||||||
'espressif8266@1.6.0'):
|
'espressif8266@1.6.0'):
|
||||||
ld_script = ld_scripts[0]
|
ld_script = ld_scripts[0]
|
||||||
elif CORE.arduino_version in (ARDUINO_VERSION_ESP8266_DEV, ARDUINO_VERSION_ESP8266_2_5_0,
|
elif CORE.arduino_version in (ARDUINO_VERSION_ESP8266_DEV, ARDUINO_VERSION_ESP8266_2_5_0,
|
||||||
ARDUINO_VERSION_ESP8266_2_5_1):
|
ARDUINO_VERSION_ESP8266_2_5_1, ARDUINO_VERSION_ESP8266_2_5_2):
|
||||||
ld_script = ld_scripts[1]
|
ld_script = ld_scripts[1]
|
||||||
|
|
||||||
if ld_script is not None:
|
if ld_script is not None:
|
||||||
|
@ -430,6 +430,12 @@ class DashboardEntry(object):
|
|||||||
def update_new(self):
|
def update_new(self):
|
||||||
return const.__version__
|
return const.__version__
|
||||||
|
|
||||||
|
@property
|
||||||
|
def loaded_integrations(self):
|
||||||
|
if self.storage is None:
|
||||||
|
return []
|
||||||
|
return self.storage.loaded_integrations
|
||||||
|
|
||||||
|
|
||||||
class MainRequestHandler(BaseHandler):
|
class MainRequestHandler(BaseHandler):
|
||||||
@authenticated
|
@authenticated
|
||||||
|
@ -67,6 +67,9 @@
|
|||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<span class="card-title">
|
<span class="card-title">
|
||||||
{{ escape(entry.name) }}
|
{{ escape(entry.name) }}
|
||||||
|
{% if 'web_server' in entry.loaded_integrations %}
|
||||||
|
<a href="http://{{ escape(entry.address) }}" target="_blank"><i class="material-icons icon-grey">launch</i></a>
|
||||||
|
{% end %}
|
||||||
<i class="material-icons right dropdown-trigger" data-target="dropdown-{{ i }}">more_vert</i>
|
<i class="material-icons right dropdown-trigger" data-target="dropdown-{{ i }}">more_vert</i>
|
||||||
</span>
|
</span>
|
||||||
<p>
|
<p>
|
||||||
|
@ -19,12 +19,16 @@ def patch_structhash():
|
|||||||
# all issues
|
# all issues
|
||||||
from platformio.commands import run
|
from platformio.commands import run
|
||||||
from platformio import util
|
from platformio import util
|
||||||
|
try:
|
||||||
|
from platformio.util import get_project_dir
|
||||||
|
except ImportError:
|
||||||
|
from platformio.project.helpers import get_project_dir
|
||||||
from os.path import join, isdir, getmtime, isfile
|
from os.path import join, isdir, getmtime, isfile
|
||||||
from os import makedirs
|
from os import makedirs
|
||||||
|
|
||||||
def patched_clean_build_dir(build_dir):
|
def patched_clean_build_dir(build_dir):
|
||||||
structhash_file = join(build_dir, "structure.hash")
|
structhash_file = join(build_dir, "structure.hash")
|
||||||
platformio_ini = join(util.get_project_dir(), "platformio.ini")
|
platformio_ini = join(get_project_dir(), "platformio.ini")
|
||||||
|
|
||||||
# if project's config is modified
|
# if project's config is modified
|
||||||
if isdir(build_dir) and getmtime(platformio_ini) > getmtime(build_dir):
|
if isdir(build_dir) and getmtime(platformio_ini) > getmtime(build_dir):
|
||||||
|
@ -37,7 +37,7 @@ def trash_storage_path(base_path): # type: (str) -> str
|
|||||||
class StorageJSON(object):
|
class StorageJSON(object):
|
||||||
def __init__(self, storage_version, name, esphome_version,
|
def __init__(self, storage_version, name, esphome_version,
|
||||||
src_version, arduino_version, address, esp_platform, board, build_path,
|
src_version, arduino_version, address, esp_platform, board, build_path,
|
||||||
firmware_bin_path):
|
firmware_bin_path, loaded_integrations):
|
||||||
# Version of the storage JSON schema
|
# Version of the storage JSON schema
|
||||||
assert storage_version is None or isinstance(storage_version, int)
|
assert storage_version is None or isinstance(storage_version, int)
|
||||||
self.storage_version = storage_version # type: int
|
self.storage_version = storage_version # type: int
|
||||||
@ -61,6 +61,9 @@ class StorageJSON(object):
|
|||||||
self.build_path = build_path # type: str
|
self.build_path = build_path # type: str
|
||||||
# The absolute path to the firmware binary
|
# The absolute path to the firmware binary
|
||||||
self.firmware_bin_path = firmware_bin_path # type: str
|
self.firmware_bin_path = firmware_bin_path # type: str
|
||||||
|
# A list of strings of names of loaded integrations
|
||||||
|
self.loaded_integrations = loaded_integrations # type: List[str]
|
||||||
|
self.loaded_integrations.sort()
|
||||||
|
|
||||||
def as_dict(self):
|
def as_dict(self):
|
||||||
return {
|
return {
|
||||||
@ -74,6 +77,7 @@ class StorageJSON(object):
|
|||||||
'board': self.board,
|
'board': self.board,
|
||||||
'build_path': self.build_path,
|
'build_path': self.build_path,
|
||||||
'firmware_bin_path': self.firmware_bin_path,
|
'firmware_bin_path': self.firmware_bin_path,
|
||||||
|
'loaded_integrations': self.loaded_integrations,
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@ -97,6 +101,7 @@ class StorageJSON(object):
|
|||||||
board=esph.board,
|
board=esph.board,
|
||||||
build_path=esph.build_path,
|
build_path=esph.build_path,
|
||||||
firmware_bin_path=esph.firmware_bin,
|
firmware_bin_path=esph.firmware_bin,
|
||||||
|
loaded_integrations=list(esph.loaded_integrations),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -113,6 +118,7 @@ class StorageJSON(object):
|
|||||||
board=board,
|
board=board,
|
||||||
build_path=None,
|
build_path=None,
|
||||||
firmware_bin_path=None,
|
firmware_bin_path=None,
|
||||||
|
loaded_integrations=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -130,9 +136,10 @@ class StorageJSON(object):
|
|||||||
board = storage.get('board')
|
board = storage.get('board')
|
||||||
build_path = storage.get('build_path')
|
build_path = storage.get('build_path')
|
||||||
firmware_bin_path = storage.get('firmware_bin_path')
|
firmware_bin_path = storage.get('firmware_bin_path')
|
||||||
|
loaded_integrations = storage.get('loaded_integrations', [])
|
||||||
return StorageJSON(storage_version, name, esphome_version,
|
return StorageJSON(storage_version, name, esphome_version,
|
||||||
src_version, arduino_version, address, esp_platform, board, build_path,
|
src_version, arduino_version, address, esp_platform, board, build_path,
|
||||||
firmware_bin_path)
|
firmware_bin_path, loaded_integrations)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(path): # type: (str) -> Optional[StorageJSON]
|
def load(path): # type: (str) -> Optional[StorageJSON]
|
||||||
|
@ -130,8 +130,6 @@ def storage_should_clean(old, new): # type: (StorageJSON, StorageJSON) -> bool
|
|||||||
if old is None:
|
if old is None:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if old.esphome_version != new.esphome_version:
|
|
||||||
return True
|
|
||||||
if old.src_version != new.src_version:
|
if old.src_version != new.src_version:
|
||||||
return True
|
return True
|
||||||
if old.arduino_version != new.arduino_version:
|
if old.arduino_version != new.arduino_version:
|
||||||
|
@ -86,9 +86,12 @@ def lint_content_find_check(find, **kwargs):
|
|||||||
decor = lint_content_check(**kwargs)
|
decor = lint_content_check(**kwargs)
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
def new_func(content):
|
def new_func(fname, content):
|
||||||
for line, col in find_all(content, find):
|
find_ = find
|
||||||
err = func()
|
if callable(find):
|
||||||
|
find_ = find(fname, content)
|
||||||
|
for line, col in find_all(content, find_):
|
||||||
|
err = func(fname)
|
||||||
return "{err} See line {line}:{col}.".format(err=err, line=line+1, col=col+1)
|
return "{err} See line {line}:{col}.".format(err=err, line=line+1, col=col+1)
|
||||||
return decor(new_func)
|
return decor(new_func)
|
||||||
return decorator
|
return decorator
|
||||||
@ -123,31 +126,63 @@ def lint_executable_bit(fname):
|
|||||||
'esphome/dashboard/static/ace.js', 'esphome/dashboard/static/ext-searchbox.js',
|
'esphome/dashboard/static/ace.js', 'esphome/dashboard/static/ext-searchbox.js',
|
||||||
'script/.neopixelbus.patch',
|
'script/.neopixelbus.patch',
|
||||||
])
|
])
|
||||||
def lint_tabs():
|
def lint_tabs(fname):
|
||||||
return "File contains tab character. Please convert tabs to spaces."
|
return "File contains tab character. Please convert tabs to spaces."
|
||||||
|
|
||||||
|
|
||||||
@lint_content_find_check('\r')
|
@lint_content_find_check('\r')
|
||||||
def lint_newline():
|
def lint_newline(fname):
|
||||||
return "File contains windows newline. Please set your editor to unix newline mode."
|
return "File contains windows newline. Please set your editor to unix newline mode."
|
||||||
|
|
||||||
|
|
||||||
@lint_content_check()
|
@lint_content_check()
|
||||||
def lint_end_newline(content):
|
def lint_end_newline(fname, content):
|
||||||
if content and not content.endswith('\n'):
|
if content and not content.endswith('\n'):
|
||||||
return "File does not end with a newline, please add an empty line at the end of the file."
|
return "File does not end with a newline, please add an empty line at the end of the file."
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def relative_cpp_search_text(fname, content):
|
||||||
|
parts = fname.split('/')
|
||||||
|
integration = parts[2]
|
||||||
|
return '#include "esphome/components/{}'.format(integration)
|
||||||
|
|
||||||
|
|
||||||
|
@lint_content_find_check(relative_cpp_search_text, include=['esphome/components/*.cpp'])
|
||||||
|
def lint_relative_cpp_import(fname):
|
||||||
|
return ("Component contains absolute import - Components must always use "
|
||||||
|
"relative imports.\n"
|
||||||
|
"Change:\n"
|
||||||
|
' #include "esphome/components/abc/abc.h"\n'
|
||||||
|
'to:\n'
|
||||||
|
' #include "abc.h"\n\n')
|
||||||
|
|
||||||
|
|
||||||
|
def relative_py_search_text(fname, content):
|
||||||
|
parts = fname.split('/')
|
||||||
|
integration = parts[2]
|
||||||
|
return 'esphome.components.{}'.format(integration)
|
||||||
|
|
||||||
|
|
||||||
|
@lint_content_find_check(relative_py_search_text, include=['esphome/components/*.py'])
|
||||||
|
def lint_relative_py_import(fname):
|
||||||
|
return ("Component contains absolute import - Components must always use "
|
||||||
|
"relative imports within the integration.\n"
|
||||||
|
"Change:\n"
|
||||||
|
' from esphome.components.abc import abc_ns"\n'
|
||||||
|
'to:\n'
|
||||||
|
' from . import abc_ns\n\n')
|
||||||
|
|
||||||
|
|
||||||
@lint_content_find_check('"esphome.h"', include=cpp_include, exclude=['tests/custom.h'])
|
@lint_content_find_check('"esphome.h"', include=cpp_include, exclude=['tests/custom.h'])
|
||||||
def lint_esphome_h():
|
def lint_esphome_h(fname):
|
||||||
return ("File contains reference to 'esphome.h' - This file is "
|
return ("File contains reference to 'esphome.h' - This file is "
|
||||||
"auto-generated and should only be used for *custom* "
|
"auto-generated and should only be used for *custom* "
|
||||||
"components. Please replace with references to the direct files.")
|
"components. Please replace with references to the direct files.")
|
||||||
|
|
||||||
|
|
||||||
@lint_content_check(include=['*.h'])
|
@lint_content_check(include=['*.h'])
|
||||||
def lint_pragma_once(content):
|
def lint_pragma_once(fname, content):
|
||||||
if '#pragma once' not in content:
|
if '#pragma once' not in content:
|
||||||
return ("Header file contains no 'pragma once' header guard. Please add a "
|
return ("Header file contains no 'pragma once' header guard. Please add a "
|
||||||
"'#pragma once' line at the top of the file.")
|
"'#pragma once' line at the top of the file.")
|
||||||
@ -171,7 +206,7 @@ def lint_pragma_once(content):
|
|||||||
'esphome/core/log.h',
|
'esphome/core/log.h',
|
||||||
'tests/custom.h',
|
'tests/custom.h',
|
||||||
])
|
])
|
||||||
def lint_log_in_header():
|
def lint_log_in_header(fname):
|
||||||
return ('Found reference to ESP_LOG in header file. Using ESP_LOG* in header files '
|
return ('Found reference to ESP_LOG in header file. Using ESP_LOG* in header files '
|
||||||
'is currently not possible - please move the definition to a source file (.cpp)')
|
'is currently not possible - please move the definition to a source file (.cpp)')
|
||||||
|
|
||||||
@ -202,7 +237,7 @@ for fname in files:
|
|||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
add_errors(fname, "File is not readable as UTF-8. Please set your editor to UTF-8 mode.")
|
add_errors(fname, "File is not readable as UTF-8. Please set your editor to UTF-8 mode.")
|
||||||
continue
|
continue
|
||||||
run_checks(LINT_CONTENT_CHECKS, fname, content)
|
run_checks(LINT_CONTENT_CHECKS, fname, fname, content)
|
||||||
|
|
||||||
for f, errs in sorted(errors.items()):
|
for f, errs in sorted(errors.items()):
|
||||||
print("\033[0;32m************* File \033[1;32m{}\033[0m".format(f))
|
print("\033[0;32m************* File \033[1;32m{}\033[0m".format(f))
|
||||||
|
@ -13,7 +13,7 @@ import threading
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
from helpers import basepath, get_output, walk_files, filter_changed
|
from helpers import basepath, get_output, git_ls_files, filter_changed
|
||||||
|
|
||||||
is_py2 = sys.version[0] == '2'
|
is_py2 = sys.version[0] == '2'
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ def main():
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
for path in walk_files(basepath):
|
for path in git_ls_files():
|
||||||
filetypes = ('.cpp', '.h', '.tcc')
|
filetypes = ('.cpp', '.h', '.tcc')
|
||||||
ext = os.path.splitext(path)[1]
|
ext = os.path.splitext(path)[1]
|
||||||
if ext in filetypes:
|
if ext in filetypes:
|
||||||
|
@ -18,7 +18,7 @@ import threading
|
|||||||
|
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
from helpers import basepath, shlex_quote, get_output, build_compile_commands, \
|
from helpers import basepath, shlex_quote, get_output, build_compile_commands, \
|
||||||
build_all_include, temp_header_file, walk_files, filter_changed
|
build_all_include, temp_header_file, git_ls_files, filter_changed
|
||||||
|
|
||||||
is_py2 = sys.version[0] == '2'
|
is_py2 = sys.version[0] == '2'
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ def main():
|
|||||||
build_compile_commands()
|
build_compile_commands()
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
for path in walk_files(basepath):
|
for path in git_ls_files():
|
||||||
filetypes = ('.cpp',)
|
filetypes = ('.cpp',)
|
||||||
ext = os.path.splitext(path)[1]
|
ext = os.path.splitext(path)[1]
|
||||||
if ext in filetypes:
|
if ext in filetypes:
|
||||||
|
@ -126,3 +126,13 @@ def filter_changed(files):
|
|||||||
for c in files:
|
for c in files:
|
||||||
print(" {}".format(c))
|
print(" {}".format(c))
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def git_ls_files():
|
||||||
|
command = ['git', 'ls-files', '-s']
|
||||||
|
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||||
|
output, err = proc.communicate()
|
||||||
|
lines = [x.split() for x in output.decode('utf-8').splitlines()]
|
||||||
|
return {
|
||||||
|
s[3].strip(): int(s[0]) for s in lines
|
||||||
|
}
|
||||||
|
@ -9,7 +9,20 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
from helpers import basepath, get_output, walk_files, filter_changed
|
from helpers import get_output, git_ls_files, filter_changed
|
||||||
|
|
||||||
|
curfile = None
|
||||||
|
|
||||||
|
|
||||||
|
def print_error(file, lineno, msg):
|
||||||
|
global curfile
|
||||||
|
|
||||||
|
if curfile != file:
|
||||||
|
print()
|
||||||
|
print("\033[0;32m************* File \033[1;32m{}\033[0m".format(file))
|
||||||
|
curfile = file
|
||||||
|
|
||||||
|
print(u'{}:{} - {}'.format(file, lineno, msg))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -21,10 +34,10 @@ def main():
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
for path in walk_files(basepath):
|
for path in git_ls_files():
|
||||||
filetypes = ('.py',)
|
filetypes = ('.py',)
|
||||||
ext = os.path.splitext(path)[1]
|
ext = os.path.splitext(path)[1]
|
||||||
if ext in filetypes:
|
if ext in filetypes and path.startswith('esphome'):
|
||||||
path = os.path.relpath(path, os.getcwd())
|
path = os.path.relpath(path, os.getcwd())
|
||||||
files.append(path)
|
files.append(path)
|
||||||
# Match against re
|
# Match against re
|
||||||
@ -35,8 +48,10 @@ def main():
|
|||||||
files = filter_changed(files)
|
files = filter_changed(files)
|
||||||
|
|
||||||
files.sort()
|
files.sort()
|
||||||
|
if not files:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
errors = collections.defaultdict(list)
|
errors = 0
|
||||||
cmd = ['flake8'] + files
|
cmd = ['flake8'] + files
|
||||||
print("Running flake8...")
|
print("Running flake8...")
|
||||||
log = get_output(*cmd)
|
log = get_output(*cmd)
|
||||||
@ -47,7 +62,8 @@ def main():
|
|||||||
file_ = line[0]
|
file_ = line[0]
|
||||||
linno = line[1]
|
linno = line[1]
|
||||||
msg = (u':'.join(line[3:])).strip()
|
msg = (u':'.join(line[3:])).strip()
|
||||||
errors[file_].append(u'{}:{} - {}'.format(file_, linno, msg))
|
print_error(file_, linno, msg)
|
||||||
|
errors += 1
|
||||||
|
|
||||||
cmd = ['pylint', '-f', 'parseable', '--persistent=n'] + files
|
cmd = ['pylint', '-f', 'parseable', '--persistent=n'] + files
|
||||||
print("Running pylint...")
|
print("Running pylint...")
|
||||||
@ -59,15 +75,10 @@ def main():
|
|||||||
file_ = line[0]
|
file_ = line[0]
|
||||||
linno = line[1]
|
linno = line[1]
|
||||||
msg = (u':'.join(line[3:])).strip()
|
msg = (u':'.join(line[3:])).strip()
|
||||||
errors[file_].append(u'{}:{} - {}'.format(file_, linno, msg))
|
print_error(file_, linno, msg)
|
||||||
|
errors += 1
|
||||||
|
|
||||||
for f, errs in sorted(errors.items()):
|
sys.exit(errors)
|
||||||
print("\033[0;32m************* File \033[1;32m{}\033[0m".format(f))
|
|
||||||
for err in errs:
|
|
||||||
print(err)
|
|
||||||
print()
|
|
||||||
|
|
||||||
sys.exit(len(errors))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -3,38 +3,36 @@
|
|||||||
|
|
||||||
class CustomSensor : public Component, public Sensor {
|
class CustomSensor : public Component, public Sensor {
|
||||||
public:
|
public:
|
||||||
void loop() override {
|
void loop() override { publish_state(42.0); }
|
||||||
publish_state(42.0);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomTextSensor : public Component, public TextSensor {
|
class CustomTextSensor : public Component, public TextSensor {
|
||||||
public:
|
public:
|
||||||
void loop() override {
|
void loop() override { publish_state("Hello World"); }
|
||||||
publish_state("Hello World");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomBinarySensor : public Component, public BinarySensor {
|
class CustomBinarySensor : public Component, public BinarySensor {
|
||||||
public:
|
public:
|
||||||
void loop() override {
|
void loop() override { publish_state(false); }
|
||||||
publish_state(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomSwitch : public Switch {
|
class CustomSwitch : public Switch {
|
||||||
protected:
|
protected:
|
||||||
void write_state(bool state) override {
|
void write_state(bool state) override { ESP_LOGD("custom_switch", "Setting %s", ONOFF(state)); }
|
||||||
ESP_LOGD("custom_switch", "Setting %s", ONOFF(state));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomComponent : public PollingComponent {
|
class CustomComponent : public PollingComponent {
|
||||||
public:
|
public:
|
||||||
void setup() override {
|
void setup() override { ESP_LOGD("custom_component", "Setup"); }
|
||||||
ESP_LOGD("custom_component", "Setup");
|
void update() override { ESP_LOGD("custom_component", "Update"); }
|
||||||
}
|
};
|
||||||
void update() override {
|
|
||||||
ESP_LOGD("custom_component", "Update");
|
class CustomBinaryOutput : public BinaryOutput, public Component {
|
||||||
}
|
protected:
|
||||||
|
void write_state(bool state) override { ESP_LOGD("custom_output", "Setting %s", ONOFF(state)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CustomFloatOutput : public FloatOutput, public Component {
|
||||||
|
protected:
|
||||||
|
void write_state(float state) override { ESP_LOGD("custom_output", "Setting %f", state); }
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ void setup() {
|
|||||||
App.init_ota()->start_safe_mode();
|
App.init_ota()->start_safe_mode();
|
||||||
|
|
||||||
// LEDC is only available on ESP32! for the ESP8266, take a look at App.make_esp8266_pwm_output().
|
// LEDC is only available on ESP32! for the ESP8266, take a look at App.make_esp8266_pwm_output().
|
||||||
auto *red = App.make_ledc_output(32); // on pin 32
|
auto *red = App.make_ledc_output(32); // on pin 32
|
||||||
auto *green = App.make_ledc_output(33);
|
auto *green = App.make_ledc_output(33);
|
||||||
auto *blue = App.make_ledc_output(34);
|
auto *blue = App.make_ledc_output(34);
|
||||||
App.make_rgb_light("Livingroom Light", red, green, blue);
|
App.make_rgb_light("Livingroom Light", red, green, blue);
|
||||||
@ -23,6 +23,4 @@ void setup() {
|
|||||||
App.setup();
|
App.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() { App.loop(); }
|
||||||
App.loop();
|
|
||||||
}
|
|
||||||
|
@ -29,6 +29,4 @@ void setup() {
|
|||||||
App.setup();
|
App.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() { App.loop(); }
|
||||||
App.loop();
|
|
||||||
}
|
|
||||||
|
@ -17,7 +17,7 @@ esphome:
|
|||||||
ESP_LOGV("main", "ON LOOP!");
|
ESP_LOGV("main", "ON LOOP!");
|
||||||
- light.addressable_set:
|
- light.addressable_set:
|
||||||
id: addr1
|
id: addr1
|
||||||
range_from: 1
|
range_from: 0
|
||||||
range_to: 100
|
range_to: 100
|
||||||
red: 100%
|
red: 100%
|
||||||
green: !lambda 'return 255;'
|
green: !lambda 'return 255;'
|
||||||
@ -839,6 +839,20 @@ light:
|
|||||||
name: Flicker Effect With Custom Values
|
name: Flicker Effect With Custom Values
|
||||||
update_interval: 16ms
|
update_interval: 16ms
|
||||||
intensity: 5%
|
intensity: 5%
|
||||||
|
- automation:
|
||||||
|
name: Custom Effect
|
||||||
|
sequence:
|
||||||
|
- light.addressable_set:
|
||||||
|
id: addr1
|
||||||
|
red: 100%
|
||||||
|
green: 100%
|
||||||
|
blue: 0%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.addressable_set:
|
||||||
|
id: addr1
|
||||||
|
red: 0%
|
||||||
|
green: 100%
|
||||||
|
blue: 0%
|
||||||
- platform: fastled_spi
|
- platform: fastled_spi
|
||||||
id: addr2
|
id: addr2
|
||||||
chipset: WS2801
|
chipset: WS2801
|
||||||
@ -881,6 +895,22 @@ remote_transmitter:
|
|||||||
- pin: 32
|
- pin: 32
|
||||||
carrier_duty_percent: 100%
|
carrier_duty_percent: 100%
|
||||||
|
|
||||||
|
climate:
|
||||||
|
- platform: tcl112
|
||||||
|
name: TCL112 Climate With Sensor
|
||||||
|
supports_heat: True
|
||||||
|
supports_cool: True
|
||||||
|
sensor: my_sensor
|
||||||
|
- platform: tcl112
|
||||||
|
name: TCL112 Climate
|
||||||
|
- platform: coolix
|
||||||
|
name: Coolix Climate With Sensor
|
||||||
|
supports_heat: True
|
||||||
|
supports_cool: True
|
||||||
|
sensor: my_sensor
|
||||||
|
- platform: coolix
|
||||||
|
name: Coolix Climate
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
pin: GPIO25
|
pin: GPIO25
|
||||||
|
@ -238,3 +238,6 @@ interval:
|
|||||||
interval: 5s
|
interval: 5s
|
||||||
then:
|
then:
|
||||||
- logger.log: "Interval Run"
|
- logger.log: "Interval Run"
|
||||||
|
|
||||||
|
display:
|
||||||
|
|
||||||
|
@ -94,6 +94,11 @@ sensor:
|
|||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
entity_id: sensor.hello_world
|
entity_id: sensor.hello_world
|
||||||
id: ha_hello_world
|
id: ha_hello_world
|
||||||
|
- platform: am2320
|
||||||
|
temperature:
|
||||||
|
name: "Temperature"
|
||||||
|
humidity:
|
||||||
|
name: "Humidity"
|
||||||
- platform: adc
|
- platform: adc
|
||||||
pin: VCC
|
pin: VCC
|
||||||
id: my_sensor
|
id: my_sensor
|
||||||
@ -110,6 +115,20 @@ sensor:
|
|||||||
- calibrate_linear:
|
- calibrate_linear:
|
||||||
- 0 -> 0
|
- 0 -> 0
|
||||||
- 100 -> 100
|
- 100 -> 100
|
||||||
|
- platform: resistance
|
||||||
|
sensor: my_sensor
|
||||||
|
configuration: DOWNSTREAM
|
||||||
|
resistor: 10kΩ
|
||||||
|
reference_voltage: 3.3V
|
||||||
|
name: Resistance
|
||||||
|
id: resist
|
||||||
|
- platform: ntc
|
||||||
|
sensor: resist
|
||||||
|
name: NTC Sensor
|
||||||
|
calibration:
|
||||||
|
b_constant: 3950
|
||||||
|
reference_resistance: 10k
|
||||||
|
reference_temperature: 25°C
|
||||||
- platform: tcs34725
|
- platform: tcs34725
|
||||||
red_channel:
|
red_channel:
|
||||||
name: Red Channel
|
name: Red Channel
|
||||||
@ -377,6 +396,22 @@ output:
|
|||||||
id: out
|
id: out
|
||||||
pin: D3
|
pin: D3
|
||||||
frequency: 50Hz
|
frequency: 50Hz
|
||||||
|
- platform: custom
|
||||||
|
type: binary
|
||||||
|
lambda: |-
|
||||||
|
auto s = new CustomBinaryOutput();
|
||||||
|
App.register_component(s);
|
||||||
|
return {s};
|
||||||
|
outputs:
|
||||||
|
- id: custom_binary
|
||||||
|
- platform: custom
|
||||||
|
type: float
|
||||||
|
lambda: |-
|
||||||
|
auto s = new CustomFloatOutput();
|
||||||
|
App.register_component(s);
|
||||||
|
return {s};
|
||||||
|
outputs:
|
||||||
|
- id: custom_float
|
||||||
|
|
||||||
mcp23017:
|
mcp23017:
|
||||||
id: mcp
|
id: mcp
|
||||||
|
Loading…
x
Reference in New Issue
Block a user