Merge branch 'dev' into as7343

This commit is contained in:
Anton Viktorov 2024-05-20 21:06:46 +00:00 committed by GitHub
commit 215abc5f23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 248 additions and 184 deletions

View File

@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5.1.0
with: with:

View File

@ -40,7 +40,7 @@ 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.1.5 - uses: actions/checkout@v4.1.6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5.1.0
with: with:

View File

@ -34,7 +34,7 @@ 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.1.5 uses: actions/checkout@v4.1.6
- 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
@ -66,7 +66,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -87,7 +87,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -108,7 +108,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -129,7 +129,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -150,7 +150,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -199,7 +199,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -229,7 +229,7 @@ jobs:
- common - common
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -254,7 +254,7 @@ jobs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Find all YAML test files - name: Find all YAML test files
id: set-matrix id: set-matrix
run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
@ -271,7 +271,7 @@ jobs:
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} 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.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -303,7 +303,7 @@ jobs:
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }} 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.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -358,7 +358,7 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -410,7 +410,7 @@ jobs:
count: ${{ steps.list-components.outputs.count }} count: ${{ steps.list-components.outputs.count }}
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
with: with:
# Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works. # Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works.
fetch-depth: 500 fetch-depth: 500
@ -458,7 +458,7 @@ jobs:
run: sudo apt-get install libsodium-dev run: sudo apt-get install libsodium-dev
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:
@ -484,7 +484,7 @@ jobs:
matrix: ${{ steps.split.outputs.components }} matrix: ${{ steps.split.outputs.components }}
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Split components into 20 groups - name: Split components into 20 groups
id: split id: split
run: | run: |
@ -512,7 +512,7 @@ jobs:
run: sudo apt-get install libsodium-dev run: sudo apt-get install libsodium-dev
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Restore Python - name: Restore Python
uses: ./.github/actions/restore-python uses: ./.github/actions/restore-python
with: with:

View File

@ -19,7 +19,7 @@ jobs:
tag: ${{ steps.tag.outputs.tag }} tag: ${{ steps.tag.outputs.tag }}
branch_build: ${{ steps.tag.outputs.branch_build }} branch_build: ${{ steps.tag.outputs.branch_build }}
steps: steps:
- uses: actions/checkout@v4.1.5 - uses: actions/checkout@v4.1.6
- name: Get tag - name: Get tag
id: tag id: tag
# yamllint disable rule:line-length # yamllint disable rule:line-length
@ -51,7 +51,7 @@ jobs:
contents: read contents: read
id-token: write id-token: write
steps: steps:
- uses: actions/checkout@v4.1.5 - uses: actions/checkout@v4.1.6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5.1.0
with: with:
@ -83,7 +83,7 @@ jobs:
- linux/arm/v7 - linux/arm/v7
- linux/arm64 - linux/arm64
steps: steps:
- uses: actions/checkout@v4.1.5 - uses: actions/checkout@v4.1.6
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5.1.0
with: with:
@ -174,7 +174,7 @@ jobs:
- ghcr - ghcr
- dockerhub - dockerhub
steps: steps:
- uses: actions/checkout@v4.1.5 - uses: actions/checkout@v4.1.6
- name: Download digests - name: Download digests
uses: actions/download-artifact@v4.1.7 uses: actions/download-artifact@v4.1.7

View File

@ -13,10 +13,10 @@ jobs:
if: github.repository == 'esphome/esphome' if: github.repository == 'esphome/esphome'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Checkout Home Assistant - name: Checkout Home Assistant
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
with: with:
repository: home-assistant/core repository: home-assistant/core
path: lib/home-assistant path: lib/home-assistant

View File

@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v4.1.5 uses: actions/checkout@v4.1.6
- name: Run yamllint - name: Run yamllint
uses: frenck/action-yamllint@v1.5.0 uses: frenck/action-yamllint@v1.5.0
with: with:

View File

@ -351,7 +351,7 @@ def upload_program(config, args, host):
not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions
and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED])
and CONF_MQTT in config and CONF_MQTT in config
and (not args.device or args.device == "MQTT") and (not args.device or args.device in ("MQTT", "OTA"))
): ):
from esphome import mqtt from esphome import mqtt

View File

@ -1,12 +1,7 @@
#include "deep_sleep_component.h" #include "deep_sleep_component.h"
#include <cinttypes>
#include "esphome/core/application.h" #include "esphome/core/application.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#ifdef USE_ESP8266
#include <Esp.h>
#endif
namespace esphome { namespace esphome {
namespace deep_sleep { namespace deep_sleep {
@ -14,25 +9,6 @@ static const char *const TAG = "deep_sleep";
bool global_has_deep_sleep = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) bool global_has_deep_sleep = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
optional<uint32_t> DeepSleepComponent::get_run_duration_() const {
#ifdef USE_ESP32
if (this->wakeup_cause_to_run_duration_.has_value()) {
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
switch (wakeup_cause) {
case ESP_SLEEP_WAKEUP_EXT0:
case ESP_SLEEP_WAKEUP_EXT1:
case ESP_SLEEP_WAKEUP_GPIO:
return this->wakeup_cause_to_run_duration_->gpio_cause;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
return this->wakeup_cause_to_run_duration_->touch_cause;
default:
return this->wakeup_cause_to_run_duration_->default_cause;
}
}
#endif
return this->run_duration_;
}
void DeepSleepComponent::setup() { void DeepSleepComponent::setup() {
ESP_LOGCONFIG(TAG, "Setting up Deep Sleep..."); ESP_LOGCONFIG(TAG, "Setting up Deep Sleep...");
global_has_deep_sleep = true; global_has_deep_sleep = true;
@ -45,6 +21,7 @@ void DeepSleepComponent::setup() {
ESP_LOGD(TAG, "Not scheduling Deep Sleep, as no run duration is configured."); ESP_LOGD(TAG, "Not scheduling Deep Sleep, as no run duration is configured.");
} }
} }
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()) {
@ -54,65 +31,31 @@ void DeepSleepComponent::dump_config() {
if (this->run_duration_.has_value()) { if (this->run_duration_.has_value()) {
ESP_LOGCONFIG(TAG, " Run Duration: %" PRIu32 " ms", *this->run_duration_); ESP_LOGCONFIG(TAG, " Run Duration: %" PRIu32 " ms", *this->run_duration_);
} }
#ifdef USE_ESP32 this->dump_config_platform_();
if (wakeup_pin_ != nullptr) {
LOG_PIN(" Wakeup Pin: ", this->wakeup_pin_);
}
if (this->wakeup_cause_to_run_duration_.has_value()) {
ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %" PRIu32 " ms",
this->wakeup_cause_to_run_duration_->default_cause);
ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->touch_cause);
ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->gpio_cause);
}
#endif
} }
void DeepSleepComponent::loop() { void DeepSleepComponent::loop() {
if (this->next_enter_deep_sleep_) if (this->next_enter_deep_sleep_)
this->begin_sleep(); this->begin_sleep();
} }
float DeepSleepComponent::get_loop_priority() const { float DeepSleepComponent::get_loop_priority() const {
return -100.0f; // run after everything else is ready return -100.0f; // run after everything else is ready
} }
void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; } void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
#if defined(USE_ESP32)
void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) {
this->wakeup_pin_mode_ = wakeup_pin_mode;
}
#endif
#if defined(USE_ESP32)
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6)
void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; }
void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
#endif
void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) {
wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration;
}
#endif
void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; } void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
void DeepSleepComponent::begin_sleep(bool manual) { void DeepSleepComponent::begin_sleep(bool manual) {
if (this->prevent_ && !manual) { if (this->prevent_ && !manual) {
this->next_enter_deep_sleep_ = true; this->next_enter_deep_sleep_ = true;
return; return;
} }
#ifdef USE_ESP32
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr && if (!this->prepare_to_sleep_()) {
!this->sleep_duration_.has_value() && this->wakeup_pin_->digital_read()) {
// Defer deep sleep until inactive
if (!this->next_enter_deep_sleep_) {
this->status_set_warning();
ESP_LOGW(TAG, "Waiting for pin_ to switch state to enter deep sleep...");
}
this->next_enter_deep_sleep_ = true;
return; return;
} }
#endif
ESP_LOGI(TAG, "Beginning Deep Sleep"); ESP_LOGI(TAG, "Beginning Deep Sleep");
if (this->sleep_duration_.has_value()) { if (this->sleep_duration_.has_value()) {
@ -120,47 +63,13 @@ void DeepSleepComponent::begin_sleep(bool manual) {
} }
App.run_safe_shutdown_hooks(); App.run_safe_shutdown_hooks();
#if defined(USE_ESP32) this->deep_sleep_();
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6)
if (this->sleep_duration_.has_value())
esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
if (this->wakeup_pin_ != nullptr) {
bool level = !this->wakeup_pin_->is_inverted();
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
level = !level;
}
esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level);
}
if (this->ext1_wakeup_.has_value()) {
esp_sleep_enable_ext1_wakeup(this->ext1_wakeup_->mask, this->ext1_wakeup_->wakeup_mode);
}
if (this->touch_wakeup_.has_value() && *(this->touch_wakeup_)) {
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
}
#endif
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6)
if (this->sleep_duration_.has_value())
esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
if (this->wakeup_pin_ != nullptr) {
bool level = !this->wakeup_pin_->is_inverted();
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
level = !level;
}
esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(),
static_cast<esp_deepsleep_gpio_wake_up_mode_t>(level));
}
#endif
esp_deep_sleep_start();
#endif
#ifdef USE_ESP8266
ESP.deepSleep(*this->sleep_duration_); // NOLINT(readability-static-accessed-through-instance)
#endif
} }
float DeepSleepComponent::get_setup_priority() const { return setup_priority::LATE; } float DeepSleepComponent::get_setup_priority() const { return setup_priority::LATE; }
void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; } void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; }
void DeepSleepComponent::allow_deep_sleep() { this->prevent_ = false; } void DeepSleepComponent::allow_deep_sleep() { this->prevent_ = false; }
} // namespace deep_sleep } // namespace deep_sleep

View File

@ -106,6 +106,10 @@ class DeepSleepComponent : public Component {
// duration before entering deep sleep. // duration before entering deep sleep.
optional<uint32_t> get_run_duration_() const; optional<uint32_t> get_run_duration_() const;
void dump_config_platform_();
bool prepare_to_sleep_();
void deep_sleep_();
optional<uint64_t> sleep_duration_; optional<uint64_t> sleep_duration_;
#ifdef USE_ESP32 #ifdef USE_ESP32
InternalGPIOPin *wakeup_pin_; InternalGPIOPin *wakeup_pin_;

View File

@ -0,0 +1,104 @@
#ifdef USE_ESP32
#include "deep_sleep_component.h"
#include "esphome/core/log.h"
namespace esphome {
namespace deep_sleep {
static const char *const TAG = "deep_sleep";
optional<uint32_t> DeepSleepComponent::get_run_duration_() const {
if (this->wakeup_cause_to_run_duration_.has_value()) {
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
switch (wakeup_cause) {
case ESP_SLEEP_WAKEUP_EXT0:
case ESP_SLEEP_WAKEUP_EXT1:
case ESP_SLEEP_WAKEUP_GPIO:
return this->wakeup_cause_to_run_duration_->gpio_cause;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
return this->wakeup_cause_to_run_duration_->touch_cause;
default:
return this->wakeup_cause_to_run_duration_->default_cause;
}
}
return this->run_duration_;
}
void DeepSleepComponent::set_wakeup_pin_mode(WakeupPinMode wakeup_pin_mode) {
this->wakeup_pin_mode_ = wakeup_pin_mode;
}
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6)
void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wakeup_ = ext1_wakeup; }
void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
#endif
void DeepSleepComponent::set_run_duration(WakeupCauseToRunDuration wakeup_cause_to_run_duration) {
wakeup_cause_to_run_duration_ = wakeup_cause_to_run_duration;
}
void DeepSleepComponent::dump_config_platform_() {
if (wakeup_pin_ != nullptr) {
LOG_PIN(" Wakeup Pin: ", this->wakeup_pin_);
}
if (this->wakeup_cause_to_run_duration_.has_value()) {
ESP_LOGCONFIG(TAG, " Default Wakeup Run Duration: %" PRIu32 " ms",
this->wakeup_cause_to_run_duration_->default_cause);
ESP_LOGCONFIG(TAG, " Touch Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->touch_cause);
ESP_LOGCONFIG(TAG, " GPIO Wakeup Run Duration: %" PRIu32 " ms", this->wakeup_cause_to_run_duration_->gpio_cause);
}
}
bool DeepSleepComponent::prepare_to_sleep_() {
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr &&
!this->sleep_duration_.has_value() && this->wakeup_pin_->digital_read()) {
// Defer deep sleep until inactive
if (!this->next_enter_deep_sleep_) {
this->status_set_warning();
ESP_LOGW(TAG, "Waiting for pin_ to switch state to enter deep sleep...");
}
this->next_enter_deep_sleep_ = true;
return false;
}
return true;
}
void DeepSleepComponent::deep_sleep_() {
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6)
if (this->sleep_duration_.has_value())
esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
if (this->wakeup_pin_ != nullptr) {
bool level = !this->wakeup_pin_->is_inverted();
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
level = !level;
}
esp_sleep_enable_ext0_wakeup(gpio_num_t(this->wakeup_pin_->get_pin()), level);
}
if (this->ext1_wakeup_.has_value()) {
esp_sleep_enable_ext1_wakeup(this->ext1_wakeup_->mask, this->ext1_wakeup_->wakeup_mode);
}
if (this->touch_wakeup_.has_value() && *(this->touch_wakeup_)) {
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
}
#endif
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6)
if (this->sleep_duration_.has_value())
esp_sleep_enable_timer_wakeup(*this->sleep_duration_);
if (this->wakeup_pin_ != nullptr) {
bool level = !this->wakeup_pin_->is_inverted();
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) {
level = !level;
}
esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(),
static_cast<esp_deepsleep_gpio_wake_up_mode_t>(level));
}
#endif
esp_deep_sleep_start();
}
} // namespace deep_sleep
} // namespace esphome
#endif

View File

@ -0,0 +1,23 @@
#ifdef USE_ESP8266
#include "deep_sleep_component.h"
#include <Esp.h>
namespace esphome {
namespace deep_sleep {
static const char *const TAG = "deep_sleep";
optional<uint32_t> DeepSleepComponent::get_run_duration_() const { return this->run_duration_; }
void DeepSleepComponent::dump_config_platform_() {}
bool DeepSleepComponent::prepare_to_sleep_() { return true; }
void DeepSleepComponent::deep_sleep_() {
ESP.deepSleep(*this->sleep_duration_); // NOLINT(readability-static-accessed-through-instance)
}
} // namespace deep_sleep
} // namespace esphome
#endif

View File

@ -14,6 +14,9 @@ from esphome.const import (
CONF_STATE, CONF_STATE,
CONF_STOP, CONF_STOP,
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_WATER,
) )
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
from esphome.cpp_helpers import setup_entity from esphome.cpp_helpers import setup_entity
@ -22,6 +25,12 @@ IS_PLATFORM_COMPONENT = True
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
DEVICE_CLASSES = [
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_GAS,
DEVICE_CLASS_WATER,
]
valve_ns = cg.esphome_ns.namespace("valve") valve_ns = cg.esphome_ns.namespace("valve")
Valve = valve_ns.class_("Valve", cg.EntityBase) Valve = valve_ns.class_("Valve", cg.EntityBase)
@ -65,6 +74,7 @@ VALVE_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).ex
{ {
cv.GenerateID(): cv.declare_id(Valve), cv.GenerateID(): cv.declare_id(Valve),
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent), cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTValveComponent),
cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True),
cv.Optional(CONF_POSITION_COMMAND_TOPIC): cv.All( cv.Optional(CONF_POSITION_COMMAND_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.subscribe_topic cv.requires_component("mqtt"), cv.subscribe_topic
), ),

View File

@ -103,7 +103,7 @@ class DashboardEntries:
def all(self) -> list[DashboardEntry]: def all(self) -> list[DashboardEntry]:
"""Return all entries.""" """Return all entries."""
return asyncio.run_coroutine_threadsafe(self._async_all, self._loop).result() return asyncio.run_coroutine_threadsafe(self._async_all(), self._loop).result()
def async_all(self) -> list[DashboardEntry]: def async_all(self) -> list[DashboardEntry]:
"""Return all entries.""" """Return all entries."""

View File

@ -277,6 +277,7 @@ def wizard(path):
from esphome.components.esp32 import boards as esp32_boards from esphome.components.esp32 import boards as esp32_boards
from esphome.components.esp8266 import boards as esp8266_boards from esphome.components.esp8266 import boards as esp8266_boards
from esphome.components.rtl87xx import boards as rtl87xx_boards from esphome.components.rtl87xx import boards as rtl87xx_boards
from esphome.components.rp2040 import boards as rp2040_boards
if not path.endswith(".yaml") and not path.endswith(".yml"): if not path.endswith(".yaml") and not path.endswith(".yml"):
safe_print( safe_print(
@ -343,7 +344,7 @@ def wizard(path):
"firmwares for it." "firmwares for it."
) )
wizard_platforms = ["ESP32", "ESP8266", "BK72XX", "RTL87XX"] wizard_platforms = ["ESP32", "ESP8266", "BK72XX", "RTL87XX", "RP2040"]
safe_print( safe_print(
"Please choose one of the supported microcontrollers " "Please choose one of the supported microcontrollers "
"(Use ESP8266 for Sonoff devices)." "(Use ESP8266 for Sonoff devices)."
@ -373,6 +374,10 @@ def wizard(path):
board_link = ( board_link = (
"http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards" "http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards"
) )
elif platform == "RP2040":
board_link = (
"https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html"
)
elif platform in ["BK72XX", "RTL87XX"]: elif platform in ["BK72XX", "RTL87XX"]:
board_link = "https://docs.libretiny.eu/docs/status/supported/" board_link = "https://docs.libretiny.eu/docs/status/supported/"
else: else:
@ -397,6 +402,10 @@ def wizard(path):
elif platform == "RTL87XX": elif platform == "RTL87XX":
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'wr3')}\".") safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'wr3')}\".")
boards_list = rtl87xx_boards.BOARDS.items() boards_list = rtl87xx_boards.BOARDS.items()
elif platform == "RP2040":
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'rpipicow')}\".")
boards_list = rp2040_boards.BOARDS.items()
else: else:
raise NotImplementedError("Unknown platform!") raise NotImplementedError("Unknown platform!")
@ -423,60 +432,64 @@ def wizard(path):
safe_print() safe_print()
sleep(1) sleep(1)
safe_print_step(3, WIFI_BIG) # Do not create wifi if the board does not support it
safe_print("In this step, I'm going to create the configuration for WiFi.") if board not in ["rpipico"]:
safe_print() safe_print_step(3, WIFI_BIG)
sleep(1) safe_print("In this step, I'm going to create the configuration for WiFi.")
safe_print( safe_print()
f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?" sleep(1)
) safe_print(
sleep(1.5) f"First, what's the {color(Fore.GREEN, 'SSID')} (the name) of the WiFi network {name} should connect to?"
safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".") )
while True: sleep(1.5)
ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): ")) safe_print(f"For example \"{color(Fore.BOLD_WHITE, 'Abraham Linksys')}\".")
try: while True:
ssid = cv.ssid(ssid) ssid = safe_input(color(Fore.BOLD_WHITE, "(ssid): "))
break try:
except vol.Invalid: ssid = cv.ssid(ssid)
safe_print( break
color( except vol.Invalid:
Fore.RED, safe_print(
f'Unfortunately, "{ssid}" doesn\'t seem to be a valid SSID. Please try again.', color(
Fore.RED,
f'Unfortunately, "{ssid}" doesn\'t seem to be a valid SSID. Please try again.',
)
) )
) safe_print()
safe_print() sleep(1)
sleep(1)
safe_print( safe_print(
f'Thank you very much! You\'ve just chosen "{color(Fore.CYAN, ssid)}" as your SSID.' f'Thank you very much! You\'ve just chosen "{color(Fore.CYAN, ssid)}" as your SSID.'
) )
safe_print() safe_print()
sleep(0.75) sleep(0.75)
safe_print( safe_print(
f"Now please state the {color(Fore.GREEN, 'password')} of the WiFi network so that I can connect to it (Leave empty for no password)" f"Now please state the {color(Fore.GREEN, 'password')} of the WiFi network so that I can connect to it (Leave empty for no password)"
) )
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 = safe_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)."
) )
sleep(1.5) sleep(1.5)
safe_print_step(4, OTA_BIG) safe_print_step(4, OTA_BIG)
safe_print( safe_print(
"Almost there! ESPHome can automatically upload custom firmwares over WiFi " "Almost there! ESPHome can automatically upload custom firmwares over WiFi "
"(over the air) and integrates into Home Assistant with a native API." "(over the air) and integrates into Home Assistant with a native API."
) )
safe_print( safe_print(
f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(Fore.GREEN, 'password')} for connecting to this ESP?" f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(Fore.GREEN, 'password')} for connecting to this ESP?"
) )
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 = safe_input(color(Fore.BOLD_WHITE, "(password): ")) password = safe_input(color(Fore.BOLD_WHITE, "(password): "))
else:
ssid, password, psk = "", "", ""
if not wizard_write( if not wizard_write(
path=path, path=path,

View File

@ -20,7 +20,7 @@ fi
pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt
pip3 install setuptools wheel pip3 install setuptools wheel
pip3 install -e --config-settings editable_mode=compat ".[dev,test,displays]" pip3 install -e ".[dev,test,displays]" --config-settings editable_mode=compat
pre-commit install pre-commit install

View File

@ -37,9 +37,10 @@ start_esphome() {
# Start esphome process # Start esphome process
echo "> [$target_component] [$test_name] [$target_platform]" echo "> [$target_component] [$test_name] [$target_platform]"
echo "esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file" set -x
# TODO: Validate escape of Command line substitution value # TODO: Validate escape of Command line substitution value
esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file python -m esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file
{ set +x; } 2>/dev/null
} }
# Find all test yaml files. # Find all test yaml files.