Merge branch 'dev' into jesserockz-2023-304

This commit is contained in:
Jesse Hills 2023-09-21 10:11:51 +12:00 committed by GitHub
commit 03fd82b903
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1049 additions and 192 deletions

View file

@ -17,12 +17,12 @@ runs:
steps: steps:
- name: Set up Python ${{ inputs.python-version }} - name: Set up Python ${{ inputs.python-version }}
id: python id: python
uses: actions/setup-python@v4.6.0 uses: actions/setup-python@v4.7.0
with: with:
python-version: ${{ inputs.python-version }} python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment - name: Restore Python virtual environment
id: cache-venv id: cache-venv
uses: actions/cache/restore@v3.3.1 uses: actions/cache/restore@v3.3.2
with: with:
path: venv path: venv
# yamllint disable-line rule:line-length # yamllint disable-line rule:line-length

View file

@ -40,15 +40,15 @@ jobs:
arch: [amd64, armv7, aarch64] arch: [amd64, armv7, aarch64]
build_type: ["ha-addon", "docker", "lint"] build_type: ["ha-addon", "docker", "lint"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4.0.0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4.7.0
with: with:
python-version: "3.9" python-version: "3.9"
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3.0.0
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3.0.0
- name: Set TAG - name: Set TAG
run: | run: |

View file

@ -7,6 +7,10 @@ on:
branches: [dev, beta, release] branches: [dev, beta, release]
pull_request: pull_request:
paths:
- "**"
- "!.github/workflows/*.yml"
- ".github/workflows/ci.yml"
merge_group: merge_group:
permissions: permissions:
@ -30,13 +34,13 @@ jobs:
cache-key: ${{ steps.cache-key.outputs.key }} cache-key: ${{ steps.cache-key.outputs.key }}
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Generate cache-key - name: Generate cache-key
id: cache-key id: cache-key
run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python id: python
uses: actions/setup-python@v4.6.0 uses: actions/setup-python@v4.7.0
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment - name: Restore Python virtual environment
@ -55,15 +59,6 @@ jobs:
pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
pip install -e . pip install -e .
yamllint:
name: yamllint
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4
- name: Run yamllint
uses: frenck/action-yamllint@v1.4.1
black: black:
name: Check black name: Check black
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -71,7 +66,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -92,7 +87,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -113,7 +108,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -134,7 +129,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -155,7 +150,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -176,7 +171,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -196,7 +191,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -215,6 +210,17 @@ jobs:
run: script/ci-suggest-changes run: script/ci-suggest-changes
if: always() if: always()
compile-tests-list:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.0.0
- name: Find all YAML test files
id: set-matrix
run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
compile-tests: compile-tests:
name: Run YAML test ${{ matrix.file }} name: Run YAML test ${{ matrix.file }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -227,24 +233,24 @@ jobs:
- pylint - pylint
- pytest - pytest
- pyupgrade - pyupgrade
- yamllint - compile-tests-list
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2 max-parallel: 2
matrix: matrix:
file: [1, 2, 3, 3.1, 4, 5, 6, 7, 8, 9, 9.1, 10] file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }}
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }} cache-key: ${{ needs.common.outputs.cache-key }}
- name: Run esphome compile tests/test${{ matrix.file }}.yaml - name: Run esphome compile ${{ matrix.file }}
run: | run: |
. venv/bin/activate . venv/bin/activate
esphome compile tests/test${{ matrix.file }}.yaml esphome compile ${{ matrix.file }}
clang-tidy: clang-tidy:
name: ${{ matrix.name }} name: ${{ matrix.name }}
@ -258,7 +264,6 @@ jobs:
- pylint - pylint
- pytest - pytest
- pyupgrade - pyupgrade
- yamllint
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2 max-parallel: 2
@ -295,7 +300,7 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -341,7 +346,6 @@ jobs:
- pylint - pylint
- pytest - pytest
- pyupgrade - pyupgrade
- yamllint
- compile-tests - compile-tests
- clang-tidy - clang-tidy
if: always() if: always()

View file

@ -18,7 +18,7 @@ jobs:
lock: lock:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v4 - uses: dessant/lock-threads@v4.0.1
with: with:
pr-inactive-days: "1" pr-inactive-days: "1"
pr-lock-reason: "" pr-lock-reason: ""

View file

@ -19,7 +19,7 @@ jobs:
outputs: outputs:
tag: ${{ steps.tag.outputs.tag }} tag: ${{ steps.tag.outputs.tag }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4.0.0
- name: Get tag - name: Get tag
id: tag id: tag
# yamllint disable rule:line-length # yamllint disable rule:line-length
@ -43,9 +43,9 @@ jobs:
if: github.repository == 'esphome/esphome' && github.event_name == 'release' if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4.0.0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4.7.0
with: with:
python-version: "3.x" python-version: "3.x"
- name: Set up python environment - name: Set up python environment
@ -88,24 +88,24 @@ jobs:
target: "lint" target: "lint"
baseimg: "docker" baseimg: "docker"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4.0.0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4.7.0
with: with:
python-version: "3.9" python-version: "3.9"
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3.0.0
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3.0.0
- name: Log in to docker hub - name: Log in to docker hub
uses: docker/login-action@v2 uses: docker/login-action@v3.0.0
with: with:
username: ${{ secrets.DOCKER_USER }} username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry - name: Log in to the GitHub container registry
uses: docker/login-action@v2 uses: docker/login-action@v3.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@ -119,7 +119,7 @@ jobs:
--suffix "${{ matrix.image.suffix }}" --suffix "${{ matrix.image.suffix }}"
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5.0.0
with: with:
context: . context: .
file: ./docker/Dockerfile file: ./docker/Dockerfile
@ -141,7 +141,7 @@ jobs:
needs: [deploy-docker] needs: [deploy-docker]
steps: steps:
- name: Trigger Workflow - name: Trigger Workflow
uses: actions/github-script@v6 uses: actions/github-script@v6.4.1
with: with:
github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }} github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
script: | script: |

View file

@ -18,7 +18,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v8 - uses: actions/stale@v8.0.0
with: with:
days-before-pr-stale: 90 days-before-pr-stale: 90
days-before-pr-close: 7 days-before-pr-close: 7
@ -38,7 +38,7 @@ jobs:
close-issues: close-issues:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v8 - uses: actions/stale@v8.0.0
with: with:
days-before-pr-stale: -1 days-before-pr-stale: -1
days-before-pr-close: -1 days-before-pr-close: -1

View file

@ -4,8 +4,7 @@ name: Synchronise Device Classes from Home Assistant
on: on:
workflow_dispatch: workflow_dispatch:
schedule: schedule:
- cron: '45 6 * * *' - cron: "45 6 * * *"
jobs: jobs:
sync: sync:
@ -14,16 +13,16 @@ jobs:
if: github.repository == 'esphome/esphome' if: github.repository == 'esphome/esphome'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
- name: Checkout Home Assistant - name: Checkout Home Assistant
uses: actions/checkout@v4 uses: actions/checkout@v4.0.0
with: with:
repository: home-assistant/core repository: home-assistant/core
path: lib/home-assistant path: lib/home-assistant
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4.7.0
with: with:
python-version: 3.11 python-version: 3.11
@ -37,7 +36,7 @@ jobs:
python ./script/sync-device_class.py python ./script/sync-device_class.py
- name: Commit changes - name: Commit changes
uses: peter-evans/create-pull-request@v5 uses: peter-evans/create-pull-request@v5.0.2
with: with:
commit-message: "Synchronise Device Classes from Home Assistant" commit-message: "Synchronise Device Classes from Home Assistant"
committer: esphomebot <esphome@nabucasa.com> committer: esphomebot <esphome@nabucasa.com>

22
.github/workflows/yaml-lint.yml vendored Normal file
View file

@ -0,0 +1,22 @@
name: YAML lint
on:
push:
branches: [dev, beta, release]
paths:
- "**.yaml"
- "**.yml"
pull_request:
paths:
- "**.yaml"
- "**.yml"
jobs:
yamllint:
name: yamllint
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.0.0
- name: Run yamllint
uses: frenck/action-yamllint@v1.4.1

View file

@ -3,7 +3,7 @@
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
repos: repos:
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.7.0 rev: 23.9.1
hooks: hooks:
- id: black - id: black
args: args:

View file

@ -29,7 +29,8 @@ RUN \
curl=7.74.0-1.3+deb11u7 \ curl=7.74.0-1.3+deb11u7 \
openssh-client=1:8.4p1-5+deb11u1 \ openssh-client=1:8.4p1-5+deb11u1 \
python3-cffi=1.14.5-1 \ python3-cffi=1.14.5-1 \
libcairo2=1.16.0-5; \ libcairo2=1.16.0-5 \
patch=2.7.6-7; \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
build-essential=12.9 \ build-essential=12.9 \

View file

@ -5,10 +5,7 @@ from esphome.const import CONF_ANALOG, CONF_INPUT
from esphome.core import CORE from esphome.core import CORE
from esphome.components.esp32 import get_esp32_variant from esphome.components.esp32 import get_esp32_variant
from esphome.const import ( from esphome.const import PLATFORM_ESP8266
PLATFORM_ESP8266,
PLATFORM_RP2040,
)
from esphome.components.esp32.const import ( from esphome.components.esp32.const import (
VARIANT_ESP32, VARIANT_ESP32,
VARIANT_ESP32C2, VARIANT_ESP32C2,
@ -147,7 +144,9 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = {
def validate_adc_pin(value): def validate_adc_pin(value):
if str(value).upper() == "VCC": if str(value).upper() == "VCC":
return cv.only_on([PLATFORM_ESP8266, PLATFORM_RP2040])("VCC") if CORE.is_rp2040:
return pins.internal_gpio_input_pin_schema(29)
return cv.only_on([PLATFORM_ESP8266])("VCC")
if str(value).upper() == "TEMPERATURE": if str(value).upper() == "TEMPERATURE":
return cv.only_on_rp2040("TEMPERATURE") return cv.only_on_rp2040("TEMPERATURE")

View file

@ -1,6 +1,6 @@
#include "adc_sensor.h" #include "adc_sensor.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_ESP8266 #ifdef USE_ESP8266
#ifdef USE_ADC_SENSOR_VCC #ifdef USE_ADC_SENSOR_VCC
@ -246,45 +246,42 @@ float ADCSensor::sample() {
adc_set_temp_sensor_enabled(true); adc_set_temp_sensor_enabled(true);
delay(1); delay(1);
adc_select_input(4); adc_select_input(4);
int32_t raw = adc_read();
adc_set_temp_sensor_enabled(false);
if (this->output_raw_) {
return raw;
}
return raw * 3.3f / 4096.0f;
} else { } else {
uint8_t pin; uint8_t pin = this->pin_->get_pin();
#ifdef USE_ADC_SENSOR_VCC
#ifdef CYW43_USES_VSYS_PIN #ifdef CYW43_USES_VSYS_PIN
// Measuring VSYS on Raspberry Pico W needs to be wrapped with if (pin == PICO_VSYS_PIN) {
// `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in // Measuring VSYS on Raspberry Pico W needs to be wrapped with
// https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in
// VSYS ADC both share GPIO29 // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and
cyw43_thread_enter(); // VSYS ADC both share GPIO29
cyw43_thread_enter();
}
#endif // CYW43_USES_VSYS_PIN #endif // CYW43_USES_VSYS_PIN
pin = PICO_VSYS_PIN;
#else
pin = this->pin_->get_pin();
#endif // USE_ADC_SENSOR_VCC
adc_gpio_init(pin); adc_gpio_init(pin);
adc_select_input(pin - 26); adc_select_input(pin - 26);
}
int32_t raw = adc_read(); int32_t raw = adc_read();
if (this->is_temperature_) {
adc_set_temp_sensor_enabled(false);
} else {
#ifdef USE_ADC_SENSOR_VCC
#ifdef CYW43_USES_VSYS_PIN #ifdef CYW43_USES_VSYS_PIN
cyw43_thread_exit(); if (pin == PICO_VSYS_PIN) {
cyw43_thread_exit();
}
#endif // CYW43_USES_VSYS_PIN #endif // CYW43_USES_VSYS_PIN
#endif // USE_ADC_SENSOR_VCC
}
if (output_raw_) { if (output_raw_) {
return raw; return raw;
}
float coeff = pin == PICO_VSYS_PIN ? 3.0 : 1.0;
return raw * 3.3f / 4096.0f * coeff;
} }
float coeff = 1.0;
#ifdef USE_ADC_SENSOR_VCC
// As per Raspberry Pico (W) datasheet (section 2.1) the VSYS/3 is measured
coeff = 3.0;
#endif // USE_ADC_SENSOR_VCC
return raw * 3.3f / 4096.0f * coeff;
} }
#endif #endif

View file

@ -62,8 +62,12 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
adc1_channel_t channel1_{ADC1_CHANNEL_MAX}; adc1_channel_t channel1_{ADC1_CHANNEL_MAX};
adc2_channel_t channel2_{ADC2_CHANNEL_MAX}; adc2_channel_t channel2_{ADC2_CHANNEL_MAX};
bool autorange_{false}; bool autorange_{false};
#if ESP_IDF_VERSION_MAJOR >= 5
esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {};
#else
esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {};
#endif #endif
#endif
}; };
} // namespace adc } // namespace adc

View file

@ -19,4 +19,4 @@ async def to_code(config):
cg.add_library("esphome/AsyncTCP-esphome", "2.0.1") cg.add_library("esphome/AsyncTCP-esphome", "2.0.1")
elif CORE.is_esp8266: elif CORE.is_esp8266:
# https://github.com/esphome/ESPAsyncTCP # https://github.com/esphome/ESPAsyncTCP
cg.add_library("esphome/ESPAsyncTCP-esphome", "1.2.3") cg.add_library("esphome/ESPAsyncTCP-esphome", "2.0.0")

View file

@ -80,8 +80,6 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(std::string, url)
TEMPLATABLE_VALUE(const char *, method) TEMPLATABLE_VALUE(const char *, method)
TEMPLATABLE_VALUE(std::string, body) TEMPLATABLE_VALUE(std::string, body)
TEMPLATABLE_VALUE(const char *, useragent)
TEMPLATABLE_VALUE(uint16_t, timeout)
void add_header(const char *key, TemplatableValue<const char *, Ts...> value) { this->headers_.insert({key, value}); } void add_header(const char *key, TemplatableValue<const char *, Ts...> value) { this->headers_.insert({key, value}); }
@ -105,25 +103,18 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1); auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1);
this->parent_->set_body(json::build_json(f)); this->parent_->set_body(json::build_json(f));
} }
if (this->useragent_.has_value()) { std::list<Header> headers;
this->parent_->set_useragent(this->useragent_.value(x...)); for (const auto &item : this->headers_) {
} auto val = item.second;
if (this->timeout_.has_value()) { Header header;
this->parent_->set_timeout(this->timeout_.value(x...)); header.name = item.first;
} header.value = val.value(x...);
if (!this->headers_.empty()) { headers.push_back(header);
std::list<Header> headers;
for (const auto &item : this->headers_) {
auto val = item.second;
Header header;
header.name = item.first;
header.value = val.value(x...);
headers.push_back(header);
}
this->parent_->set_headers(headers);
} }
this->parent_->set_headers(headers);
this->parent_->send(this->response_triggers_); this->parent_->send(this->response_triggers_);
this->parent_->close(); this->parent_->close();
this->parent_->set_body("");
} }
protected: protected:

View file

@ -13,8 +13,7 @@ namespace mdns {
void MDNSComponent::setup() { void MDNSComponent::setup() {
this->compile_records_(); this->compile_records_();
network::IPAddress addr = network::get_ip_address(); MDNS.begin(this->hostname_.c_str());
MDNS.begin(this->hostname_.c_str(), (uint32_t) addr);
for (const auto &service : this->services_) { for (const auto &service : this->services_) {
// Strip the leading underscore from the proto and service_type. While it is // Strip the leading underscore from the proto and service_type. While it is

View file

@ -35,7 +35,7 @@ from esphome.components.climate import (
) )
CODEOWNERS = ["@dudanov"] CODEOWNERS = ["@dudanov"]
DEPENDENCIES = ["climate", "uart", "wifi"] DEPENDENCIES = ["climate", "uart"]
AUTO_LOAD = ["sensor"] AUTO_LOAD = ["sensor"]
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
CONF_POWER_USAGE = "power_usage" CONF_POWER_USAGE = "power_usage"

View file

@ -8,6 +8,7 @@ from .const import (
CONF_BITMASK, CONF_BITMASK,
CONF_BYTE_OFFSET, CONF_BYTE_OFFSET,
CONF_COMMAND_THROTTLE, CONF_COMMAND_THROTTLE,
CONF_OFFLINE_SKIP_UPDATES,
CONF_CUSTOM_COMMAND, CONF_CUSTOM_COMMAND,
CONF_FORCE_NEW_RANGE, CONF_FORCE_NEW_RANGE,
CONF_MODBUS_CONTROLLER_ID, CONF_MODBUS_CONTROLLER_ID,
@ -104,6 +105,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional( cv.Optional(
CONF_COMMAND_THROTTLE, default="0ms" CONF_COMMAND_THROTTLE, default="0ms"
): cv.positive_time_period_milliseconds, ): cv.positive_time_period_milliseconds,
cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int,
} }
) )
.extend(cv.polling_component_schema("60s")) .extend(cv.polling_component_schema("60s"))
@ -206,8 +208,9 @@ async def add_modbus_base_properties(
async def to_code(config): async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID], config[CONF_COMMAND_THROTTLE]) var = cg.new_Pvariable(config[CONF_ID])
cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE])) cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE]))
cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
await register_modbus_device(var, config) await register_modbus_device(var, config)

View file

@ -1,6 +1,7 @@
CONF_BITMASK = "bitmask" CONF_BITMASK = "bitmask"
CONF_BYTE_OFFSET = "byte_offset" CONF_BYTE_OFFSET = "byte_offset"
CONF_COMMAND_THROTTLE = "command_throttle" CONF_COMMAND_THROTTLE = "command_throttle"
CONF_OFFLINE_SKIP_UPDATES = "offline_skip_updates"
CONF_CUSTOM_COMMAND = "custom_command" CONF_CUSTOM_COMMAND = "custom_command"
CONF_FORCE_NEW_RANGE = "force_new_range" CONF_FORCE_NEW_RANGE = "force_new_range"
CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id" CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id"

View file

@ -26,6 +26,17 @@ bool ModbusController::send_next_command_() {
// remove from queue if command was sent too often // remove from queue if command was sent too often
if (command->send_countdown < 1) { if (command->send_countdown < 1) {
if (!this->module_offline_) {
ESP_LOGW(TAG, "Modbus device=%d set offline", this->address_);
if (this->offline_skip_updates_ > 0) {
// Update skip_updates_counter to stop flooding channel with timeouts
for (auto &r : this->register_ranges_) {
r.skip_updates_counter = this->offline_skip_updates_;
}
}
}
this->module_offline_ = true;
ESP_LOGD( ESP_LOGD(
TAG, TAG,
"Modbus command to device=%d register=0x%02X countdown=%d no response received - removed from send queue", "Modbus command to device=%d register=0x%02X countdown=%d no response received - removed from send queue",
@ -49,6 +60,18 @@ bool ModbusController::send_next_command_() {
void ModbusController::on_modbus_data(const std::vector<uint8_t> &data) { void ModbusController::on_modbus_data(const std::vector<uint8_t> &data) {
auto &current_command = this->command_queue_.front(); auto &current_command = this->command_queue_.front();
if (current_command != nullptr) { if (current_command != nullptr) {
if (this->module_offline_) {
ESP_LOGW(TAG, "Modbus device=%d back online", this->address_);
if (this->offline_skip_updates_ > 0) {
// Restore skip_updates_counter to restore commands updates
for (auto &r : this->register_ranges_) {
r.skip_updates_counter = 0;
}
}
}
this->module_offline_ = false;
// Move the commandItem to the response queue // Move the commandItem to the response queue
current_command->payload = data; current_command->payload = data;
this->incoming_queue_.push(std::move(current_command)); this->incoming_queue_.push(std::move(current_command));

View file

@ -409,7 +409,6 @@ class ModbusCommandItem {
class ModbusController : public PollingComponent, public modbus::ModbusDevice { class ModbusController : public PollingComponent, public modbus::ModbusDevice {
public: public:
ModbusController(uint16_t throttle = 0) : command_throttle_(throttle){};
void dump_config() override; void dump_config() override;
void loop() override; void loop() override;
void setup() override; void setup() override;
@ -431,6 +430,12 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
const std::vector<uint8_t> &data); const std::vector<uint8_t> &data);
/// called by esphome generated code to set the command_throttle period /// called by esphome generated code to set the command_throttle period
void set_command_throttle(uint16_t command_throttle) { this->command_throttle_ = command_throttle; } void set_command_throttle(uint16_t command_throttle) { this->command_throttle_ = command_throttle; }
/// called by esphome generated code to set the offline_skip_updates
void set_offline_skip_updates(uint16_t offline_skip_updates) { this->offline_skip_updates_ = offline_skip_updates; }
/// get the number of queued modbus commands (should be mostly empty)
size_t get_command_queue_length() { return command_queue_.size(); }
/// get if the module is offline, didn't respond the last command
bool get_module_offline() { return module_offline_; }
protected: protected:
/// parse sensormap_ and create range of sequential addresses /// parse sensormap_ and create range of sequential addresses
@ -443,8 +448,6 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
void process_modbus_data_(const ModbusCommandItem *response); void process_modbus_data_(const ModbusCommandItem *response);
/// send the next modbus command from the send queue /// send the next modbus command from the send queue
bool send_next_command_(); bool send_next_command_();
/// get the number of queued modbus commands (should be mostly empty)
size_t get_command_queue_length_() { return command_queue_.size(); }
/// dump the parsed sensormap for diagnostics /// dump the parsed sensormap for diagnostics
void dump_sensors_(); void dump_sensors_();
/// Collection of all sensors for this component /// Collection of all sensors for this component
@ -459,6 +462,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
uint32_t last_command_timestamp_; uint32_t last_command_timestamp_;
/// min time in ms between sending modbus commands /// min time in ms between sending modbus commands
uint16_t command_throttle_; uint16_t command_throttle_;
/// if module didn't respond the last command
bool module_offline_;
/// how many updates to skip if module is offline
uint16_t offline_skip_updates_;
}; };
/** Convert vector<uint8_t> response payload to float. /** Convert vector<uint8_t> response payload to float.

View file

@ -71,7 +71,8 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data(); const auto *mopeka_data = (const mopeka_std_package *) manu_data.data.data();
const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF; const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF;
if (static_cast<SensorType>(hardware_id) != STANDARD && static_cast<SensorType>(hardware_id) != XL) { if (static_cast<SensorType>(hardware_id) != STANDARD && static_cast<SensorType>(hardware_id) != XL &&
static_cast<SensorType>(hardware_id) != ETRAILER) {
ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id); ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id);
return false; return false;
} }

View file

@ -14,6 +14,7 @@ namespace mopeka_std_check {
enum SensorType { enum SensorType {
STANDARD = 0x02, STANDARD = 0x02,
XL = 0x03, XL = 0x03,
ETRAILER = 0x46,
}; };
// 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long. // 4 values in one struct so it aligns to 8 byte. One `mopeka_std_values` is 40 bit long.

View file

@ -273,8 +273,8 @@ async def to_code(config):
await cg.register_component(var, config) await cg.register_component(var, config)
# Add required libraries for ESP8266 # Add required libraries for ESP8266
if CORE.is_esp8266: if CORE.is_esp8266:
# https://github.com/OttoWinter/async-mqtt-client/blob/master/library.json # https://github.com/heman/async-mqtt-client/blob/master/library.json
cg.add_library("ottowinter/AsyncMqttClient-esphome", "0.8.6") cg.add_library("heman/AsyncMqttClient-esphome", "1.0.0")
cg.add_define("USE_MQTT") cg.add_define("USE_MQTT")
cg.add_global(mqtt_ns.using) cg.add_global(mqtt_ns.using)

View file

@ -168,15 +168,10 @@ void MQTTClientComponent::start_dnslookup_() {
case ERR_OK: { case ERR_OK: {
// Got IP immediately // Got IP immediately
this->dns_resolved_ = true; this->dns_resolved_ = true;
#ifdef USE_ESP32
#if LWIP_IPV6 #if LWIP_IPV6
this->ip_ = addr.u_addr.ip4.addr; this->ip_ = addr.u_addr.ip4.addr;
#else #else
this->ip_ = addr.addr; this->ip_ = addr.addr;
#endif
#endif
#ifdef USE_ESP8266
this->ip_ = addr.addr;
#endif #endif
this->start_connect_(); this->start_connect_();
return; return;
@ -228,15 +223,10 @@ void MQTTClientComponent::dns_found_callback(const char *name, const ip_addr_t *
if (ipaddr == nullptr) { if (ipaddr == nullptr) {
a_this->dns_resolve_error_ = true; a_this->dns_resolve_error_ = true;
} else { } else {
#ifdef USE_ESP32
#if LWIP_IPV6 #if LWIP_IPV6
a_this->ip_ = ipaddr->u_addr.ip4.addr; a_this->ip_ = ipaddr->u_addr.ip4.addr;
#else #else
a_this->ip_ = ipaddr->addr; a_this->ip_ = ipaddr->addr;
#endif
#endif // USE_ESP32
#ifdef USE_ESP8266
a_this->ip_ = ipaddr->addr;
#endif #endif
a_this->dns_resolved_ = true; a_this->dns_resolved_ = true;
} }

View file

@ -15,22 +15,23 @@ IPAddress = network_ns.class_("IPAddress")
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.SplitDefault(CONF_ENABLE_IPV6, esp32=False): cv.All( cv.Optional(CONF_ENABLE_IPV6, default=False): cv.boolean,
cv.only_on_esp32, cv.boolean
),
} }
) )
async def to_code(config): async def to_code(config):
if CONF_ENABLE_IPV6 in config: cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6])
cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6]) if CORE.using_esp_idf:
if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6])
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) add_idf_sdkconfig_option(
add_idf_sdkconfig_option( "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6]
"CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] )
) else:
else: if config[CONF_ENABLE_IPV6]:
if config[CONF_ENABLE_IPV6]: cg.add_build_flag("-DCONFIG_LWIP_IPV6")
cg.add_build_flag("-DCONFIG_LWIP_IPV6") cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG")
cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") if CORE.is_rp2040:
cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6")
if CORE.is_esp8266:
cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY")

View file

@ -11,6 +11,9 @@ void PulseMeterSensor::setup() {
this->pin_->setup(); this->pin_->setup();
this->isr_pin_ = pin_->to_isr(); this->isr_pin_ = pin_->to_isr();
// Set the last processed edge to now for the first timeout
this->last_processed_edge_us_ = micros();
if (this->filter_mode_ == FILTER_EDGE) { if (this->filter_mode_ == FILTER_EDGE) {
this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE); this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE);
} else if (this->filter_mode_ == FILTER_PULSE) { } else if (this->filter_mode_ == FILTER_PULSE) {
@ -38,12 +41,16 @@ void PulseMeterSensor::loop() {
} }
// We need to detect at least two edges to have a valid pulse width // We need to detect at least two edges to have a valid pulse width
if (!this->initialized_) { switch (this->meter_state_) {
this->initialized_ = true; case MeterState::INITIAL:
} else { case MeterState::TIMED_OUT: {
uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_; this->meter_state_ = MeterState::RUNNING;
float pulse_width_us = delta_us / float(this->get_->count_); } break;
this->publish_state((60.0f * 1000000.0f) / pulse_width_us); case MeterState::RUNNING: {
uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_;
float pulse_width_us = delta_us / float(this->get_->count_);
this->publish_state((60.0f * 1000000.0f) / pulse_width_us);
} break;
} }
this->last_processed_edge_us_ = this->get_->last_detected_edge_us_; this->last_processed_edge_us_ = this->get_->last_detected_edge_us_;
@ -53,10 +60,18 @@ void PulseMeterSensor::loop() {
const uint32_t now = micros(); const uint32_t now = micros();
const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_; const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_;
if (this->initialized_ && time_since_valid_edge_us > this->timeout_us_) { switch (this->meter_state_) {
ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000); // Running and initial states can timeout
this->initialized_ = false; case MeterState::INITIAL:
this->publish_state(0.0f); case MeterState::RUNNING: {
if (time_since_valid_edge_us > this->timeout_us_) {
this->meter_state_ = MeterState::TIMED_OUT;
ESP_LOGD(TAG, "No pulse detected for %us, assuming 0 pulses/min", time_since_valid_edge_us / 1000000);
this->publish_state(0.0f);
}
} break;
default:
break;
} }
} }
} }

View file

@ -38,7 +38,8 @@ class PulseMeterSensor : public sensor::Sensor, public Component {
InternalFilterMode filter_mode_{FILTER_EDGE}; InternalFilterMode filter_mode_{FILTER_EDGE};
// Variables used in the loop // Variables used in the loop
bool initialized_ = false; enum class MeterState { INITIAL, RUNNING, TIMED_OUT };
MeterState meter_state_ = MeterState::INITIAL;
uint32_t total_pulses_ = 0; uint32_t total_pulses_ = 0;
uint32_t last_processed_edge_us_ = 0; uint32_t last_processed_edge_us_ = 0;

View file

@ -10,7 +10,7 @@ static const char *const TAG = "radon_eye_ble";
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
if (not device.get_name().empty()) { if (not device.get_name().empty()) {
if (device.get_name().rfind("FR:R20:SN", 0) == 0) { if (device.get_name().rfind("FR:R", 0) == 0) {
// This is an RD200, I think // This is an RD200, I think
ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(), ESP_LOGD(TAG, "Found Radon Eye RD200 device Name: %s (MAC: %s)", device.get_name().c_str(),
device.address_str().c_str()); device.address_str().c_str());

View file

@ -57,6 +57,10 @@ KNOWN_FIRMWARE = {
"https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin", "https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.6/shelly-dimmer-stm32_v51.6.bin",
"eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36", "eda483e111c914723a33f5088f1397d5c0b19333db4a88dc965636b976c16c36",
), ),
"51.7": (
"https://github.com/jamesturton/shelly-dimmer-stm32/releases/download/v51.7/shelly-dimmer-stm32_v51.7.bin",
"7a20f1c967c469917368a79bc56498009045237080408cef7190743e08031889",
),
} }

View file

@ -12,6 +12,8 @@ from esphome.const import (
UNIT_PERCENT, UNIT_PERCENT,
) )
CONF_HEATER_ENABLED = "heater_enabled"
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["sensirion_common"] AUTO_LOAD = ["sensirion_common"]
@ -36,7 +38,8 @@ CONFIG_SCHEMA = (
device_class=DEVICE_CLASS_HUMIDITY, device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
} cv.Optional(CONF_HEATER_ENABLED, default=True): cv.boolean,
},
) )
.extend(cv.polling_component_schema("60s")) .extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x44)) .extend(i2c.i2c_device_schema(0x44))
@ -48,6 +51,8 @@ async def to_code(config):
await cg.register_component(var, config) await cg.register_component(var, config)
await i2c.register_i2c_device(var, config) await i2c.register_i2c_device(var, config)
cg.add(var.set_heater_enabled(config[CONF_HEATER_ENABLED]))
if CONF_TEMPERATURE in config: if CONF_TEMPERATURE in config:
sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
cg.add(var.set_temperature_sensor(sens)) cg.add(var.set_temperature_sensor(sens))

View file

@ -22,6 +22,10 @@ void SHT3XDComponent::setup() {
this->mark_failed(); this->mark_failed();
return; return;
} }
if (!this->write_command(heater_enabled_ ? SHT3XD_COMMAND_HEATER_ENABLE : SHT3XD_COMMAND_HEATER_DISABLE)) {
this->mark_failed();
return;
}
uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]); uint32_t serial_number = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]);
ESP_LOGV(TAG, " Serial Number: 0x%08X", serial_number); ESP_LOGV(TAG, " Serial Number: 0x%08X", serial_number);
} }

View file

@ -17,10 +17,12 @@ class SHT3XDComponent : public PollingComponent, public sensirion_common::Sensir
void dump_config() override; void dump_config() override;
float get_setup_priority() const override; float get_setup_priority() const override;
void update() override; void update() override;
void set_heater_enabled(bool heater_enabled) { heater_enabled_ = heater_enabled; }
protected: protected:
sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr};
bool heater_enabled_{true};
}; };
} // namespace sht3xd } // namespace sht3xd

View file

@ -60,7 +60,7 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po
memset(server, 0, sizeof(sockaddr_in6)); memset(server, 0, sizeof(sockaddr_in6));
server->sin6_family = AF_INET6; server->sin6_family = AF_INET6;
server->sin6_port = htons(port); server->sin6_port = htons(port);
server->sin6_addr = in6addr_any; server->sin6_addr = IN6ADDR_ANY_INIT;
return sizeof(sockaddr_in6); return sizeof(sockaddr_in6);
#else #else
if (addrlen < sizeof(sockaddr_in)) { if (addrlen < sizeof(sockaddr_in)) {

View file

@ -14,8 +14,8 @@ SX1509BinarySensor = sx1509_ns.class_("SX1509BinarySensor", binary_sensor.Binary
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(SX1509BinarySensor).extend( CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(SX1509BinarySensor).extend(
{ {
cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component),
cv.Required(CONF_ROW): cv.int_range(min=0, max=4), cv.Required(CONF_ROW): cv.int_range(min=0, max=7),
cv.Required(CONF_COL): cv.int_range(min=0, max=4), cv.Required(CONF_COL): cv.int_range(min=0, max=7),
} }
) )

View file

@ -986,6 +986,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
// Fire any preset changed trigger if defined // Fire any preset changed trigger if defined
Trigger<> *trig = this->preset_change_trigger_; Trigger<> *trig = this->preset_change_trigger_;
assert(trig != nullptr); assert(trig != nullptr);
this->preset = preset;
trig->trigger(); trig->trigger();
this->refresh(); this->refresh();
@ -1010,6 +1011,7 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset)
// Fire any preset changed trigger if defined // Fire any preset changed trigger if defined
Trigger<> *trig = this->preset_change_trigger_; Trigger<> *trig = this->preset_change_trigger_;
assert(trig != nullptr); assert(trig != nullptr);
this->custom_preset = custom_preset;
trig->trigger(); trig->trigger();
this->refresh(); this->refresh();

View file

@ -1561,6 +1561,23 @@ void WaveshareEPaper7P5In::dump_config() {
LOG_PIN(" Busy Pin: ", this->busy_pin_); LOG_PIN(" Busy Pin: ", this->busy_pin_);
LOG_UPDATE_INTERVAL(this); LOG_UPDATE_INTERVAL(this);
} }
bool WaveshareEPaper7P5InV2::wait_until_idle_() {
if (this->busy_pin_ == nullptr) {
return true;
}
const uint32_t start = millis();
while (this->busy_pin_->digital_read()) {
this->command(0x71);
if (millis() - start > this->idle_timeout_()) {
ESP_LOGE(TAG, "Timeout while displaying image!");
return false;
}
App.feed_wdt();
delay(10);
}
return true;
}
void WaveshareEPaper7P5InV2::initialize() { void WaveshareEPaper7P5InV2::initialize() {
// COMMAND POWER SETTING // COMMAND POWER SETTING
this->command(0x01); this->command(0x01);
@ -1568,10 +1585,21 @@ void WaveshareEPaper7P5InV2::initialize() {
this->data(0x07); this->data(0x07);
this->data(0x3f); this->data(0x3f);
this->data(0x3f); this->data(0x3f);
this->command(0x04);
// We don't want the display to be powered at this point
delay(100); // NOLINT delay(100); // NOLINT
this->wait_until_idle_(); this->wait_until_idle_();
// COMMAND VCOM AND DATA INTERVAL SETTING
this->command(0x50);
this->data(0x10);
this->data(0x07);
// COMMAND TCON SETTING
this->command(0x60);
this->data(0x22);
// COMMAND PANEL SETTING // COMMAND PANEL SETTING
this->command(0x00); this->command(0x00);
this->data(0x1F); this->data(0x1F);
@ -1582,19 +1610,30 @@ void WaveshareEPaper7P5InV2::initialize() {
this->data(0x20); this->data(0x20);
this->data(0x01); this->data(0x01);
this->data(0xE0); this->data(0xE0);
// COMMAND ...?
// COMMAND DUAL SPI MM_EN, DUSPI_EN
this->command(0x15); this->command(0x15);
this->data(0x00); this->data(0x00);
// COMMAND VCOM AND DATA INTERVAL SETTING
this->command(0x50); // COMMAND POWER DRIVER HAT DOWN
this->data(0x10); // This command will turn off booster, controller, source driver, gate driver, VCOM, and
this->data(0x07); // temperature sensor, but register data will be kept until VDD turned OFF or Deep Sleep Mode.
// COMMAND TCON SETTING // Source/Gate/Border/VCOM will be released to floating.
this->command(0x60); this->command(0x02);
this->data(0x22);
} }
void HOT WaveshareEPaper7P5InV2::display() { void HOT WaveshareEPaper7P5InV2::display() {
uint32_t buf_len = this->get_buffer_length_(); uint32_t buf_len = this->get_buffer_length_();
// COMMAND POWER ON
ESP_LOGI(TAG, "Power on the display and hat");
// This command will turn on booster, controller, regulators, and temperature sensor will be
// activated for one-time sensing before enabling booster. When all voltages are ready, the
// BUSY_N signal will return to high.
this->command(0x04);
delay(200); // NOLINT
this->wait_until_idle_();
// COMMAND DATA START TRANSMISSION NEW DATA // COMMAND DATA START TRANSMISSION NEW DATA
this->command(0x13); this->command(0x13);
delay(2); delay(2);
@ -1602,14 +1641,23 @@ void HOT WaveshareEPaper7P5InV2::display() {
this->data(~(this->buffer_[i])); this->data(~(this->buffer_[i]));
} }
delay(100); // NOLINT
this->wait_until_idle_();
// COMMAND DISPLAY REFRESH // COMMAND DISPLAY REFRESH
this->command(0x12); this->command(0x12);
delay(100); // NOLINT delay(100); // NOLINT
this->wait_until_idle_(); this->wait_until_idle_();
ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
this->command(0x02);
this->wait_until_idle_();
ESP_LOGV(TAG, "After command(0x02) (>> power off)");
} }
int WaveshareEPaper7P5InV2::get_width_internal() { return 800; } int WaveshareEPaper7P5InV2::get_width_internal() { return 800; }
int WaveshareEPaper7P5InV2::get_height_internal() { return 480; } int WaveshareEPaper7P5InV2::get_height_internal() { return 480; }
uint32_t WaveshareEPaper7P5InV2::idle_timeout_() { return 10000; }
void WaveshareEPaper7P5InV2::dump_config() { void WaveshareEPaper7P5InV2::dump_config() {
LOG_DISPLAY("", "Waveshare E-Paper", this); LOG_DISPLAY("", "Waveshare E-Paper", this);
ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2"); ESP_LOGCONFIG(TAG, " Model: 7.5inV2rev2");

View file

@ -472,6 +472,8 @@ class WaveshareEPaper7P5InBC : public WaveshareEPaper {
class WaveshareEPaper7P5InV2 : public WaveshareEPaper { class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
public: public:
bool wait_until_idle_();
void initialize() override; void initialize() override;
void display() override; void display() override;
@ -491,6 +493,8 @@ class WaveshareEPaper7P5InV2 : public WaveshareEPaper {
int get_width_internal() override; int get_width_internal() override;
int get_height_internal() override; int get_height_internal() override;
uint32_t idle_timeout_() override;
}; };
class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 { class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 {

View file

@ -59,7 +59,7 @@ CONFIG_SCHEMA = cv.All(
{ {
cv.GenerateID(): cv.declare_id(WebServer), cv.GenerateID(): cv.declare_id(WebServer),
cv.Optional(CONF_PORT, default=80): cv.port, cv.Optional(CONF_PORT, default=80): cv.port,
cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2), cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2, int=True),
cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_URL): cv.string,
cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_CSS_INCLUDE): cv.file_,
cv.Optional(CONF_JS_URL): cv.string, cv.Optional(CONF_JS_URL): cv.string,

View file

@ -19,6 +19,7 @@ extern "C" {
#include "lwip/apps/sntp.h" #include "lwip/apps/sntp.h"
#if LWIP_IPV6 #if LWIP_IPV6
#include "lwip/netif.h" // struct netif #include "lwip/netif.h" // struct netif
#include <AddrList.h>
#endif #endif
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0) #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0)
#include "LwipDhcpServer.h" #include "LwipDhcpServer.h"
@ -97,6 +98,7 @@ bool WiFiComponent::wifi_apply_power_save_() {
power_save = NONE_SLEEP_T; power_save = NONE_SLEEP_T;
break; break;
} }
wifi_fpm_auto_sleep_set_in_null_mode(1);
return wifi_set_sleep_type(power_save); return wifi_set_sleep_type(power_save);
} }
@ -164,11 +166,11 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
ip_addr_t dns; ip_addr_t dns;
if (uint32_t(manual_ip->dns1) != 0) { if (uint32_t(manual_ip->dns1) != 0) {
dns.addr = static_cast<uint32_t>(manual_ip->dns1); ip_addr_set_ip4_u32_val(dns, static_cast<uint32_t>(manual_ip->dns1));
dns_setserver(0, &dns); dns_setserver(0, &dns);
} }
if (uint32_t(manual_ip->dns2) != 0) { if (uint32_t(manual_ip->dns2) != 0) {
dns.addr = static_cast<uint32_t>(manual_ip->dns2); ip_addr_set_ip4_u32_val(dns, static_cast<uint32_t>(manual_ip->dns2));
dns_setserver(1, &dns); dns_setserver(1, &dns);
} }
@ -325,6 +327,18 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
return false; return false;
} }
#if ENABLE_IPV6
for (bool configured = false; !configured;) {
for (auto addr : addrList) {
ESP_LOGV(TAG, "Address %s", addr.toString().c_str());
if ((configured = !addr.isLocal() && addr.isV6())) {
break;
}
}
delay(500); // NOLINT
}
#endif
if (ap.get_channel().has_value()) { if (ap.get_channel().has_value()) {
ret = wifi_set_channel(*ap.get_channel()); ret = wifi_set_channel(*ap.get_channel());
if (!ret) { if (!ret) {

View file

@ -175,7 +175,11 @@ network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask(
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; } network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; }
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { network::IPAddress WiFiComponent::wifi_dns_ip_(int num) {
const ip_addr_t *dns_ip = dns_getserver(num); const ip_addr_t *dns_ip = dns_getserver(num);
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
return {dns_ip->u_addr.ip4.addr};
#else
return {dns_ip->addr}; return {dns_ip->addr};
#endif
} }
void WiFiComponent::wifi_loop_() { void WiFiComponent::wifi_loop_() {

View file

@ -1,6 +1,6 @@
"""Constants used by esphome.""" """Constants used by esphome."""
__version__ = "2023.9.0-dev" __version__ = "2023.10.0-dev"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = ( VALID_SUBSTITUTIONS_CHARACTERS = (

View file

@ -57,7 +57,7 @@ class SimpleRegistry(dict):
return decorator return decorator
def safe_print(message=""): def safe_print(message="", end="\n"):
from esphome.core import CORE from esphome.core import CORE
if CORE.dashboard: if CORE.dashboard:
@ -67,20 +67,26 @@ def safe_print(message=""):
pass pass
try: try:
print(message) print(message, end=end)
return return
except UnicodeEncodeError: except UnicodeEncodeError:
pass pass
try: try:
print(message.encode("utf-8", "backslashreplace")) print(message.encode("utf-8", "backslashreplace"), end=end)
except UnicodeEncodeError: except UnicodeEncodeError:
try: try:
print(message.encode("ascii", "backslashreplace")) print(message.encode("ascii", "backslashreplace"), end=end)
except UnicodeEncodeError: except UnicodeEncodeError:
print("Cannot print line because of invalid locale!") print("Cannot print line because of invalid locale!")
def safe_input(prompt=""):
if prompt:
safe_print(prompt, end="")
return input()
def shlex_quote(s): def shlex_quote(s):
if not s: if not s:
return "''" return "''"

View file

@ -11,7 +11,7 @@ from esphome.core import CORE
from esphome.helpers import get_bool_env, write_file from esphome.helpers import get_bool_env, write_file
from esphome.log import Fore, color from esphome.log import Fore, color
from esphome.storage_json import StorageJSON, ext_storage_path from esphome.storage_json import StorageJSON, ext_storage_path
from esphome.util import safe_print from esphome.util import safe_input, safe_print
CORE_BIG = r""" _____ ____ _____ ______ CORE_BIG = r""" _____ ____ _____ ______
/ ____/ __ \| __ \| ____| / ____/ __ \| __ \| ____|
@ -252,7 +252,7 @@ def safe_print_step(step, big):
def default_input(text, default): def default_input(text, default):
safe_print() safe_print()
safe_print(f"Press ENTER for default ({default})") safe_print(f"Press ENTER for default ({default})")
return input(text.format(default)) or default return safe_input(text.format(default)) or default
# From https://stackoverflow.com/a/518232/8924614 # From https://stackoverflow.com/a/518232/8924614
@ -306,7 +306,7 @@ def wizard(path):
) )
safe_print() safe_print()
sleep(1) sleep(1)
name = input(color(Fore.BOLD_WHITE, "(name): ")) name = safe_input(color(Fore.BOLD_WHITE, "(name): "))
while True: while True:
try: try:
@ -343,7 +343,9 @@ def wizard(path):
while True: while True:
sleep(0.5) sleep(0.5)
safe_print() safe_print()
platform = input(color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")) platform = safe_input(
color(Fore.BOLD_WHITE, f"({'/'.join(wizard_platforms)}): ")
)
try: try:
platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper()) platform = vol.All(vol.Upper, vol.Any(*wizard_platforms))(platform.upper())
break break
@ -397,7 +399,7 @@ def wizard(path):
boards.append(board_id) boards.append(board_id)
while True: while True:
board = input(color(Fore.BOLD_WHITE, "(board): ")) board = safe_input(color(Fore.BOLD_WHITE, "(board): "))
try: try:
board = vol.All(vol.Lower, vol.Any(*boards))(board) board = vol.All(vol.Lower, vol.Any(*boards))(board)
break break
@ -423,7 +425,7 @@ def wizard(path):
sleep(1.5) sleep(1.5)
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".")
while True: while True:
ssid = input(color(Fore.BOLD_WHITE, "(ssid): ")) ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): "))
try: try:
ssid = cv.ssid(ssid) ssid = cv.ssid(ssid)
break break
@ -449,7 +451,7 @@ def wizard(path):
safe_print() safe_print()
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"") safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'PASSWORD42')}\"")
sleep(0.5) sleep(0.5)
psk = input(color(Fore.BOLD_WHITE, "(PSK): ")) psk = safe_input(color(Fore.BOLD_WHITE, "(PSK): "))
safe_print( safe_print(
"Perfect! WiFi is now set up (you can create static IPs and so on later)." "Perfect! WiFi is now set up (you can create static IPs and so on later)."
) )
@ -466,7 +468,7 @@ def wizard(path):
safe_print() safe_print()
sleep(0.25) sleep(0.25)
safe_print("Press ENTER for no password") safe_print("Press ENTER for no password")
password = input(color(Fore.BOLD_WHITE, "(password): ")) password = safe_input(color(Fore.BOLD_WHITE, "(password): "))
if not wizard_write( if not wizard_write(
path=path, path=path,

View file

@ -57,6 +57,7 @@ lib_deps =
${common.lib_deps} ${common.lib_deps}
SPI ; spi (Arduino built-in) SPI ; spi (Arduino built-in)
Wire ; i2c (Arduino built-int) Wire ; i2c (Arduino built-int)
heman/AsyncMqttClient-esphome@1.0.0 ; mqtt
esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base
fastled/FastLED@3.3.2 ; fastled_base fastled/FastLED@3.3.2 ; fastled_base
mikalhart/TinyGPSPlus@1.0.2 ; gps mikalhart/TinyGPSPlus@1.0.2 ; gps
@ -88,8 +89,7 @@ lib_deps =
${common:arduino.lib_deps} ${common:arduino.lib_deps}
ESP8266WiFi ; wifi (Arduino built-in) ESP8266WiFi ; wifi (Arduino built-in)
Update ; ota (Arduino built-in) Update ; ota (Arduino built-in)
ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt esphome/ESPAsyncTCP-esphome@2.0.0 ; async_tcp
esphome/ESPAsyncTCP-esphome@1.2.3 ; async_tcp
ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266HTTPClient ; http_request (Arduino built-in)
ESP8266mDNS ; mdns (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in)
DNSServer ; captive_portal (Arduino built-in) DNSServer ; captive_portal (Arduino built-in)

View file

@ -11,7 +11,7 @@ esptool==4.6.2
click==8.1.7 click==8.1.7
esphome-dashboard==20230904.0 esphome-dashboard==20230904.0
aioesphomeapi==15.0.0 aioesphomeapi==15.0.0
zeroconf==0.102.0 zeroconf==0.108.0
# esp-idf requires this, but doesn't bundle it by default # esp-idf requires this, but doesn't bundle it by default
# https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24

View file

@ -1,6 +1,6 @@
pylint==2.17.5 pylint==2.17.5
flake8==6.1.0 # also change in .pre-commit-config.yaml when updating flake8==6.1.0 # also change in .pre-commit-config.yaml when updating
black==23.7.0 # also change in .pre-commit-config.yaml when updating black==23.9.1 # also change in .pre-commit-config.yaml when updating
pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating pyupgrade==3.10.1 # also change in .pre-commit-config.yaml when updating
pre-commit pre-commit

697
tests/test11.5.yaml Normal file
View file

@ -0,0 +1,697 @@
---
# copy of test5.yaml configured to build on IDF 5
esphome:
name: test11-5
build_path: build/test11.5
project:
name: esphome.test11_5_project
version: "1.0.0"
esp32:
board: nodemcu-32s
framework:
type: esp-idf
version: 5.0.2
platform_version: 6.3.2
advanced:
ignore_efuse_mac_crc: true
wifi:
networks:
- ssid: "MySSID"
password: "password1"
manual_ip:
static_ip: 192.168.1.23
gateway: 192.168.1.1
subnet: 255.255.255.0
api:
ota:
logger:
debug:
psram:
uart:
- id: uart_1
tx_pin: 1
rx_pin: 3
baud_rate: 9600
- id: uart_2
tx_pin: 17
rx_pin: 16
baud_rate: 19200
i2c:
frequency: 100khz
modbus:
uart_id: uart_1
flow_control_pin: 5
id: mod_bus1
modbus_controller:
- id: modbus_controller_test
address: 0x2
modbus_id: mod_bus1
mqtt:
broker: test.mosquitto.org
port: 1883
discovery: true
discovery_prefix: homeassistant
idf_send_async: false
on_message:
topic: testing/sensor/testing_sensor/state
qos: 0
then:
# yamllint disable rule:line-length
- lambda: |-
ESP_LOGD("Mqtt Test", "testing/sensor/testing_sensor/state=[%s]", x.c_str());
# yamllint enable rule:line-length
vbus:
- uart_id: uart_2
binary_sensor:
- platform: gpio
pin: GPIO0
id: io0_button
icon: mdi:gesture-tap-button
- platform: modbus_controller
modbus_controller_id: modbus_controller_test
id: modbus_binsensortest
register_type: read
address: 0x3200
bitmask: 0x80 # (bit 8)
lambda: "return x;"
- platform: tm1638
id: Button0
key: 0
filters:
- delayed_on: 10ms
on_press:
then:
- switch.turn_on: Led0
on_release:
then:
- switch.turn_off: Led0
- platform: tm1638
id: Button1
key: 1
on_press:
then:
- switch.turn_on: Led1
on_release:
then:
- switch.turn_off: Led1
- platform: tm1638
id: Button2
key: 2
on_press:
then:
- switch.turn_on: Led2
on_release:
then:
- switch.turn_off: Led2
- platform: tm1638
id: Button3
key: 3
on_press:
then:
- switch.turn_on: Led3
on_release:
then:
- switch.turn_off: Led3
- platform: tm1638
id: Button4
key: 4
on_press:
then:
- output.turn_on: Led4
on_release:
then:
- output.turn_off: Led4
- platform: tm1638
id: Button5
key: 5
on_press:
then:
- output.turn_on: Led5
on_release:
then:
- output.turn_off: Led5
- platform: tm1638
id: Button6
key: 6
on_press:
then:
- output.turn_on: Led6
on_release:
then:
- output.turn_off: Led6
- platform: tm1638
id: Button7
key: 7
on_press:
then:
- output.turn_on: Led7
on_release:
then:
- output.turn_off: Led7
- platform: gpio
id: sn74hc165_pin_0
pin:
sn74hc165: sn74hc165_hub
number: 0
- platform: ezo_pmp
pump_state:
name: "Pump State"
is_paused:
name: "Is Paused"
- platform: matrix_keypad
keypad_id: keypad
id: key4
row: 1
col: 1
- platform: matrix_keypad
id: key1
key: 1
- platform: vbus
model: deltasol_bs_plus
relay2:
name: Relay 2 On
sensor1_error:
name: Sensor 1 Error
- platform: vbus
model: custom
command: 0x100
source: 0x1234
dest: 0x10
binary_sensors:
- id: vcustom_b
name: VBus Custom Binary Sensor
lambda: return x[0] & 1;
tlc5947:
data_pin: GPIO12
clock_pin: GPIO14
lat_pin: GPIO15
gp8403:
- id: gp8403_5v
voltage: 5V
- id: gp8403_10v
voltage: 10V
output:
- platform: gpio
pin: GPIO2
id: built_in_led
- platform: tlc5947
id: output_red
channel: 0
max_power: 0.8
- platform: mcp47a1
id: output_mcp47a1
- platform: modbus_controller
modbus_controller_id: modbus_controller_test
id: modbus_output_test
lambda: |-
return x * 1.0 ;
address: 0x9001
value_type: U_WORD
- platform: tm1638
id: Led4
led: 4
- platform: tm1638
id: Led5
led: 5
- platform: tm1638
id: Led6
led: 6
- platform: tm1638
id: Led7
led: 7
- platform: gp8403
id: gp8403_output_0
gp8403_id: gp8403_5v
channel: 0
- platform: gp8403
gp8403_id: gp8403_10v
id: gp8403_output_1
channel: 1
demo:
esp32_ble:
esp32_ble_server:
manufacturer: ESPHome
model: Test11
esp32_improv:
authorizer: io0_button
authorized_duration: 1min
status_indicator: built_in_led
ezo_pmp:
id: hcl_pump
update_interval: 1s
number:
- platform: template
name: My template number
id: template_number_id
optimistic: true
max_value: 100
min_value: 0
step: 5
unit_of_measurement: "%"
mode: slider
device_class: humidity
on_value:
- logger.log:
format: Number changed to %f
args: [x]
set_action:
- logger.log:
format: Template Number set to %f
args: [x]
- number.set:
id: template_number_id
value: 50
- number.to_min: template_number_id
- number.to_min:
id: template_number_id
- number.to_max: template_number_id
- number.to_max:
id: template_number_id
- number.increment: template_number_id
- number.increment:
id: template_number_id
cycle: false
- number.decrement: template_number_id
- number.decrement:
id: template_number_id
cycle: false
- number.operation:
id: template_number_id
operation: Increment
cycle: false
- number.operation:
id: template_number_id
operation: !lambda "return NUMBER_OP_INCREMENT;"
cycle: !lambda "return false;"
- id: modbus_numbertest
platform: modbus_controller
modbus_controller_id: modbus_controller_test
name: ModbusNumber
address: 0x9002
value_type: U_WORD
lambda: "return x * 1.0;"
write_lambda: |-
return x * 1.0 ;
multiply: 1.0
select:
- platform: template
name: My template select
id: template_select_id
optimistic: true
initial_option: two
restore_value: true
on_value:
- logger.log:
format: Select changed to %s (index %d)"
args: ["x.c_str()", "i"]
set_action:
- logger.log:
format: Template Select set to %s
args: ["x.c_str()"]
- select.set:
id: template_select_id
option: two
- select.first: template_select_id
- select.last:
id: template_select_id
- select.previous: template_select_id
- select.next:
id: template_select_id
cycle: false
- select.operation:
id: template_select_id
operation: Previous
cycle: false
- select.operation:
id: template_select_id
operation: !lambda "return SELECT_OP_PREVIOUS;"
cycle: !lambda "return true;"
- select.set_index:
id: template_select_id
index: 1
- select.set_index:
id: template_select_id
index: !lambda "return 1 + 1;"
options:
- one
- two
- three
- platform: modbus_controller
name: Modbus Select Register 1000
address: 1000
value_type: U_WORD
optionsmap:
"Zero": 0
"One": 1
"Two": 2
"Three": 3
sensor:
- platform: adc
id: adc_sensor_p32
name: ADC pin 32
pin: 32
attenuation: 11db
update_interval: 1s
- platform: internal_temperature
name: Internal Temperature
- platform: selec_meter
total_active_energy:
name: SelecEM2M Total Active Energy
import_active_energy:
name: SelecEM2M Import Active Energy
export_active_energy:
name: SelecEM2M Export Active Energy
total_reactive_energy:
name: SelecEM2M Total Reactive Energy
import_reactive_energy:
name: SelecEM2M Import Reactive Energy
export_reactive_energy:
name: SelecEM2M Export Reactive Energy
apparent_energy:
name: SelecEM2M Apparent Energy
active_power:
name: SelecEM2M Active Power
reactive_power:
name: SelecEM2M Reactive Power
apparent_power:
name: SelecEM2M Apparent Power
voltage:
name: SelecEM2M Voltage
current:
name: SelecEM2M Current
power_factor:
name: SelecEM2M Power Factor
frequency:
name: SelecEM2M Frequency
maximum_demand_active_power:
name: SelecEM2M Maximum Demand Active Power
disabled_by_default: true
maximum_demand_reactive_power:
name: SelecEM2M Maximum Demand Reactive Power
disabled_by_default: true
maximum_demand_apparent_power:
name: SelecEM2M Maximum Demand Apparent Power
disabled_by_default: true
- id: modbus_sensortest
platform: modbus_controller
modbus_controller_id: modbus_controller_test
address: 0x331A
register_type: read
value_type: U_WORD
- platform: t6615
uart_id: uart_2
co2:
name: CO2 Sensor
- platform: bmp3xx
temperature:
name: BMP Temperature
oversampling: 16x
pressure:
name: BMP Pressure
address: 0x77
iir_filter: 2X
- platform: sen5x
id: sen54
temperature:
name: Temperature
accuracy_decimals: 1
humidity:
name: Humidity
accuracy_decimals: 0
pm_1_0:
name: PM <1µm Weight concentration
id: pm_1_0
accuracy_decimals: 1
pm_2_5:
name: PM <2.5µm Weight concentration
id: pm_2_5
accuracy_decimals: 1
pm_4_0:
name: PM <4µm Weight concentration
id: pm_4_0
accuracy_decimals: 1
pm_10_0:
name: PM <10µm Weight concentration
id: pm_10_0
accuracy_decimals: 1
nox:
name: NOx
voc:
name: VOC
algorithm_tuning:
index_offset: 100
learning_time_offset_hours: 12
learning_time_gain_hours: 12
gating_max_duration_minutes: 180
std_initial: 50
gain_factor: 230
temperature_compensation:
offset: 0
normalized_offset_slope: 0
time_constant: 0
auto_cleaning_interval: 604800s
acceleration_mode: low
store_baseline: true
address: 0x69
- platform: mcp9600
thermocouple_type: K
hot_junction:
name: Thermocouple Temperature
cold_junction:
name: Ambient Temperature
- platform: ezo_pmp
current_volume_dosed:
name: Current Volume Dosed
total_volume_dosed:
name: Total Volume Dosed
absolute_total_volume_dosed:
name: Absolute Total Volume Dosed
pump_voltage:
name: Pump Voltage
last_volume_requested:
name: Last Volume Requested
max_flow_rate:
name: Max Flow Rate
- platform: vbus
model: deltasol c
temperature_3:
name: Temperature 3
operating_hours_1:
name: Operating Hours 1
heat_quantity:
name: Heat Quantity
time:
name: System Time
- platform: debug
free:
name: "Heap Free"
block:
name: "Heap Max Block"
loop_time:
name: "Loop Time"
psram:
name: "PSRAM Free"
- platform: vbus
model: custom
command: 0x100
source: 0x1234
dest: 0x10
sensors:
- id: vcustom
name: VBus Custom Sensor
lambda: return x[0] / 10.0;
- platform: kuntze
ph:
name: Kuntze pH
temperature:
name: Kuntze temperature
script:
- id: automation_test
then:
- repeat:
count: 5
then:
- logger.log: looping!
- id: zero_repeat_test
then:
- repeat:
count: !lambda "return 0;"
then:
- logger.log: shouldn't see mee!
switch:
- platform: modbus_controller
modbus_controller_id: modbus_controller_test
id: modbus_switch_test
register_type: coil
address: 2
bitmask: 1
- platform: tm1638
id: Led0
led: 0
name: TM1638Led0
- platform: tm1638
id: Led1
led: 1
name: TM1638Led1
- platform: tm1638
id: Led2
led: 2
name: TM1638Led2
- platform: tm1638
id: Led3
led: 3
name: TM1638Led3
display:
- platform: tm1638
id: primarydisplay
stb_pin: 5 #TM1638 STB
clk_pin: 18 #TM1638 CLK
dio_pin: 23 #TM1638 DIO
update_interval: 5s
intensity: 5
lambda: |-
it.print("81818181");
time:
- platform: pcf85063
- platform: pcf8563
text_sensor:
- platform: ezo_pmp
dosing_mode:
name: Dosing Mode
calibration_status:
name: Calibration Status
on_value:
- ezo_pmp.dose_volume:
id: hcl_pump
volume: 10
- ezo_pmp.dose_volume_over_time:
id: hcl_pump
volume: 10
duration: 2
- ezo_pmp.dose_with_constant_flow_rate:
id: hcl_pump
volume_per_minute: 10
duration: 2
- ezo_pmp.set_calibration_volume:
id: hcl_pump
volume: 10
- ezo_pmp.find: hcl_pump
- ezo_pmp.dose_continuously: hcl_pump
- ezo_pmp.clear_total_volume_dosed: hcl_pump
- ezo_pmp.clear_calibration: hcl_pump
- ezo_pmp.pause_dosing: hcl_pump
- ezo_pmp.stop_dosing: hcl_pump
- ezo_pmp.arbitrary_command:
id: hcl_pump
command: D,?
sn74hc165:
id: sn74hc165_hub
data_pin: GPIO12
clock_pin: GPIO14
load_pin: GPIO27
clock_inhibit_pin: GPIO26
sr_count: 4
matrix_keypad:
id: keypad
rows:
- pin: 21
- pin: 19
columns:
- pin: 17
- pin: 16
keys: "1234"
key_collector:
- id: reader
source_id: keypad
min_length: 4
max_length: 4
light:
- platform: esp32_rmt_led_strip
id: led_strip
pin: 13
num_leds: 60
rmt_channel: 6
rgb_order: GRB
chipset: ws2812
- platform: esp32_rmt_led_strip
id: led_strip2
pin: 15
num_leds: 60
rmt_channel: 2
rgb_order: RGB
bit0_high: 100us
bit0_low: 100us
bit1_high: 100us
bit1_low: 100us

View file

@ -392,6 +392,12 @@ select:
"Three": 3 "Three": 3
sensor: sensor:
- platform: adc
id: adc_sensor_p32
name: ADC pin 32
pin: 32
attenuation: 11db
update_interval: 1s
- platform: internal_temperature - platform: internal_temperature
name: Internal Temperature name: Internal Temperature
- platform: selec_meter - platform: selec_meter

View file

@ -319,7 +319,7 @@ def test_wizard_accepts_default_answers_esp8266(tmpdir, monkeypatch, wizard_answ
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())
@ -341,7 +341,7 @@ def test_wizard_accepts_default_answers_esp32(tmpdir, monkeypatch, wizard_answer
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())
@ -371,7 +371,7 @@ def test_wizard_offers_better_node_name(tmpdir, monkeypatch, wizard_answers):
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())
@ -394,7 +394,7 @@ def test_wizard_requires_correct_platform(tmpdir, monkeypatch, wizard_answers):
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())
@ -416,7 +416,7 @@ def test_wizard_requires_correct_board(tmpdir, monkeypatch, wizard_answers):
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())
@ -438,7 +438,7 @@ def test_wizard_requires_valid_ssid(tmpdir, monkeypatch, wizard_answers):
config_file = tmpdir.join("test.yaml") config_file = tmpdir.join("test.yaml")
input_mock = MagicMock(side_effect=wizard_answers) input_mock = MagicMock(side_effect=wizard_answers)
monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr("builtins.input", input_mock)
monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0)
monkeypatch.setattr(wz, "sleep", lambda _: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0)
monkeypatch.setattr(wz, "wizard_write", MagicMock()) monkeypatch.setattr(wz, "wizard_write", MagicMock())