mirror of
https://github.com/esphome/esphome.git
synced 2026-02-02 09:47:34 -07:00
Compare commits
7 Commits
esp32_ard_
...
template_s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89bd9b610e | ||
|
|
9dbcf1447b | ||
|
|
6c853cae57 | ||
|
|
48e6efb6aa | ||
|
|
cfc3b3336f | ||
|
|
9ca394d1e5 | ||
|
|
e62a87afe1 |
@@ -211,7 +211,7 @@ void APIServer::loop() {
|
||||
|
||||
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
|
||||
// Fire trigger after client is removed so api.connected reflects the true state
|
||||
this->client_disconnected_trigger_.trigger(client_name, client_peername);
|
||||
this->client_disconnected_trigger_->trigger(client_name, client_peername);
|
||||
#endif
|
||||
// Don't increment client_index since we need to process the swapped element
|
||||
}
|
||||
|
||||
@@ -227,10 +227,12 @@ class APIServer : public Component,
|
||||
#endif
|
||||
|
||||
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
||||
Trigger<std::string, std::string> *get_client_connected_trigger() { return &this->client_connected_trigger_; }
|
||||
Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
|
||||
#endif
|
||||
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
|
||||
Trigger<std::string, std::string> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; }
|
||||
Trigger<std::string, std::string> *get_client_disconnected_trigger() const {
|
||||
return this->client_disconnected_trigger_;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -251,10 +253,10 @@ class APIServer : public Component,
|
||||
// Pointers and pointer-like types first (4 bytes each)
|
||||
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
||||
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
||||
Trigger<std::string, std::string> client_connected_trigger_;
|
||||
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
|
||||
#endif
|
||||
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
|
||||
Trigger<std::string, std::string> client_disconnected_trigger_;
|
||||
Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>();
|
||||
#endif
|
||||
|
||||
// 4-byte aligned types
|
||||
|
||||
@@ -136,10 +136,12 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
|
||||
void set_wants_response() { this->flags_.wants_response = true; }
|
||||
|
||||
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
||||
Trigger<JsonObjectConst, Ts...> *get_success_trigger_with_response() { return &this->success_trigger_with_response_; }
|
||||
Trigger<JsonObjectConst, Ts...> *get_success_trigger_with_response() const {
|
||||
return this->success_trigger_with_response_;
|
||||
}
|
||||
#endif
|
||||
Trigger<Ts...> *get_success_trigger() { return &this->success_trigger_; }
|
||||
Trigger<std::string, Ts...> *get_error_trigger() { return &this->error_trigger_; }
|
||||
Trigger<Ts...> *get_success_trigger() const { return this->success_trigger_; }
|
||||
Trigger<std::string, Ts...> *get_error_trigger() const { return this->error_trigger_; }
|
||||
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
||||
|
||||
void play(const Ts &...x) override {
|
||||
@@ -185,14 +187,14 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
|
||||
if (response.is_success()) {
|
||||
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
||||
if (this->flags_.wants_response) {
|
||||
this->success_trigger_with_response_.trigger(response.get_json(), args...);
|
||||
this->success_trigger_with_response_->trigger(response.get_json(), args...);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
this->success_trigger_.trigger(args...);
|
||||
this->success_trigger_->trigger(args...);
|
||||
}
|
||||
} else {
|
||||
this->error_trigger_.trigger(response.get_error_message(), args...);
|
||||
this->error_trigger_->trigger(response.get_error_message(), args...);
|
||||
}
|
||||
},
|
||||
captured_args);
|
||||
@@ -249,10 +251,10 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
|
||||
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
||||
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
||||
TemplatableStringValue<Ts...> response_template_{""};
|
||||
Trigger<JsonObjectConst, Ts...> success_trigger_with_response_;
|
||||
Trigger<JsonObjectConst, Ts...> *success_trigger_with_response_ = new Trigger<JsonObjectConst, Ts...>();
|
||||
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
||||
Trigger<Ts...> success_trigger_;
|
||||
Trigger<std::string, Ts...> error_trigger_;
|
||||
Trigger<Ts...> *success_trigger_ = new Trigger<Ts...>();
|
||||
Trigger<std::string, Ts...> *error_trigger_ = new Trigger<std::string, Ts...>();
|
||||
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
||||
|
||||
struct Flags {
|
||||
|
||||
@@ -6,7 +6,8 @@ namespace bang_bang {
|
||||
|
||||
static const char *const TAG = "bang_bang.climate";
|
||||
|
||||
BangBangClimate::BangBangClimate() = default;
|
||||
BangBangClimate::BangBangClimate()
|
||||
: idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {}
|
||||
|
||||
void BangBangClimate::setup() {
|
||||
this->sensor_->add_on_state_callback([this](float state) {
|
||||
@@ -159,13 +160,13 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
|
||||
switch (action) {
|
||||
case climate::CLIMATE_ACTION_OFF:
|
||||
case climate::CLIMATE_ACTION_IDLE:
|
||||
trig = &this->idle_trigger_;
|
||||
trig = this->idle_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_ACTION_COOLING:
|
||||
trig = &this->cool_trigger_;
|
||||
trig = this->cool_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_ACTION_HEATING:
|
||||
trig = &this->heat_trigger_;
|
||||
trig = this->heat_trigger_;
|
||||
break;
|
||||
default:
|
||||
trig = nullptr;
|
||||
@@ -203,9 +204,9 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa
|
||||
void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
|
||||
void BangBangClimate::set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
|
||||
|
||||
Trigger<> *BangBangClimate::get_idle_trigger() { return &this->idle_trigger_; }
|
||||
Trigger<> *BangBangClimate::get_cool_trigger() { return &this->cool_trigger_; }
|
||||
Trigger<> *BangBangClimate::get_heat_trigger() { return &this->heat_trigger_; }
|
||||
Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; }
|
||||
Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; }
|
||||
Trigger<> *BangBangClimate::get_heat_trigger() const { return this->heat_trigger_; }
|
||||
|
||||
void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||
void BangBangClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||
|
||||
@@ -30,9 +30,9 @@ class BangBangClimate : public climate::Climate, public Component {
|
||||
void set_normal_config(const BangBangClimateTargetTempConfig &normal_config);
|
||||
void set_away_config(const BangBangClimateTargetTempConfig &away_config);
|
||||
|
||||
Trigger<> *get_idle_trigger();
|
||||
Trigger<> *get_cool_trigger();
|
||||
Trigger<> *get_heat_trigger();
|
||||
Trigger<> *get_idle_trigger() const;
|
||||
Trigger<> *get_cool_trigger() const;
|
||||
Trigger<> *get_heat_trigger() const;
|
||||
|
||||
protected:
|
||||
/// Override control to change settings of the climate device.
|
||||
@@ -57,13 +57,17 @@ class BangBangClimate : public climate::Climate, public Component {
|
||||
*
|
||||
* In idle mode, the controller is assumed to have both heating and cooling disabled.
|
||||
*/
|
||||
Trigger<> idle_trigger_;
|
||||
Trigger<> *idle_trigger_{nullptr};
|
||||
/** The trigger to call when the controller should switch to cooling mode.
|
||||
*/
|
||||
Trigger<> cool_trigger_;
|
||||
Trigger<> *cool_trigger_{nullptr};
|
||||
/** The trigger to call when the controller should switch to heating mode.
|
||||
*
|
||||
* A null value for this attribute means that the controller has no heating action
|
||||
* For example window blinds, where only cooling (blinds closed) and not-cooling
|
||||
* (blinds open) is possible.
|
||||
*/
|
||||
Trigger<> heat_trigger_;
|
||||
Trigger<> *heat_trigger_{nullptr};
|
||||
/** A reference to the trigger that was previously active.
|
||||
*
|
||||
* This is so that the previous trigger can be stopped before enabling a new one.
|
||||
|
||||
@@ -89,9 +89,8 @@ async def to_code(config):
|
||||
var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds)
|
||||
)
|
||||
|
||||
# Although this component does not use SPI/Wire directly, the BSEC library requires them
|
||||
# Although this component does not use SPI, the BSEC library requires the SPI library
|
||||
cg.add_library("SPI", None)
|
||||
cg.add_library("Wire", None)
|
||||
|
||||
cg.add_define("USE_BSEC")
|
||||
cg.add_library("boschsensortec/BSEC Software Library", "1.6.1480")
|
||||
|
||||
@@ -156,7 +156,7 @@ void CC1101Component::call_listeners_(const std::vector<uint8_t> &packet, float
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_packet(packet, freq_offset, rssi, lqi);
|
||||
}
|
||||
this->packet_trigger_.trigger(packet, freq_offset, rssi, lqi);
|
||||
this->packet_trigger_->trigger(packet, freq_offset, rssi, lqi);
|
||||
}
|
||||
|
||||
void CC1101Component::loop() {
|
||||
|
||||
@@ -79,7 +79,7 @@ class CC1101Component : public Component,
|
||||
// Packet mode operations
|
||||
CC1101Error transmit_packet(const std::vector<uint8_t> &packet);
|
||||
void register_listener(CC1101Listener *listener) { this->listeners_.push_back(listener); }
|
||||
Trigger<std::vector<uint8_t>, float, float, uint8_t> *get_packet_trigger() { return &this->packet_trigger_; }
|
||||
Trigger<std::vector<uint8_t>, float, float, uint8_t> *get_packet_trigger() const { return this->packet_trigger_; }
|
||||
|
||||
protected:
|
||||
uint16_t chip_id_{0};
|
||||
@@ -96,7 +96,8 @@ class CC1101Component : public Component,
|
||||
|
||||
// Packet handling
|
||||
void call_listeners_(const std::vector<uint8_t> &packet, float freq_offset, float rssi, uint8_t lqi);
|
||||
Trigger<std::vector<uint8_t>, float, float, uint8_t> packet_trigger_;
|
||||
Trigger<std::vector<uint8_t>, float, float, uint8_t> *packet_trigger_{
|
||||
new Trigger<std::vector<uint8_t>, float, float, uint8_t>()};
|
||||
std::vector<uint8_t> packet_;
|
||||
std::vector<CC1101Listener *> listeners_;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ void CurrentBasedCover::loop() {
|
||||
if (this->current_operation == COVER_OPERATION_OPENING) {
|
||||
if (this->malfunction_detection_ && this->is_closing_()) { // Malfunction
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
this->malfunction_trigger_->trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit",
|
||||
this->name_.c_str());
|
||||
} else if (this->is_opening_blocked_()) { // Blocked
|
||||
@@ -87,7 +87,7 @@ void CurrentBasedCover::loop() {
|
||||
} else if (this->current_operation == COVER_OPERATION_CLOSING) {
|
||||
if (this->malfunction_detection_ && this->is_opening_()) { // Malfunction
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
this->malfunction_trigger_->trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit",
|
||||
this->name_.c_str());
|
||||
} else if (this->is_closing_blocked_()) { // Blocked
|
||||
@@ -221,15 +221,15 @@ void CurrentBasedCover::start_direction_(CoverOperation dir) {
|
||||
Trigger<> *trig;
|
||||
switch (dir) {
|
||||
case COVER_OPERATION_IDLE:
|
||||
trig = &this->stop_trigger_;
|
||||
trig = this->stop_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_OPENING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->open_trigger_;
|
||||
trig = this->open_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_CLOSING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->close_trigger_;
|
||||
trig = this->close_trigger_;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
@@ -16,9 +16,9 @@ class CurrentBasedCover : public cover::Cover, public Component {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
Trigger<> *get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *get_stop_trigger() const { return this->stop_trigger_; }
|
||||
|
||||
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *get_open_trigger() const { return this->open_trigger_; }
|
||||
void set_open_sensor(sensor::Sensor *open_sensor) { this->open_sensor_ = open_sensor; }
|
||||
void set_open_moving_current_threshold(float open_moving_current_threshold) {
|
||||
this->open_moving_current_threshold_ = open_moving_current_threshold;
|
||||
@@ -28,7 +28,7 @@ class CurrentBasedCover : public cover::Cover, public Component {
|
||||
}
|
||||
void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; }
|
||||
|
||||
Trigger<> *get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *get_close_trigger() const { return this->close_trigger_; }
|
||||
void set_close_sensor(sensor::Sensor *close_sensor) { this->close_sensor_ = close_sensor; }
|
||||
void set_close_moving_current_threshold(float close_moving_current_threshold) {
|
||||
this->close_moving_current_threshold_ = close_moving_current_threshold;
|
||||
@@ -44,7 +44,7 @@ class CurrentBasedCover : public cover::Cover, public Component {
|
||||
void set_malfunction_detection(bool malfunction_detection) { this->malfunction_detection_ = malfunction_detection; }
|
||||
void set_start_sensing_delay(uint32_t start_sensing_delay) { this->start_sensing_delay_ = start_sensing_delay; }
|
||||
|
||||
Trigger<> *get_malfunction_trigger() { return &this->malfunction_trigger_; }
|
||||
Trigger<> *get_malfunction_trigger() const { return this->malfunction_trigger_; }
|
||||
|
||||
cover::CoverTraits get_traits() override;
|
||||
|
||||
@@ -64,23 +64,23 @@ class CurrentBasedCover : public cover::Cover, public Component {
|
||||
|
||||
void recompute_position_();
|
||||
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> *stop_trigger_{new Trigger<>()};
|
||||
|
||||
sensor::Sensor *open_sensor_{nullptr};
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> *open_trigger_{new Trigger<>()};
|
||||
float open_moving_current_threshold_;
|
||||
float open_obstacle_current_threshold_{FLT_MAX};
|
||||
uint32_t open_duration_;
|
||||
|
||||
sensor::Sensor *close_sensor_{nullptr};
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> *close_trigger_{new Trigger<>()};
|
||||
float close_moving_current_threshold_;
|
||||
float close_obstacle_current_threshold_{FLT_MAX};
|
||||
uint32_t close_duration_;
|
||||
|
||||
uint32_t max_duration_{UINT32_MAX};
|
||||
bool malfunction_detection_{true};
|
||||
Trigger<> malfunction_trigger_;
|
||||
Trigger<> *malfunction_trigger_{new Trigger<>()};
|
||||
uint32_t start_sensing_delay_;
|
||||
float obstacle_rollback_;
|
||||
|
||||
|
||||
@@ -141,15 +141,15 @@ void EndstopCover::start_direction_(CoverOperation dir) {
|
||||
Trigger<> *trig;
|
||||
switch (dir) {
|
||||
case COVER_OPERATION_IDLE:
|
||||
trig = &this->stop_trigger_;
|
||||
trig = this->stop_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_OPENING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->open_trigger_;
|
||||
trig = this->open_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_CLOSING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->close_trigger_;
|
||||
trig = this->close_trigger_;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
@@ -15,9 +15,9 @@ class EndstopCover : public cover::Cover, public Component {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *get_open_trigger() const { return this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() const { return this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() const { return this->stop_trigger_; }
|
||||
void set_open_endstop(binary_sensor::BinarySensor *open_endstop) { this->open_endstop_ = open_endstop; }
|
||||
void set_close_endstop(binary_sensor::BinarySensor *close_endstop) { this->close_endstop_ = close_endstop; }
|
||||
void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; }
|
||||
@@ -39,11 +39,11 @@ class EndstopCover : public cover::Cover, public Component {
|
||||
|
||||
binary_sensor::BinarySensor *open_endstop_;
|
||||
binary_sensor::BinarySensor *close_endstop_;
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> *open_trigger_{new Trigger<>()};
|
||||
uint32_t open_duration_;
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> *close_trigger_{new Trigger<>()};
|
||||
uint32_t close_duration_;
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> *stop_trigger_{new Trigger<>()};
|
||||
uint32_t max_duration_{UINT32_MAX};
|
||||
|
||||
Trigger<> *prev_command_trigger_{nullptr};
|
||||
|
||||
@@ -5,7 +5,6 @@ import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
|
||||
from esphome import yaml_util
|
||||
import esphome.codegen as cg
|
||||
@@ -51,7 +50,6 @@ from esphome.writer import clean_cmake_cache
|
||||
|
||||
from .boards import BOARDS, STANDARD_BOARDS
|
||||
from .const import ( # noqa
|
||||
KEY_ARDUINO_LIBRARIES,
|
||||
KEY_BOARD,
|
||||
KEY_COMPONENTS,
|
||||
KEY_ESP32,
|
||||
@@ -148,168 +146,6 @@ DEFAULT_EXCLUDED_IDF_COMPONENTS = (
|
||||
"wifi_provisioning", # WiFi provisioning - ESPHome uses its own improv implementation
|
||||
)
|
||||
|
||||
# Additional IDF managed components to exclude for Arduino framework builds
|
||||
# These are pulled in by the Arduino framework's idf_component.yml but not used by ESPHome
|
||||
# Note: Component names include the namespace prefix (e.g., "espressif__cbor") because
|
||||
# that's how managed components are registered in the IDF build system
|
||||
# List includes direct dependencies from arduino-esp32/idf_component.yml
|
||||
# plus transitive dependencies from RainMaker/Insights (except espressif/mdns which we need)
|
||||
ARDUINO_EXCLUDED_IDF_COMPONENTS = (
|
||||
"chmorgan__esp-libhelix-mp3", # MP3 decoder - not used
|
||||
"espressif__cbor", # CBOR library - only used by RainMaker/Insights
|
||||
"espressif__esp-dsp", # DSP library - not used
|
||||
"espressif__esp-modbus", # Modbus - ESPHome has its own
|
||||
"espressif__esp-sr", # Speech recognition - not used
|
||||
"espressif__esp-zboss-lib", # Zigbee ZBOSS library - not used
|
||||
"espressif__esp-zigbee-lib", # Zigbee library - not used
|
||||
"espressif__esp_diag_data_store", # Diagnostics - not used
|
||||
"espressif__esp_diagnostics", # Diagnostics - not used
|
||||
"espressif__esp_hosted", # ESP hosted - only for ESP32-P4
|
||||
"espressif__esp_insights", # ESP Insights - not used
|
||||
"espressif__esp_modem", # Modem library - not used
|
||||
"espressif__esp_rainmaker", # RainMaker - not used
|
||||
"espressif__esp_rcp_update", # RCP update - RainMaker transitive dep
|
||||
"espressif__esp_schedule", # Schedule - RainMaker transitive dep
|
||||
"espressif__esp_secure_cert_mgr", # Secure cert - RainMaker transitive dep
|
||||
"espressif__esp_wifi_remote", # WiFi remote - only for ESP32-P4
|
||||
"espressif__json_generator", # JSON generator - RainMaker transitive dep
|
||||
"espressif__json_parser", # JSON parser - RainMaker transitive dep
|
||||
"espressif__lan867x", # Ethernet PHY - ESPHome uses ESP-IDF ethernet directly
|
||||
"espressif__libsodium", # Crypto - ESPHome uses its own noise-c library
|
||||
"espressif__network_provisioning", # Network provisioning - not used
|
||||
"espressif__qrcode", # QR code - not used
|
||||
"espressif__rmaker_common", # RainMaker common - not used
|
||||
"joltwallet__littlefs", # LittleFS - ESPHome doesn't use filesystem
|
||||
)
|
||||
|
||||
# Mapping of Arduino libraries to IDF managed components they require
|
||||
# When an Arduino library is enabled via cg.add_library(), these components
|
||||
# are automatically un-stubbed from ARDUINO_EXCLUDED_IDF_COMPONENTS.
|
||||
#
|
||||
# Note: Some libraries (Matter, LittleFS, ESP_SR, WiFiProv, ArduinoOTA) already have
|
||||
# conditional maybe_add_component() calls in arduino-esp32/CMakeLists.txt that handle
|
||||
# their managed component dependencies. Our mapping is primarily needed for libraries
|
||||
# that don't have such conditionals (Ethernet, PPP, Zigbee, RainMaker, Insights, etc.)
|
||||
# and to ensure the stubs are removed from our idf_component.yml overrides.
|
||||
ARDUINO_LIBRARY_IDF_COMPONENTS: dict[str, tuple[str, ...]] = {
|
||||
"BLE": ("esp_driver_gptimer",),
|
||||
"BluetoothSerial": ("esp_driver_gptimer",),
|
||||
"ESP_HostedOTA": ("espressif__esp_hosted", "espressif__esp_wifi_remote"),
|
||||
"ESP_SR": ("espressif__esp-sr",),
|
||||
"Ethernet": ("espressif__lan867x",),
|
||||
"FFat": ("fatfs",),
|
||||
"Insights": (
|
||||
"espressif__cbor",
|
||||
"espressif__esp_insights",
|
||||
"espressif__esp_diagnostics",
|
||||
"espressif__esp_diag_data_store",
|
||||
"espressif__rmaker_common", # Transitive dep from esp_insights
|
||||
),
|
||||
"LittleFS": ("joltwallet__littlefs",),
|
||||
"Matter": ("espressif__esp_matter",),
|
||||
"PPP": ("espressif__esp_modem",),
|
||||
"RainMaker": (
|
||||
# Direct deps from idf_component.yml
|
||||
"espressif__cbor",
|
||||
"espressif__esp_rainmaker",
|
||||
"espressif__esp_insights",
|
||||
"espressif__esp_diagnostics",
|
||||
"espressif__esp_diag_data_store",
|
||||
"espressif__rmaker_common",
|
||||
"espressif__qrcode",
|
||||
# Transitive deps from esp_rainmaker
|
||||
"espressif__esp_rcp_update",
|
||||
"espressif__esp_schedule",
|
||||
"espressif__esp_secure_cert_mgr",
|
||||
"espressif__json_generator",
|
||||
"espressif__json_parser",
|
||||
"espressif__network_provisioning",
|
||||
),
|
||||
"SD": ("fatfs",),
|
||||
"SD_MMC": ("fatfs",),
|
||||
"SPIFFS": ("spiffs",),
|
||||
"WiFiProv": ("espressif__network_provisioning", "espressif__qrcode"),
|
||||
"Zigbee": ("espressif__esp-zigbee-lib", "espressif__esp-zboss-lib"),
|
||||
}
|
||||
|
||||
# Arduino library to Arduino library dependencies
|
||||
# When enabling one library, also enable its dependencies
|
||||
# Kconfig "select" statements don't work with CONFIG_ARDUINO_SELECTIVE_COMPILATION
|
||||
ARDUINO_LIBRARY_DEPENDENCIES: dict[str, tuple[str, ...]] = {
|
||||
"Ethernet": ("Network",),
|
||||
"WiFi": ("Network",),
|
||||
}
|
||||
|
||||
|
||||
def _idf_component_stub_name(component: str) -> str:
|
||||
"""Get stub directory name from IDF component name.
|
||||
|
||||
Component names are typically namespace__name (e.g., espressif__cbor).
|
||||
Returns just the name part (e.g., cbor). If no namespace is present,
|
||||
returns the original component name.
|
||||
"""
|
||||
_prefix, sep, suffix = component.partition("__")
|
||||
return suffix if sep else component
|
||||
|
||||
|
||||
def _idf_component_dep_name(component: str) -> str:
|
||||
"""Convert IDF component name to dependency format.
|
||||
|
||||
Converts espressif__cbor to espressif/cbor.
|
||||
"""
|
||||
return component.replace("__", "/")
|
||||
|
||||
|
||||
# Arduino libraries to disable by default when using Arduino framework
|
||||
# ESPHome uses ESP-IDF APIs directly; we only need the Arduino core
|
||||
# (HardwareSerial, Print, Stream, GPIO functions which are always compiled)
|
||||
# Components use cg.add_library() which auto-enables any they need
|
||||
# This list must match ARDUINO_ALL_LIBRARIES from arduino-esp32/CMakeLists.txt
|
||||
ARDUINO_DISABLED_LIBRARIES: frozenset[str] = frozenset(
|
||||
{
|
||||
"ArduinoOTA",
|
||||
"AsyncUDP",
|
||||
"BLE",
|
||||
"BluetoothSerial",
|
||||
"DNSServer",
|
||||
"EEPROM",
|
||||
"ESP_HostedOTA",
|
||||
"ESP_I2S",
|
||||
"ESP_NOW",
|
||||
"ESP_SR",
|
||||
"ESPmDNS",
|
||||
"Ethernet",
|
||||
"FFat",
|
||||
"FS",
|
||||
"Hash",
|
||||
"HTTPClient",
|
||||
"HTTPUpdate",
|
||||
"Insights",
|
||||
"LittleFS",
|
||||
"Matter",
|
||||
"NetBIOS",
|
||||
"Network",
|
||||
"NetworkClientSecure",
|
||||
"OpenThread",
|
||||
"PPP",
|
||||
"Preferences",
|
||||
"RainMaker",
|
||||
"SD",
|
||||
"SD_MMC",
|
||||
"SimpleBLE",
|
||||
"SPI",
|
||||
"SPIFFS",
|
||||
"Ticker",
|
||||
"Update",
|
||||
"USB",
|
||||
"WebServer",
|
||||
"WiFi",
|
||||
"WiFiProv",
|
||||
"Wire",
|
||||
"Zigbee",
|
||||
}
|
||||
)
|
||||
|
||||
# ESP32 (original) chip revision options
|
||||
# Setting minimum revision to 3.0 or higher:
|
||||
# - Reduces flash size by excluding workaround code for older chip bugs
|
||||
@@ -401,13 +237,7 @@ def set_core_data(config):
|
||||
CORE.data[KEY_ESP32][KEY_COMPONENTS] = {}
|
||||
# Initialize with default exclusions - components can call include_builtin_idf_component()
|
||||
# to re-enable any they need
|
||||
excluded = set(DEFAULT_EXCLUDED_IDF_COMPONENTS)
|
||||
# Add Arduino-specific managed component exclusions when using Arduino framework
|
||||
if conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
||||
excluded.update(ARDUINO_EXCLUDED_IDF_COMPONENTS)
|
||||
CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = excluded
|
||||
# Initialize Arduino library tracking - cg.add_library() auto-enables libraries
|
||||
CORE.data[KEY_ESP32][KEY_ARDUINO_LIBRARIES] = set()
|
||||
CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = set(DEFAULT_EXCLUDED_IDF_COMPONENTS)
|
||||
CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse(
|
||||
config[CONF_FRAMEWORK][CONF_VERSION]
|
||||
)
|
||||
@@ -555,26 +385,6 @@ def include_builtin_idf_component(name: str) -> None:
|
||||
CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS].discard(name)
|
||||
|
||||
|
||||
def _enable_arduino_library(name: str) -> None:
|
||||
"""Enable an Arduino library that is disabled by default.
|
||||
|
||||
This is called automatically by CORE.add_library() when a component adds
|
||||
an Arduino library via cg.add_library(). Components should not call this
|
||||
directly - just use cg.add_library("LibName", None).
|
||||
|
||||
Args:
|
||||
name: The library name (e.g., "Wire", "SPI", "WiFi")
|
||||
"""
|
||||
enabled_libs: set[str] = CORE.data[KEY_ESP32][KEY_ARDUINO_LIBRARIES]
|
||||
enabled_libs.add(name)
|
||||
# Also enable any required Arduino library dependencies
|
||||
for dep_lib in ARDUINO_LIBRARY_DEPENDENCIES.get(name, ()):
|
||||
enabled_libs.add(dep_lib)
|
||||
# Also enable any required IDF components
|
||||
for idf_component in ARDUINO_LIBRARY_IDF_COMPONENTS.get(name, ()):
|
||||
include_builtin_idf_component(idf_component)
|
||||
|
||||
|
||||
def add_extra_script(stage: str, filename: str, path: Path):
|
||||
"""Add an extra script to the project."""
|
||||
key = f"{stage}:{filename}"
|
||||
@@ -1316,27 +1126,6 @@ async def _write_exclude_components() -> None:
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _write_arduino_libraries_sdkconfig() -> None:
|
||||
"""Write Arduino selective compilation sdkconfig after all components have added libraries.
|
||||
|
||||
This must run at FINAL priority so that all components have had a chance to call
|
||||
cg.add_library() which auto-enables Arduino libraries via _enable_arduino_library().
|
||||
"""
|
||||
if KEY_ESP32 not in CORE.data:
|
||||
return
|
||||
# Enable Arduino selective compilation to disable unused Arduino libraries
|
||||
# ESPHome uses ESP-IDF APIs directly; we only need the Arduino core
|
||||
# (HardwareSerial, Print, Stream, GPIO functions which are always compiled)
|
||||
# cg.add_library() auto-enables needed libraries; users can also add
|
||||
# libraries via esphome: libraries: config which calls cg.add_library()
|
||||
add_idf_sdkconfig_option("CONFIG_ARDUINO_SELECTIVE_COMPILATION", True)
|
||||
enabled_libs = CORE.data[KEY_ESP32].get(KEY_ARDUINO_LIBRARIES, set())
|
||||
for lib in ARDUINO_DISABLED_LIBRARIES:
|
||||
# Enable if explicitly requested, disable otherwise
|
||||
add_idf_sdkconfig_option(f"CONFIG_ARDUINO_SELECTIVE_{lib}", lib in enabled_libs)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _add_yaml_idf_components(components: list[ConfigType]):
|
||||
"""Add IDF components from YAML config with final priority to override code-added components."""
|
||||
@@ -1755,11 +1544,6 @@ async def to_code(config):
|
||||
# Default exclusions are added in set_core_data() during config validation.
|
||||
CORE.add_job(_write_exclude_components)
|
||||
|
||||
# Write Arduino selective compilation sdkconfig at FINAL priority after all
|
||||
# components have had a chance to call cg.add_library() to enable libraries they need.
|
||||
if conf[CONF_TYPE] == FRAMEWORK_ARDUINO:
|
||||
CORE.add_job(_write_arduino_libraries_sdkconfig)
|
||||
|
||||
|
||||
APP_PARTITION_SIZES = {
|
||||
"2MB": 0x0C0000, # 768 KB
|
||||
@@ -1840,49 +1624,11 @@ def _write_sdkconfig():
|
||||
|
||||
def _write_idf_component_yml():
|
||||
yml_path = CORE.relative_build_path("src/idf_component.yml")
|
||||
dependencies: dict[str, dict] = {}
|
||||
|
||||
# For Arduino builds, override unused managed components from the Arduino framework
|
||||
# by pointing them to empty stub directories using override_path
|
||||
# This prevents the IDF component manager from downloading the real components
|
||||
if CORE.using_arduino:
|
||||
# Determine which IDF components are needed by enabled Arduino libraries
|
||||
enabled_libs = CORE.data[KEY_ESP32].get(KEY_ARDUINO_LIBRARIES, set())
|
||||
required_idf_components = {
|
||||
comp
|
||||
for lib in enabled_libs
|
||||
for comp in ARDUINO_LIBRARY_IDF_COMPONENTS.get(lib, ())
|
||||
}
|
||||
|
||||
# Only stub components that are not required by any enabled Arduino library
|
||||
components_to_stub = (
|
||||
set(ARDUINO_EXCLUDED_IDF_COMPONENTS) - required_idf_components
|
||||
)
|
||||
|
||||
stubs_dir = CORE.relative_build_path("component_stubs")
|
||||
stubs_dir.mkdir(exist_ok=True)
|
||||
for component_name in components_to_stub:
|
||||
# Create stub directory with minimal CMakeLists.txt
|
||||
stub_path = stubs_dir / _idf_component_stub_name(component_name)
|
||||
stub_path.mkdir(exist_ok=True)
|
||||
stub_cmake = stub_path / "CMakeLists.txt"
|
||||
if not stub_cmake.exists():
|
||||
stub_cmake.write_text("idf_component_register()\n")
|
||||
dependencies[_idf_component_dep_name(component_name)] = {
|
||||
"version": "*",
|
||||
"override_path": str(stub_path),
|
||||
}
|
||||
|
||||
# Remove stubs for components that are now required by enabled libraries
|
||||
for component_name in required_idf_components:
|
||||
stub_path = stubs_dir / _idf_component_stub_name(component_name)
|
||||
if stub_path.exists():
|
||||
shutil.rmtree(stub_path)
|
||||
|
||||
if CORE.data[KEY_ESP32][KEY_COMPONENTS]:
|
||||
components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS]
|
||||
dependencies = {}
|
||||
for name, component in components.items():
|
||||
dependency: dict[str, str] = {}
|
||||
dependency = {}
|
||||
if component[KEY_REF]:
|
||||
dependency["version"] = component[KEY_REF]
|
||||
if component[KEY_REPO]:
|
||||
@@ -1890,8 +1636,9 @@ def _write_idf_component_yml():
|
||||
if component[KEY_PATH]:
|
||||
dependency["path"] = component[KEY_PATH]
|
||||
dependencies[name] = dependency
|
||||
|
||||
contents = yaml_util.dump({"dependencies": dependencies}) if dependencies else ""
|
||||
contents = yaml_util.dump({"dependencies": dependencies})
|
||||
else:
|
||||
contents = ""
|
||||
if write_file_if_changed(yml_path, contents):
|
||||
dependencies_lock = CORE.relative_build_path("dependencies.lock")
|
||||
if dependencies_lock.is_file():
|
||||
|
||||
@@ -7,7 +7,6 @@ KEY_VARIANT = "variant"
|
||||
KEY_SDKCONFIG_OPTIONS = "sdkconfig_options"
|
||||
KEY_COMPONENTS = "components"
|
||||
KEY_EXCLUDE_COMPONENTS = "exclude_components"
|
||||
KEY_ARDUINO_LIBRARIES = "arduino_libraries"
|
||||
KEY_REPO = "repo"
|
||||
KEY_REF = "ref"
|
||||
KEY_REFRESH = "refresh"
|
||||
|
||||
@@ -13,7 +13,7 @@ from esphome.const import (
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_WIFI,
|
||||
)
|
||||
from esphome.core import HexInt
|
||||
from esphome.core import CORE, HexInt
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
@@ -124,6 +124,9 @@ async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
if CORE.using_arduino:
|
||||
cg.add_library("WiFi", None)
|
||||
|
||||
# ESP-NOW uses wake_loop_threadsafe() to wake the main loop from ESP-NOW callbacks
|
||||
# This enables low-latency event processing instead of waiting for select() timeout
|
||||
socket.require_wake_loop_threadsafe()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logging
|
||||
|
||||
from esphome import automation, pins
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.esp32 import (
|
||||
VARIANT_ESP32,
|
||||
@@ -35,8 +35,6 @@ from esphome.const import (
|
||||
CONF_MODE,
|
||||
CONF_MOSI_PIN,
|
||||
CONF_NUMBER,
|
||||
CONF_ON_CONNECT,
|
||||
CONF_ON_DISCONNECT,
|
||||
CONF_PAGE_ID,
|
||||
CONF_PIN,
|
||||
CONF_POLLING_INTERVAL,
|
||||
@@ -239,8 +237,6 @@ BASE_SCHEMA = cv.Schema(
|
||||
cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name,
|
||||
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
|
||||
cv.Optional(CONF_MAC_ADDRESS): cv.mac_address,
|
||||
cv.Optional(CONF_ON_CONNECT): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_ON_DISCONNECT): automation.validate_automation(single=True),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
@@ -431,17 +427,8 @@ async def to_code(config):
|
||||
# Add LAN867x 10BASE-T1S PHY support component
|
||||
add_idf_component(name="espressif/lan867x", ref="2.0.0")
|
||||
|
||||
if on_connect_config := config.get(CONF_ON_CONNECT):
|
||||
cg.add_define("USE_ETHERNET_CONNECT_TRIGGER")
|
||||
await automation.build_automation(
|
||||
var.get_connect_trigger(), [], on_connect_config
|
||||
)
|
||||
|
||||
if on_disconnect_config := config.get(CONF_ON_DISCONNECT):
|
||||
cg.add_define("USE_ETHERNET_DISCONNECT_TRIGGER")
|
||||
await automation.build_automation(
|
||||
var.get_disconnect_trigger(), [], on_disconnect_config
|
||||
)
|
||||
if CORE.using_arduino:
|
||||
cg.add_library("WiFi", None)
|
||||
|
||||
CORE.add_job(final_step)
|
||||
|
||||
|
||||
@@ -309,9 +309,6 @@ void EthernetComponent::loop() {
|
||||
|
||||
this->dump_connect_params_();
|
||||
this->status_clear_warning();
|
||||
#ifdef USE_ETHERNET_CONNECT_TRIGGER
|
||||
this->connect_trigger_.trigger();
|
||||
#endif
|
||||
} else if (now - this->connect_begin_ > 15000) {
|
||||
ESP_LOGW(TAG, "Connecting failed; reconnecting");
|
||||
this->start_connect_();
|
||||
@@ -321,16 +318,10 @@ void EthernetComponent::loop() {
|
||||
if (!this->started_) {
|
||||
ESP_LOGI(TAG, "Stopped connection");
|
||||
this->state_ = EthernetComponentState::STOPPED;
|
||||
#ifdef USE_ETHERNET_DISCONNECT_TRIGGER
|
||||
this->disconnect_trigger_.trigger();
|
||||
#endif
|
||||
} else if (!this->connected_) {
|
||||
ESP_LOGW(TAG, "Connection lost; reconnecting");
|
||||
this->state_ = EthernetComponentState::CONNECTING;
|
||||
this->start_connect_();
|
||||
#ifdef USE_ETHERNET_DISCONNECT_TRIGGER
|
||||
this->disconnect_trigger_.trigger();
|
||||
#endif
|
||||
} else {
|
||||
this->finish_connect_();
|
||||
// When connected and stable, disable the loop to save CPU cycles
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/network/ip_address.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
@@ -120,12 +119,6 @@ class EthernetComponent : public Component {
|
||||
void add_ip_state_listener(EthernetIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); }
|
||||
#endif
|
||||
|
||||
#ifdef USE_ETHERNET_CONNECT_TRIGGER
|
||||
Trigger<> *get_connect_trigger() { return &this->connect_trigger_; }
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_DISCONNECT_TRIGGER
|
||||
Trigger<> *get_disconnect_trigger() { return &this->disconnect_trigger_; }
|
||||
#endif
|
||||
protected:
|
||||
static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
@@ -197,12 +190,6 @@ class EthernetComponent : public Component {
|
||||
StaticVector<EthernetIPStateListener *, ESPHOME_ETHERNET_IP_STATE_LISTENERS> ip_state_listeners_;
|
||||
#endif
|
||||
|
||||
#ifdef USE_ETHERNET_CONNECT_TRIGGER
|
||||
Trigger<> connect_trigger_;
|
||||
#endif
|
||||
#ifdef USE_ETHERNET_DISCONNECT_TRIGGER
|
||||
Trigger<> disconnect_trigger_;
|
||||
#endif
|
||||
private:
|
||||
// Stores a pointer to a string literal (static storage duration).
|
||||
// ONLY set from Python-generated code with string literals - never dynamic strings.
|
||||
|
||||
@@ -335,18 +335,18 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
|
||||
|
||||
switch (dir) {
|
||||
case COVER_OPERATION_IDLE:
|
||||
trig = &this->stop_trigger_;
|
||||
trig = this->stop_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_OPENING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->open_trigger_;
|
||||
trig = this->open_trigger_;
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
obstacle = this->open_obstacle_;
|
||||
#endif
|
||||
break;
|
||||
case COVER_OPERATION_CLOSING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->close_trigger_;
|
||||
trig = this->close_trigger_;
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
obstacle = this->close_obstacle_;
|
||||
#endif
|
||||
|
||||
@@ -17,9 +17,9 @@ class FeedbackCover : public cover::Cover, public Component {
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
|
||||
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *get_open_trigger() const { return this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() const { return this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() const { return this->stop_trigger_; }
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
void set_open_endstop(binary_sensor::BinarySensor *open_endstop);
|
||||
@@ -61,9 +61,9 @@ class FeedbackCover : public cover::Cover, public Component {
|
||||
binary_sensor::BinarySensor *close_obstacle_{nullptr};
|
||||
|
||||
#endif
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> *open_trigger_{new Trigger<>()};
|
||||
Trigger<> *close_trigger_{new Trigger<>()};
|
||||
Trigger<> *stop_trigger_{new Trigger<>()};
|
||||
|
||||
uint32_t open_duration_{0};
|
||||
uint32_t close_duration_{0};
|
||||
|
||||
@@ -332,13 +332,13 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
void set_json(std::function<void(Ts..., JsonObject)> json_func) { this->json_func_ = json_func; }
|
||||
|
||||
#ifdef USE_HTTP_REQUEST_RESPONSE
|
||||
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *get_success_trigger_with_response() {
|
||||
return &this->success_trigger_with_response_;
|
||||
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *get_success_trigger_with_response() const {
|
||||
return this->success_trigger_with_response_;
|
||||
}
|
||||
#endif
|
||||
Trigger<std::shared_ptr<HttpContainer>, Ts...> *get_success_trigger() { return &this->success_trigger_; }
|
||||
Trigger<std::shared_ptr<HttpContainer>, Ts...> *get_success_trigger() const { return this->success_trigger_; }
|
||||
|
||||
Trigger<Ts...> *get_error_trigger() { return &this->error_trigger_; }
|
||||
Trigger<Ts...> *get_error_trigger() const { return this->error_trigger_; }
|
||||
|
||||
void set_max_response_buffer_size(size_t max_response_buffer_size) {
|
||||
this->max_response_buffer_size_ = max_response_buffer_size;
|
||||
@@ -372,7 +372,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
auto captured_args = std::make_tuple(x...);
|
||||
|
||||
if (container == nullptr) {
|
||||
std::apply([this](Ts... captured_args_inner) { this->error_trigger_.trigger(captured_args_inner...); },
|
||||
std::apply([this](Ts... captured_args_inner) { this->error_trigger_->trigger(captured_args_inner...); },
|
||||
captured_args);
|
||||
return;
|
||||
}
|
||||
@@ -406,14 +406,14 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
}
|
||||
std::apply(
|
||||
[this, &container, &response_body](Ts... captured_args_inner) {
|
||||
this->success_trigger_with_response_.trigger(container, response_body, captured_args_inner...);
|
||||
this->success_trigger_with_response_->trigger(container, response_body, captured_args_inner...);
|
||||
},
|
||||
captured_args);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
std::apply([this, &container](
|
||||
Ts... captured_args_inner) { this->success_trigger_.trigger(container, captured_args_inner...); },
|
||||
Ts... captured_args_inner) { this->success_trigger_->trigger(container, captured_args_inner...); },
|
||||
captured_args);
|
||||
}
|
||||
container->end();
|
||||
@@ -433,10 +433,12 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
std::map<const char *, TemplatableValue<std::string, Ts...>> json_{};
|
||||
std::function<void(Ts..., JsonObject)> json_func_{nullptr};
|
||||
#ifdef USE_HTTP_REQUEST_RESPONSE
|
||||
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> success_trigger_with_response_;
|
||||
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *success_trigger_with_response_ =
|
||||
new Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...>();
|
||||
#endif
|
||||
Trigger<std::shared_ptr<HttpContainer>, Ts...> success_trigger_;
|
||||
Trigger<Ts...> error_trigger_;
|
||||
Trigger<std::shared_ptr<HttpContainer>, Ts...> *success_trigger_ =
|
||||
new Trigger<std::shared_ptr<HttpContainer>, Ts...>();
|
||||
Trigger<Ts...> *error_trigger_ = new Trigger<Ts...>();
|
||||
|
||||
size_t max_response_buffer_size_{SIZE_MAX};
|
||||
};
|
||||
|
||||
@@ -114,7 +114,6 @@ async def to_code(config):
|
||||
cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1))
|
||||
cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb"))
|
||||
|
||||
cg.add_library("WiFi", None)
|
||||
cg.add_library("NetworkClientSecure", None)
|
||||
cg.add_library("HTTPClient", None)
|
||||
cg.add_library("esphome/ESP32-audioI2S", "2.3.0")
|
||||
|
||||
@@ -138,20 +138,20 @@ class LambdaLightEffect : public LightEffect {
|
||||
class AutomationLightEffect : public LightEffect {
|
||||
public:
|
||||
AutomationLightEffect(const char *name) : LightEffect(name) {}
|
||||
void stop() override { this->trig_.stop_action(); }
|
||||
void stop() override { this->trig_->stop_action(); }
|
||||
void apply() override {
|
||||
if (!this->trig_.is_action_running()) {
|
||||
this->trig_.trigger();
|
||||
if (!this->trig_->is_action_running()) {
|
||||
this->trig_->trigger();
|
||||
}
|
||||
}
|
||||
Trigger<> *get_trig() { return &this->trig_; }
|
||||
Trigger<> *get_trig() const { return trig_; }
|
||||
|
||||
/// Get the current effect index for use in automations.
|
||||
/// Useful for automations that need to know which effect is running.
|
||||
uint32_t get_current_index() const { return this->get_index(); }
|
||||
|
||||
protected:
|
||||
Trigger<> trig_;
|
||||
Trigger<> *trig_{new Trigger<>};
|
||||
};
|
||||
|
||||
struct StrobeLightEffectColor {
|
||||
|
||||
@@ -325,7 +325,7 @@ void MicroWakeWord::loop() {
|
||||
ESP_LOGD(TAG, "Detected '%s' with sliding average probability is %.2f and max probability is %.2f",
|
||||
detection_event.wake_word->c_str(), (detection_event.average_probability / uint8_to_float_divisor),
|
||||
(detection_event.max_probability / uint8_to_float_divisor));
|
||||
this->wake_word_detected_trigger_.trigger(*detection_event.wake_word);
|
||||
this->wake_word_detected_trigger_->trigger(*detection_event.wake_word);
|
||||
if (this->stop_after_detection_) {
|
||||
this->stop();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class MicroWakeWord : public Component
|
||||
|
||||
void set_stop_after_detection(bool stop_after_detection) { this->stop_after_detection_ = stop_after_detection; }
|
||||
|
||||
Trigger<std::string> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; }
|
||||
Trigger<std::string> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
|
||||
|
||||
void add_wake_word_model(WakeWordModel *model);
|
||||
|
||||
@@ -78,7 +78,7 @@ class MicroWakeWord : public Component
|
||||
|
||||
protected:
|
||||
microphone::MicrophoneSource *microphone_source_{nullptr};
|
||||
Trigger<std::string> wake_word_detected_trigger_;
|
||||
Trigger<std::string> *wake_word_detected_trigger_ = new Trigger<std::string>();
|
||||
State state_{State::STOPPED};
|
||||
|
||||
std::weak_ptr<RingBuffer> ring_buffer_;
|
||||
|
||||
@@ -30,7 +30,7 @@ from esphome.const import (
|
||||
UNIT_PERCENT,
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import CORE, coroutine
|
||||
from esphome.core import coroutine
|
||||
|
||||
CODEOWNERS = ["@dudanov"]
|
||||
DEPENDENCIES = ["climate", "uart"]
|
||||
@@ -290,7 +290,4 @@ async def to_code(config):
|
||||
if CONF_HUMIDITY_SETPOINT in config:
|
||||
sens = await sensor.new_sensor(config[CONF_HUMIDITY_SETPOINT])
|
||||
cg.add(var.set_humidity_setpoint_sensor(sens))
|
||||
# MideaUART library requires WiFi (WiFi auto-enables Network via dependency mapping)
|
||||
if CORE.is_esp32:
|
||||
cg.add_library("WiFi", None)
|
||||
cg.add_library("dudanov/MideaUART", "1.1.9")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "mixer_speaker.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
@@ -139,8 +139,7 @@ class MQTTBackendESP32 final : public MQTTBackend {
|
||||
this->lwt_retain_ = retain;
|
||||
}
|
||||
void set_server(network::IPAddress ip, uint16_t port) final {
|
||||
char ip_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
this->host_ = ip.str_to(ip_buf);
|
||||
this->host_ = ip.str();
|
||||
this->port_ = port;
|
||||
}
|
||||
void set_server(const char *host, uint16_t port) final {
|
||||
|
||||
@@ -137,7 +137,8 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
@coroutine_with_priority(CoroPriority.NETWORK)
|
||||
async def to_code(config):
|
||||
cg.add_define("USE_NETWORK")
|
||||
# ESP32 with Arduino uses ESP-IDF network APIs directly, no Arduino Network library needed
|
||||
if CORE.using_arduino and CORE.is_esp32:
|
||||
cg.add_library("Networking", None)
|
||||
|
||||
# Apply high performance networking settings
|
||||
# Config can explicitly enable/disable, or default to component-driven behavior
|
||||
|
||||
@@ -83,7 +83,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
uint32_t on_time, off_time;
|
||||
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time);
|
||||
this->target_time_ = 0;
|
||||
this->transmit_trigger_.trigger();
|
||||
this->transmit_trigger_->trigger();
|
||||
for (uint32_t i = 0; i < send_times; i++) {
|
||||
InterruptLock lock;
|
||||
for (int32_t item : this->temp_.get_data()) {
|
||||
@@ -102,7 +102,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
if (i + 1 < send_times)
|
||||
this->target_time_ += send_wait;
|
||||
}
|
||||
this->complete_trigger_.trigger();
|
||||
this->complete_trigger_->trigger();
|
||||
}
|
||||
|
||||
} // namespace remote_transmitter
|
||||
|
||||
@@ -57,8 +57,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
||||
void set_non_blocking(bool non_blocking) { this->non_blocking_ = non_blocking; }
|
||||
#endif
|
||||
|
||||
Trigger<> *get_transmit_trigger() { return &this->transmit_trigger_; }
|
||||
Trigger<> *get_complete_trigger() { return &this->complete_trigger_; }
|
||||
Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; };
|
||||
Trigger<> *get_complete_trigger() const { return this->complete_trigger_; };
|
||||
|
||||
protected:
|
||||
void send_internal(uint32_t send_times, uint32_t send_wait) override;
|
||||
@@ -96,8 +96,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
||||
#endif
|
||||
uint8_t carrier_duty_percent_;
|
||||
|
||||
Trigger<> transmit_trigger_;
|
||||
Trigger<> complete_trigger_;
|
||||
Trigger<> *transmit_trigger_{new Trigger<>()};
|
||||
Trigger<> *complete_trigger_{new Trigger<>()};
|
||||
};
|
||||
|
||||
} // namespace remote_transmitter
|
||||
|
||||
@@ -203,7 +203,7 @@ void RemoteTransmitterComponent::wait_for_rmt_() {
|
||||
this->status_set_warning();
|
||||
}
|
||||
|
||||
this->complete_trigger_.trigger();
|
||||
this->complete_trigger_->trigger();
|
||||
}
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1)
|
||||
@@ -264,7 +264,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
return;
|
||||
}
|
||||
|
||||
this->transmit_trigger_.trigger();
|
||||
this->transmit_trigger_->trigger();
|
||||
|
||||
rmt_transmit_config_t config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
@@ -333,7 +333,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
ESP_LOGE(TAG, "Empty data");
|
||||
return;
|
||||
}
|
||||
this->transmit_trigger_.trigger();
|
||||
this->transmit_trigger_->trigger();
|
||||
for (uint32_t i = 0; i < send_times; i++) {
|
||||
rmt_transmit_config_t config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
@@ -354,7 +354,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
if (i + 1 < send_times)
|
||||
delayMicroseconds(send_wait);
|
||||
}
|
||||
this->complete_trigger_.trigger();
|
||||
this->complete_trigger_->trigger();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -519,9 +519,9 @@ void SpeakerMediaPlayer::set_mute_state_(bool mute_state) {
|
||||
|
||||
if (old_mute_state != mute_state) {
|
||||
if (mute_state) {
|
||||
this->defer([this]() { this->mute_trigger_.trigger(); });
|
||||
this->defer([this]() { this->mute_trigger_->trigger(); });
|
||||
} else {
|
||||
this->defer([this]() { this->unmute_trigger_.trigger(); });
|
||||
this->defer([this]() { this->unmute_trigger_->trigger(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -550,7 +550,7 @@ void SpeakerMediaPlayer::set_volume_(float volume, bool publish) {
|
||||
this->set_mute_state_(false);
|
||||
}
|
||||
|
||||
this->defer([this, volume]() { this->volume_trigger_.trigger(volume); });
|
||||
this->defer([this, volume]() { this->volume_trigger_->trigger(volume); });
|
||||
}
|
||||
|
||||
} // namespace speaker
|
||||
|
||||
@@ -84,9 +84,9 @@ class SpeakerMediaPlayer : public Component,
|
||||
this->media_format_ = media_format;
|
||||
}
|
||||
|
||||
Trigger<> *get_mute_trigger() { return &this->mute_trigger_; }
|
||||
Trigger<> *get_unmute_trigger() { return &this->unmute_trigger_; }
|
||||
Trigger<float> *get_volume_trigger() { return &this->volume_trigger_; }
|
||||
Trigger<> *get_mute_trigger() const { return this->mute_trigger_; }
|
||||
Trigger<> *get_unmute_trigger() const { return this->unmute_trigger_; }
|
||||
Trigger<float> *get_volume_trigger() const { return this->volume_trigger_; }
|
||||
|
||||
void play_file(audio::AudioFile *media_file, bool announcement, bool enqueue);
|
||||
|
||||
@@ -154,9 +154,9 @@ class SpeakerMediaPlayer : public Component,
|
||||
// Used to save volume/mute state for restoration on reboot
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
Trigger<> mute_trigger_;
|
||||
Trigger<> unmute_trigger_;
|
||||
Trigger<float> volume_trigger_;
|
||||
Trigger<> *mute_trigger_ = new Trigger<>();
|
||||
Trigger<> *unmute_trigger_ = new Trigger<>();
|
||||
Trigger<float> *volume_trigger_ = new Trigger<float>();
|
||||
};
|
||||
|
||||
} // namespace speaker
|
||||
|
||||
@@ -29,7 +29,7 @@ void SprinklerControllerNumber::setup() {
|
||||
}
|
||||
|
||||
void SprinklerControllerNumber::control(float value) {
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
this->publish_state(value);
|
||||
|
||||
@@ -39,7 +39,8 @@ void SprinklerControllerNumber::control(float value) {
|
||||
|
||||
void SprinklerControllerNumber::dump_config() { LOG_NUMBER("", "Sprinkler Controller Number", this); }
|
||||
|
||||
SprinklerControllerSwitch::SprinklerControllerSwitch() = default;
|
||||
SprinklerControllerSwitch::SprinklerControllerSwitch()
|
||||
: turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {}
|
||||
|
||||
void SprinklerControllerSwitch::loop() {
|
||||
// Loop is only enabled when f_ has a value (see setup())
|
||||
@@ -55,11 +56,11 @@ void SprinklerControllerSwitch::write_state(bool state) {
|
||||
}
|
||||
|
||||
if (state) {
|
||||
this->prev_trigger_ = &this->turn_on_trigger_;
|
||||
this->turn_on_trigger_.trigger();
|
||||
this->prev_trigger_ = this->turn_on_trigger_;
|
||||
this->turn_on_trigger_->trigger();
|
||||
} else {
|
||||
this->prev_trigger_ = &this->turn_off_trigger_;
|
||||
this->turn_off_trigger_.trigger();
|
||||
this->prev_trigger_ = this->turn_off_trigger_;
|
||||
this->turn_off_trigger_->trigger();
|
||||
}
|
||||
|
||||
this->publish_state(state);
|
||||
@@ -68,6 +69,9 @@ void SprinklerControllerSwitch::write_state(bool state) {
|
||||
void SprinklerControllerSwitch::set_state_lambda(std::function<optional<bool>()> &&f) { this->f_ = f; }
|
||||
float SprinklerControllerSwitch::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<> *SprinklerControllerSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; }
|
||||
Trigger<> *SprinklerControllerSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; }
|
||||
|
||||
void SprinklerControllerSwitch::setup() {
|
||||
this->state = this->get_initial_state_with_restore_mode().value_or(false);
|
||||
// Disable loop if no state lambda is set - nothing to poll
|
||||
|
||||
@@ -76,7 +76,7 @@ class SprinklerControllerNumber : public number::Number, public Component {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::PROCESSOR; }
|
||||
|
||||
Trigger<float> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<float> *get_set_trigger() const { return set_trigger_; }
|
||||
void set_initial_value(float initial_value) { initial_value_ = initial_value; }
|
||||
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
||||
|
||||
@@ -84,7 +84,7 @@ class SprinklerControllerNumber : public number::Number, public Component {
|
||||
void control(float value) override;
|
||||
float initial_value_{NAN};
|
||||
bool restore_value_{true};
|
||||
Trigger<float> set_trigger_;
|
||||
Trigger<float> *set_trigger_ = new Trigger<float>();
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
};
|
||||
@@ -97,8 +97,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component {
|
||||
void dump_config() override;
|
||||
|
||||
void set_state_lambda(std::function<optional<bool>()> &&f);
|
||||
Trigger<> *get_turn_on_trigger() { return &this->turn_on_trigger_; }
|
||||
Trigger<> *get_turn_off_trigger() { return &this->turn_off_trigger_; }
|
||||
Trigger<> *get_turn_on_trigger() const;
|
||||
Trigger<> *get_turn_off_trigger() const;
|
||||
void loop() override;
|
||||
|
||||
float get_setup_priority() const override;
|
||||
@@ -107,8 +107,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component {
|
||||
void write_state(bool state) override;
|
||||
|
||||
optional<std::function<optional<bool>()>> f_;
|
||||
Trigger<> turn_on_trigger_;
|
||||
Trigger<> turn_off_trigger_;
|
||||
Trigger<> *turn_on_trigger_;
|
||||
Trigger<> *turn_off_trigger_;
|
||||
Trigger<> *prev_trigger_{nullptr};
|
||||
};
|
||||
|
||||
|
||||
@@ -343,7 +343,7 @@ void SX126x::call_listeners_(const std::vector<uint8_t> &packet, float rssi, flo
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_packet(packet, rssi, snr);
|
||||
}
|
||||
this->packet_trigger_.trigger(packet, rssi, snr);
|
||||
this->packet_trigger_->trigger(packet, rssi, snr);
|
||||
}
|
||||
|
||||
void SX126x::loop() {
|
||||
|
||||
@@ -97,7 +97,7 @@ class SX126x : public Component,
|
||||
void configure();
|
||||
SX126xError transmit_packet(const std::vector<uint8_t> &packet);
|
||||
void register_listener(SX126xListener *listener) { this->listeners_.push_back(listener); }
|
||||
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() { return &this->packet_trigger_; }
|
||||
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() const { return this->packet_trigger_; };
|
||||
|
||||
protected:
|
||||
void configure_fsk_ook_();
|
||||
@@ -111,7 +111,7 @@ class SX126x : public Component,
|
||||
void read_register_(uint16_t reg, uint8_t *data, uint8_t size);
|
||||
void call_listeners_(const std::vector<uint8_t> &packet, float rssi, float snr);
|
||||
void wait_busy_();
|
||||
Trigger<std::vector<uint8_t>, float, float> packet_trigger_;
|
||||
Trigger<std::vector<uint8_t>, float, float> *packet_trigger_{new Trigger<std::vector<uint8_t>, float, float>()};
|
||||
std::vector<SX126xListener *> listeners_;
|
||||
std::vector<uint8_t> packet_;
|
||||
std::vector<uint8_t> sync_value_;
|
||||
|
||||
@@ -300,7 +300,7 @@ void SX127x::call_listeners_(const std::vector<uint8_t> &packet, float rssi, flo
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_packet(packet, rssi, snr);
|
||||
}
|
||||
this->packet_trigger_.trigger(packet, rssi, snr);
|
||||
this->packet_trigger_->trigger(packet, rssi, snr);
|
||||
}
|
||||
|
||||
void SX127x::loop() {
|
||||
|
||||
@@ -83,7 +83,7 @@ class SX127x : public Component,
|
||||
void configure();
|
||||
SX127xError transmit_packet(const std::vector<uint8_t> &packet);
|
||||
void register_listener(SX127xListener *listener) { this->listeners_.push_back(listener); }
|
||||
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() { return &this->packet_trigger_; }
|
||||
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() const { return this->packet_trigger_; };
|
||||
|
||||
protected:
|
||||
void configure_fsk_ook_();
|
||||
@@ -94,7 +94,7 @@ class SX127x : public Component,
|
||||
void write_register_(uint8_t reg, uint8_t value);
|
||||
void call_listeners_(const std::vector<uint8_t> &packet, float rssi, float snr);
|
||||
uint8_t read_register_(uint8_t reg);
|
||||
Trigger<std::vector<uint8_t>, float, float> packet_trigger_;
|
||||
Trigger<std::vector<uint8_t>, float, float> *packet_trigger_{new Trigger<std::vector<uint8_t>, float, float>()};
|
||||
std::vector<SX127xListener *> listeners_;
|
||||
std::vector<uint8_t> packet_;
|
||||
std::vector<uint8_t> sync_value_;
|
||||
|
||||
@@ -7,7 +7,13 @@ using namespace esphome::cover;
|
||||
|
||||
static const char *const TAG = "template.cover";
|
||||
|
||||
TemplateCover::TemplateCover() = default;
|
||||
TemplateCover::TemplateCover()
|
||||
: open_trigger_(new Trigger<>()),
|
||||
close_trigger_(new Trigger<>),
|
||||
stop_trigger_(new Trigger<>()),
|
||||
toggle_trigger_(new Trigger<>()),
|
||||
position_trigger_(new Trigger<float>()),
|
||||
tilt_trigger_(new Trigger<float>()) {}
|
||||
void TemplateCover::setup() {
|
||||
switch (this->restore_mode_) {
|
||||
case COVER_NO_RESTORE:
|
||||
@@ -56,22 +62,22 @@ void TemplateCover::loop() {
|
||||
void TemplateCover::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
void TemplateCover::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; }
|
||||
float TemplateCover::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
Trigger<> *TemplateCover::get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *TemplateCover::get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *TemplateCover::get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *TemplateCover::get_toggle_trigger() { return &this->toggle_trigger_; }
|
||||
Trigger<> *TemplateCover::get_open_trigger() const { return this->open_trigger_; }
|
||||
Trigger<> *TemplateCover::get_close_trigger() const { return this->close_trigger_; }
|
||||
Trigger<> *TemplateCover::get_stop_trigger() const { return this->stop_trigger_; }
|
||||
Trigger<> *TemplateCover::get_toggle_trigger() const { return this->toggle_trigger_; }
|
||||
void TemplateCover::dump_config() { LOG_COVER("", "Template Cover", this); }
|
||||
void TemplateCover::control(const CoverCall &call) {
|
||||
if (call.get_stop()) {
|
||||
this->stop_prev_trigger_();
|
||||
this->stop_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->stop_trigger_;
|
||||
this->stop_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->stop_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_toggle().has_value()) {
|
||||
this->stop_prev_trigger_();
|
||||
this->toggle_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->toggle_trigger_;
|
||||
this->toggle_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->toggle_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
@@ -79,13 +85,13 @@ void TemplateCover::control(const CoverCall &call) {
|
||||
this->stop_prev_trigger_();
|
||||
|
||||
if (pos == COVER_OPEN) {
|
||||
this->open_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->open_trigger_;
|
||||
this->open_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->open_trigger_;
|
||||
} else if (pos == COVER_CLOSED) {
|
||||
this->close_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->close_trigger_;
|
||||
this->close_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->close_trigger_;
|
||||
} else {
|
||||
this->position_trigger_.trigger(pos);
|
||||
this->position_trigger_->trigger(pos);
|
||||
}
|
||||
|
||||
if (this->optimistic_) {
|
||||
@@ -95,7 +101,7 @@ void TemplateCover::control(const CoverCall &call) {
|
||||
|
||||
if (call.get_tilt().has_value()) {
|
||||
auto tilt = *call.get_tilt();
|
||||
this->tilt_trigger_.trigger(tilt);
|
||||
this->tilt_trigger_->trigger(tilt);
|
||||
|
||||
if (this->optimistic_) {
|
||||
this->tilt = tilt;
|
||||
@@ -113,8 +119,8 @@ CoverTraits TemplateCover::get_traits() {
|
||||
traits.set_supports_tilt(this->has_tilt_);
|
||||
return traits;
|
||||
}
|
||||
Trigger<float> *TemplateCover::get_position_trigger() { return &this->position_trigger_; }
|
||||
Trigger<float> *TemplateCover::get_tilt_trigger() { return &this->tilt_trigger_; }
|
||||
Trigger<float> *TemplateCover::get_position_trigger() const { return this->position_trigger_; }
|
||||
Trigger<float> *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; }
|
||||
void TemplateCover::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; }
|
||||
void TemplateCover::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; }
|
||||
void TemplateCover::set_has_position(bool has_position) { this->has_position_ = has_position; }
|
||||
|
||||
@@ -19,12 +19,12 @@ class TemplateCover final : public cover::Cover, public Component {
|
||||
|
||||
template<typename F> void set_state_lambda(F &&f) { this->state_f_.set(std::forward<F>(f)); }
|
||||
template<typename F> void set_tilt_lambda(F &&f) { this->tilt_f_.set(std::forward<F>(f)); }
|
||||
Trigger<> *get_open_trigger();
|
||||
Trigger<> *get_close_trigger();
|
||||
Trigger<> *get_stop_trigger();
|
||||
Trigger<> *get_toggle_trigger();
|
||||
Trigger<float> *get_position_trigger();
|
||||
Trigger<float> *get_tilt_trigger();
|
||||
Trigger<> *get_open_trigger() const;
|
||||
Trigger<> *get_close_trigger() const;
|
||||
Trigger<> *get_stop_trigger() const;
|
||||
Trigger<> *get_toggle_trigger() const;
|
||||
Trigger<float> *get_position_trigger() const;
|
||||
Trigger<float> *get_tilt_trigger() const;
|
||||
void set_optimistic(bool optimistic);
|
||||
void set_assumed_state(bool assumed_state);
|
||||
void set_has_stop(bool has_stop);
|
||||
@@ -49,16 +49,16 @@ class TemplateCover final : public cover::Cover, public Component {
|
||||
TemplateLambda<float> tilt_f_;
|
||||
bool assumed_state_{false};
|
||||
bool optimistic_{false};
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> *open_trigger_;
|
||||
Trigger<> *close_trigger_;
|
||||
bool has_stop_{false};
|
||||
bool has_toggle_{false};
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> toggle_trigger_;
|
||||
Trigger<> *stop_trigger_;
|
||||
Trigger<> *toggle_trigger_;
|
||||
Trigger<> *prev_command_trigger_{nullptr};
|
||||
Trigger<float> position_trigger_;
|
||||
Trigger<float> *position_trigger_;
|
||||
bool has_position_{false};
|
||||
Trigger<float> tilt_trigger_;
|
||||
Trigger<float> *tilt_trigger_;
|
||||
bool has_tilt_{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void TemplateDate::control(const datetime::DateCall &call) {
|
||||
if (has_day)
|
||||
value.day_of_month = *call.get_day();
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_year)
|
||||
|
||||
@@ -22,7 +22,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
|
||||
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
|
||||
@@ -34,7 +34,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent
|
||||
bool optimistic_{false};
|
||||
ESPTime initial_value_{};
|
||||
bool restore_value_{false};
|
||||
Trigger<ESPTime> set_trigger_;
|
||||
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
|
||||
TemplateLambda<ESPTime> f_;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
@@ -80,7 +80,7 @@ void TemplateDateTime::control(const datetime::DateTimeCall &call) {
|
||||
if (has_second)
|
||||
value.second = *call.get_second();
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_year)
|
||||
|
||||
@@ -22,7 +22,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
|
||||
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
|
||||
@@ -34,7 +34,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo
|
||||
bool optimistic_{false};
|
||||
ESPTime initial_value_{};
|
||||
bool restore_value_{false};
|
||||
Trigger<ESPTime> set_trigger_;
|
||||
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
|
||||
TemplateLambda<ESPTime> f_;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
@@ -62,7 +62,7 @@ void TemplateTime::control(const datetime::TimeCall &call) {
|
||||
if (has_second)
|
||||
value.second = *call.get_second();
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_hour)
|
||||
|
||||
@@ -22,7 +22,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
|
||||
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
|
||||
@@ -34,7 +34,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent
|
||||
bool optimistic_{false};
|
||||
ESPTime initial_value_{};
|
||||
bool restore_value_{false};
|
||||
Trigger<ESPTime> set_trigger_;
|
||||
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
|
||||
TemplateLambda<ESPTime> f_;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
@@ -7,7 +7,8 @@ using namespace esphome::lock;
|
||||
|
||||
static const char *const TAG = "template.lock";
|
||||
|
||||
TemplateLock::TemplateLock() = default;
|
||||
TemplateLock::TemplateLock()
|
||||
: lock_trigger_(new Trigger<>()), unlock_trigger_(new Trigger<>()), open_trigger_(new Trigger<>()) {}
|
||||
|
||||
void TemplateLock::setup() {
|
||||
if (!this->f_.has_value())
|
||||
@@ -27,11 +28,11 @@ void TemplateLock::control(const lock::LockCall &call) {
|
||||
|
||||
auto state = *call.get_state();
|
||||
if (state == LOCK_STATE_LOCKED) {
|
||||
this->prev_trigger_ = &this->lock_trigger_;
|
||||
this->lock_trigger_.trigger();
|
||||
this->prev_trigger_ = this->lock_trigger_;
|
||||
this->lock_trigger_->trigger();
|
||||
} else if (state == LOCK_STATE_UNLOCKED) {
|
||||
this->prev_trigger_ = &this->unlock_trigger_;
|
||||
this->unlock_trigger_.trigger();
|
||||
this->prev_trigger_ = this->unlock_trigger_;
|
||||
this->unlock_trigger_->trigger();
|
||||
}
|
||||
|
||||
if (this->optimistic_)
|
||||
@@ -41,11 +42,14 @@ void TemplateLock::open_latch() {
|
||||
if (this->prev_trigger_ != nullptr) {
|
||||
this->prev_trigger_->stop_action();
|
||||
}
|
||||
this->prev_trigger_ = &this->open_trigger_;
|
||||
this->open_trigger_.trigger();
|
||||
this->prev_trigger_ = this->open_trigger_;
|
||||
this->open_trigger_->trigger();
|
||||
}
|
||||
void TemplateLock::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
float TemplateLock::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
Trigger<> *TemplateLock::get_lock_trigger() const { return this->lock_trigger_; }
|
||||
Trigger<> *TemplateLock::get_unlock_trigger() const { return this->unlock_trigger_; }
|
||||
Trigger<> *TemplateLock::get_open_trigger() const { return this->open_trigger_; }
|
||||
void TemplateLock::dump_config() {
|
||||
LOG_LOCK("", "Template Lock", this);
|
||||
ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_));
|
||||
|
||||
@@ -15,9 +15,9 @@ class TemplateLock final : public lock::Lock, public Component {
|
||||
void dump_config() override;
|
||||
|
||||
template<typename F> void set_state_lambda(F &&f) { this->f_.set(std::forward<F>(f)); }
|
||||
Trigger<> *get_lock_trigger() { return &this->lock_trigger_; }
|
||||
Trigger<> *get_unlock_trigger() { return &this->unlock_trigger_; }
|
||||
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *get_lock_trigger() const;
|
||||
Trigger<> *get_unlock_trigger() const;
|
||||
Trigger<> *get_open_trigger() const;
|
||||
void set_optimistic(bool optimistic);
|
||||
void loop() override;
|
||||
|
||||
@@ -29,9 +29,9 @@ class TemplateLock final : public lock::Lock, public Component {
|
||||
|
||||
TemplateLambda<lock::LockState> f_;
|
||||
bool optimistic_{false};
|
||||
Trigger<> lock_trigger_;
|
||||
Trigger<> unlock_trigger_;
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> *lock_trigger_;
|
||||
Trigger<> *unlock_trigger_;
|
||||
Trigger<> *open_trigger_;
|
||||
Trigger<> *prev_trigger_{nullptr};
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ void TemplateNumber::update() {
|
||||
}
|
||||
|
||||
void TemplateNumber::control(float value) {
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
if (this->optimistic_)
|
||||
this->publish_state(value);
|
||||
|
||||
@@ -17,7 +17,7 @@ class TemplateNumber final : public number::Number, public PollingComponent {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<float> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<float> *get_set_trigger() const { return set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { optimistic_ = optimistic; }
|
||||
void set_initial_value(float initial_value) { initial_value_ = initial_value; }
|
||||
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
||||
@@ -27,7 +27,7 @@ class TemplateNumber final : public number::Number, public PollingComponent {
|
||||
bool optimistic_{false};
|
||||
float initial_value_{NAN};
|
||||
bool restore_value_{false};
|
||||
Trigger<float> set_trigger_;
|
||||
Trigger<float> *set_trigger_ = new Trigger<float>();
|
||||
TemplateLambda<float> f_;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
|
||||
@@ -8,22 +8,22 @@ namespace esphome::template_ {
|
||||
|
||||
class TemplateBinaryOutput final : public output::BinaryOutput {
|
||||
public:
|
||||
Trigger<bool> *get_trigger() { return &this->trigger_; }
|
||||
Trigger<bool> *get_trigger() const { return trigger_; }
|
||||
|
||||
protected:
|
||||
void write_state(bool state) override { this->trigger_.trigger(state); }
|
||||
void write_state(bool state) override { this->trigger_->trigger(state); }
|
||||
|
||||
Trigger<bool> trigger_;
|
||||
Trigger<bool> *trigger_ = new Trigger<bool>();
|
||||
};
|
||||
|
||||
class TemplateFloatOutput final : public output::FloatOutput {
|
||||
public:
|
||||
Trigger<float> *get_trigger() { return &this->trigger_; }
|
||||
Trigger<float> *get_trigger() const { return trigger_; }
|
||||
|
||||
protected:
|
||||
void write_state(float state) override { this->trigger_.trigger(state); }
|
||||
void write_state(float state) override { this->trigger_->trigger(state); }
|
||||
|
||||
Trigger<float> trigger_;
|
||||
Trigger<float> *trigger_ = new Trigger<float>();
|
||||
};
|
||||
|
||||
} // namespace esphome::template_
|
||||
|
||||
@@ -17,6 +17,9 @@ from .. import template_ns
|
||||
TemplateSelect = template_ns.class_(
|
||||
"TemplateSelect", select.Select, cg.PollingComponent
|
||||
)
|
||||
TemplateSelectWithSetAction = template_ns.class_(
|
||||
"TemplateSelectWithSetAction", TemplateSelect
|
||||
)
|
||||
|
||||
|
||||
def validate(config):
|
||||
@@ -39,6 +42,11 @@ def validate(config):
|
||||
raise cv.Invalid(
|
||||
"Either optimistic mode must be enabled, or set_action must be set, to handle the option being set."
|
||||
)
|
||||
|
||||
# Use subclass with trigger only when set_action is configured
|
||||
if CONF_SET_ACTION in config:
|
||||
config[CONF_ID].type = TemplateSelectWithSetAction
|
||||
|
||||
return config
|
||||
|
||||
|
||||
|
||||
@@ -41,8 +41,6 @@ void TemplateSelect::update() {
|
||||
}
|
||||
|
||||
void TemplateSelect::control(size_t index) {
|
||||
this->set_trigger_->trigger(StringRef(this->option_at(index)));
|
||||
|
||||
if (this->optimistic_)
|
||||
this->publish_state(index);
|
||||
|
||||
@@ -50,6 +48,11 @@ void TemplateSelect::control(size_t index) {
|
||||
this->pref_.save(&index);
|
||||
}
|
||||
|
||||
void TemplateSelectWithSetAction::control(size_t index) {
|
||||
this->set_trigger_.trigger(StringRef(this->option_at(index)));
|
||||
TemplateSelect::control(index);
|
||||
}
|
||||
|
||||
void TemplateSelect::dump_config() {
|
||||
LOG_SELECT("", "Template Select", this);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
namespace esphome::template_ {
|
||||
|
||||
class TemplateSelect final : public select::Select, public PollingComponent {
|
||||
/// Base template select class - used when no set_action is configured
|
||||
class TemplateSelect : public select::Select, public PollingComponent {
|
||||
public:
|
||||
template<typename F> void set_template(F &&f) { this->f_.set(std::forward<F>(f)); }
|
||||
|
||||
@@ -18,7 +19,6 @@ class TemplateSelect final : public select::Select, public PollingComponent {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<StringRef> *get_set_trigger() const { return this->set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
void set_initial_option_index(size_t initial_option_index) { this->initial_option_index_ = initial_option_index; }
|
||||
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
||||
@@ -28,10 +28,19 @@ class TemplateSelect final : public select::Select, public PollingComponent {
|
||||
bool optimistic_ = false;
|
||||
size_t initial_option_index_{0};
|
||||
bool restore_value_ = false;
|
||||
Trigger<StringRef> *set_trigger_ = new Trigger<StringRef>();
|
||||
TemplateLambda<std::string> f_;
|
||||
|
||||
ESPPreferenceObject pref_;
|
||||
};
|
||||
|
||||
/// Template select with set_action trigger - only instantiated when set_action is configured
|
||||
class TemplateSelectWithSetAction final : public TemplateSelect {
|
||||
public:
|
||||
Trigger<StringRef> *get_set_trigger() { return &this->set_trigger_; }
|
||||
|
||||
protected:
|
||||
void control(size_t index) override;
|
||||
Trigger<StringRef> set_trigger_;
|
||||
};
|
||||
|
||||
} // namespace esphome::template_
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace esphome::template_ {
|
||||
|
||||
static const char *const TAG = "template.switch";
|
||||
|
||||
TemplateSwitch::TemplateSwitch() = default;
|
||||
TemplateSwitch::TemplateSwitch() : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {}
|
||||
|
||||
void TemplateSwitch::loop() {
|
||||
auto s = this->f_();
|
||||
@@ -19,11 +19,11 @@ void TemplateSwitch::write_state(bool state) {
|
||||
}
|
||||
|
||||
if (state) {
|
||||
this->prev_trigger_ = &this->turn_on_trigger_;
|
||||
this->turn_on_trigger_.trigger();
|
||||
this->prev_trigger_ = this->turn_on_trigger_;
|
||||
this->turn_on_trigger_->trigger();
|
||||
} else {
|
||||
this->prev_trigger_ = &this->turn_off_trigger_;
|
||||
this->turn_off_trigger_.trigger();
|
||||
this->prev_trigger_ = this->turn_off_trigger_;
|
||||
this->turn_off_trigger_->trigger();
|
||||
}
|
||||
|
||||
if (this->optimistic_)
|
||||
@@ -32,8 +32,8 @@ void TemplateSwitch::write_state(bool state) {
|
||||
void TemplateSwitch::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
bool TemplateSwitch::assumed_state() { return this->assumed_state_; }
|
||||
float TemplateSwitch::get_setup_priority() const { return setup_priority::HARDWARE - 2.0f; }
|
||||
Trigger<> *TemplateSwitch::get_turn_on_trigger() { return &this->turn_on_trigger_; }
|
||||
Trigger<> *TemplateSwitch::get_turn_off_trigger() { return &this->turn_off_trigger_; }
|
||||
Trigger<> *TemplateSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; }
|
||||
Trigger<> *TemplateSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; }
|
||||
void TemplateSwitch::setup() {
|
||||
if (!this->f_.has_value())
|
||||
this->disable_loop();
|
||||
|
||||
@@ -15,8 +15,8 @@ class TemplateSwitch final : public switch_::Switch, public Component {
|
||||
void dump_config() override;
|
||||
|
||||
template<typename F> void set_state_lambda(F &&f) { this->f_.set(std::forward<F>(f)); }
|
||||
Trigger<> *get_turn_on_trigger();
|
||||
Trigger<> *get_turn_off_trigger();
|
||||
Trigger<> *get_turn_on_trigger() const;
|
||||
Trigger<> *get_turn_off_trigger() const;
|
||||
void set_optimistic(bool optimistic);
|
||||
void set_assumed_state(bool assumed_state);
|
||||
void loop() override;
|
||||
@@ -31,9 +31,9 @@ class TemplateSwitch final : public switch_::Switch, public Component {
|
||||
TemplateLambda<bool> f_;
|
||||
bool optimistic_{false};
|
||||
bool assumed_state_{false};
|
||||
Trigger<> turn_on_trigger_;
|
||||
Trigger<> turn_off_trigger_;
|
||||
Trigger<> *prev_trigger_{nullptr}; // Points to one of the above
|
||||
Trigger<> *turn_on_trigger_;
|
||||
Trigger<> *turn_off_trigger_;
|
||||
Trigger<> *prev_trigger_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace esphome::template_
|
||||
|
||||
@@ -47,7 +47,7 @@ void TemplateText::update() {
|
||||
}
|
||||
|
||||
void TemplateText::control(const std::string &value) {
|
||||
this->set_trigger_.trigger(value);
|
||||
this->set_trigger_->trigger(value);
|
||||
|
||||
if (this->optimistic_)
|
||||
this->publish_state(value);
|
||||
|
||||
@@ -68,7 +68,7 @@ class TemplateText final : public text::Text, public PollingComponent {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<std::string> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<std::string> *get_set_trigger() const { return this->set_trigger_; }
|
||||
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||
void set_initial_value(const char *initial_value) { this->initial_value_ = initial_value; }
|
||||
/// Prevent accidental use of std::string which would dangle
|
||||
@@ -79,7 +79,7 @@ class TemplateText final : public text::Text, public PollingComponent {
|
||||
void control(const std::string &value) override;
|
||||
bool optimistic_ = false;
|
||||
const char *initial_value_{nullptr};
|
||||
Trigger<std::string> set_trigger_;
|
||||
Trigger<std::string> *set_trigger_ = new Trigger<std::string>();
|
||||
TemplateLambda<std::string> f_{};
|
||||
|
||||
TemplateTextSaverBase *pref_ = nullptr;
|
||||
|
||||
@@ -7,7 +7,12 @@ using namespace esphome::valve;
|
||||
|
||||
static const char *const TAG = "template.valve";
|
||||
|
||||
TemplateValve::TemplateValve() = default;
|
||||
TemplateValve::TemplateValve()
|
||||
: open_trigger_(new Trigger<>()),
|
||||
close_trigger_(new Trigger<>),
|
||||
stop_trigger_(new Trigger<>()),
|
||||
toggle_trigger_(new Trigger<>()),
|
||||
position_trigger_(new Trigger<float>()) {}
|
||||
|
||||
void TemplateValve::setup() {
|
||||
switch (this->restore_mode_) {
|
||||
@@ -51,10 +56,10 @@ void TemplateValve::set_optimistic(bool optimistic) { this->optimistic_ = optimi
|
||||
void TemplateValve::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; }
|
||||
float TemplateValve::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
Trigger<> *TemplateValve::get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *TemplateValve::get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *TemplateValve::get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *TemplateValve::get_toggle_trigger() { return &this->toggle_trigger_; }
|
||||
Trigger<> *TemplateValve::get_open_trigger() const { return this->open_trigger_; }
|
||||
Trigger<> *TemplateValve::get_close_trigger() const { return this->close_trigger_; }
|
||||
Trigger<> *TemplateValve::get_stop_trigger() const { return this->stop_trigger_; }
|
||||
Trigger<> *TemplateValve::get_toggle_trigger() const { return this->toggle_trigger_; }
|
||||
|
||||
void TemplateValve::dump_config() {
|
||||
LOG_VALVE("", "Template Valve", this);
|
||||
@@ -67,14 +72,14 @@ void TemplateValve::dump_config() {
|
||||
void TemplateValve::control(const ValveCall &call) {
|
||||
if (call.get_stop()) {
|
||||
this->stop_prev_trigger_();
|
||||
this->stop_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->stop_trigger_;
|
||||
this->stop_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->stop_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_toggle().has_value()) {
|
||||
this->stop_prev_trigger_();
|
||||
this->toggle_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->toggle_trigger_;
|
||||
this->toggle_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->toggle_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
@@ -82,13 +87,13 @@ void TemplateValve::control(const ValveCall &call) {
|
||||
this->stop_prev_trigger_();
|
||||
|
||||
if (pos == VALVE_OPEN) {
|
||||
this->open_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->open_trigger_;
|
||||
this->open_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->open_trigger_;
|
||||
} else if (pos == VALVE_CLOSED) {
|
||||
this->close_trigger_.trigger();
|
||||
this->prev_command_trigger_ = &this->close_trigger_;
|
||||
this->close_trigger_->trigger();
|
||||
this->prev_command_trigger_ = this->close_trigger_;
|
||||
} else {
|
||||
this->position_trigger_.trigger(pos);
|
||||
this->position_trigger_->trigger(pos);
|
||||
}
|
||||
|
||||
if (this->optimistic_) {
|
||||
@@ -108,7 +113,7 @@ ValveTraits TemplateValve::get_traits() {
|
||||
return traits;
|
||||
}
|
||||
|
||||
Trigger<float> *TemplateValve::get_position_trigger() { return &this->position_trigger_; }
|
||||
Trigger<float> *TemplateValve::get_position_trigger() const { return this->position_trigger_; }
|
||||
|
||||
void TemplateValve::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; }
|
||||
void TemplateValve::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; }
|
||||
|
||||
@@ -18,11 +18,11 @@ class TemplateValve final : public valve::Valve, public Component {
|
||||
TemplateValve();
|
||||
|
||||
template<typename F> void set_state_lambda(F &&f) { this->state_f_.set(std::forward<F>(f)); }
|
||||
Trigger<> *get_open_trigger();
|
||||
Trigger<> *get_close_trigger();
|
||||
Trigger<> *get_stop_trigger();
|
||||
Trigger<> *get_toggle_trigger();
|
||||
Trigger<float> *get_position_trigger();
|
||||
Trigger<> *get_open_trigger() const;
|
||||
Trigger<> *get_close_trigger() const;
|
||||
Trigger<> *get_stop_trigger() const;
|
||||
Trigger<> *get_toggle_trigger() const;
|
||||
Trigger<float> *get_position_trigger() const;
|
||||
void set_optimistic(bool optimistic);
|
||||
void set_assumed_state(bool assumed_state);
|
||||
void set_has_stop(bool has_stop);
|
||||
@@ -45,14 +45,14 @@ class TemplateValve final : public valve::Valve, public Component {
|
||||
TemplateLambda<float> state_f_;
|
||||
bool assumed_state_{false};
|
||||
bool optimistic_{false};
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> *open_trigger_;
|
||||
Trigger<> *close_trigger_;
|
||||
bool has_stop_{false};
|
||||
bool has_toggle_{false};
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> toggle_trigger_;
|
||||
Trigger<> *stop_trigger_;
|
||||
Trigger<> *toggle_trigger_;
|
||||
Trigger<> *prev_command_trigger_{nullptr};
|
||||
Trigger<float> position_trigger_;
|
||||
Trigger<float> *position_trigger_;
|
||||
bool has_position_{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace esphome::template_ {
|
||||
|
||||
static const char *const TAG = "template.water_heater";
|
||||
|
||||
TemplateWaterHeater::TemplateWaterHeater() = default;
|
||||
TemplateWaterHeater::TemplateWaterHeater() : set_trigger_(new Trigger<>()) {}
|
||||
|
||||
void TemplateWaterHeater::setup() {
|
||||
if (this->restore_mode_ == TemplateWaterHeaterRestoreMode::WATER_HEATER_RESTORE ||
|
||||
@@ -78,7 +78,7 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
this->set_trigger_.trigger();
|
||||
this->set_trigger_->trigger();
|
||||
|
||||
if (this->optimistic_) {
|
||||
this->publish_state();
|
||||
|
||||
@@ -28,7 +28,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater {
|
||||
this->supported_modes_ = modes;
|
||||
}
|
||||
|
||||
Trigger<> *get_set_trigger() { return &this->set_trigger_; }
|
||||
Trigger<> *get_set_trigger() const { return this->set_trigger_; }
|
||||
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
@@ -42,7 +42,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater {
|
||||
water_heater::WaterHeaterTraits traits() override;
|
||||
|
||||
// Ordered to minimize padding on 32-bit: 4-byte members first, then smaller
|
||||
Trigger<> set_trigger_;
|
||||
Trigger<> *set_trigger_;
|
||||
TemplateLambda<float> current_temperature_f_;
|
||||
TemplateLambda<water_heater::WaterHeaterMode> mode_f_;
|
||||
TemplateWaterHeaterRestoreMode restore_mode_{WATER_HEATER_NO_RESTORE};
|
||||
|
||||
@@ -499,7 +499,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
}
|
||||
|
||||
bool action_ready = false;
|
||||
Trigger<> *trig = &this->idle_action_trigger_, *trig_fan = nullptr;
|
||||
Trigger<> *trig = this->idle_action_trigger_, *trig_fan = nullptr;
|
||||
switch (action) {
|
||||
case climate::CLIMATE_ACTION_OFF:
|
||||
case climate::CLIMATE_ACTION_IDLE:
|
||||
@@ -529,10 +529,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME);
|
||||
if (this->supports_fan_with_cooling_) {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON);
|
||||
trig_fan = &this->fan_only_action_trigger_;
|
||||
trig_fan = this->fan_only_action_trigger_;
|
||||
}
|
||||
this->cooling_max_runtime_exceeded_ = false;
|
||||
trig = &this->cool_action_trigger_;
|
||||
trig = this->cool_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to COOLING action");
|
||||
action_ready = true;
|
||||
}
|
||||
@@ -543,10 +543,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME);
|
||||
if (this->supports_fan_with_heating_) {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON);
|
||||
trig_fan = &this->fan_only_action_trigger_;
|
||||
trig_fan = this->fan_only_action_trigger_;
|
||||
}
|
||||
this->heating_max_runtime_exceeded_ = false;
|
||||
trig = &this->heat_action_trigger_;
|
||||
trig = this->heat_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to HEATING action");
|
||||
action_ready = true;
|
||||
}
|
||||
@@ -558,7 +558,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
} else {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON);
|
||||
}
|
||||
trig = &this->fan_only_action_trigger_;
|
||||
trig = this->fan_only_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_ONLY action");
|
||||
action_ready = true;
|
||||
}
|
||||
@@ -567,7 +567,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
if (this->drying_action_ready_()) {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_ON);
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON);
|
||||
trig = &this->dry_action_trigger_;
|
||||
trig = this->dry_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to DRYING action");
|
||||
action_ready = true;
|
||||
}
|
||||
@@ -586,7 +586,9 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
|
||||
}
|
||||
this->action = action;
|
||||
this->prev_action_trigger_ = trig;
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
// if enabled, call the fan_only action with cooling/heating actions
|
||||
if (trig_fan != nullptr) {
|
||||
ESP_LOGVV(TAG, "Calling FAN_ONLY action with HEATING/COOLING action");
|
||||
@@ -632,14 +634,14 @@ void ThermostatClimate::trigger_supplemental_action_() {
|
||||
if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME)) {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME);
|
||||
}
|
||||
trig = &this->supplemental_cool_action_trigger_;
|
||||
trig = this->supplemental_cool_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Calling supplemental COOLING action");
|
||||
break;
|
||||
case climate::CLIMATE_ACTION_HEATING:
|
||||
if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME)) {
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME);
|
||||
}
|
||||
trig = &this->supplemental_heat_action_trigger_;
|
||||
trig = this->supplemental_heat_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Calling supplemental HEATING action");
|
||||
break;
|
||||
default:
|
||||
@@ -658,24 +660,24 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction
|
||||
return;
|
||||
}
|
||||
|
||||
Trigger<> *trig = &this->humidity_control_off_action_trigger_;
|
||||
Trigger<> *trig = this->humidity_control_off_action_trigger_;
|
||||
switch (action) {
|
||||
case THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF:
|
||||
// trig = &this->humidity_control_off_action_trigger_;
|
||||
// trig = this->humidity_control_off_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to HUMIDIFICATION_OFF action");
|
||||
break;
|
||||
case THERMOSTAT_HUMIDITY_CONTROL_ACTION_DEHUMIDIFY:
|
||||
trig = &this->humidity_control_dehumidify_action_trigger_;
|
||||
trig = this->humidity_control_dehumidify_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to DEHUMIDIFY action");
|
||||
break;
|
||||
case THERMOSTAT_HUMIDITY_CONTROL_ACTION_HUMIDIFY:
|
||||
trig = &this->humidity_control_humidify_action_trigger_;
|
||||
trig = this->humidity_control_humidify_action_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to HUMIDIFY action");
|
||||
break;
|
||||
case THERMOSTAT_HUMIDITY_CONTROL_ACTION_NONE:
|
||||
default:
|
||||
action = THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF;
|
||||
// trig = &this->humidity_control_off_action_trigger_;
|
||||
// trig = this->humidity_control_off_action_trigger_;
|
||||
}
|
||||
|
||||
if (this->prev_humidity_control_trigger_ != nullptr) {
|
||||
@@ -684,7 +686,9 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction
|
||||
}
|
||||
this->humidification_action = action;
|
||||
this->prev_humidity_control_trigger_ = trig;
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bool publish_state) {
|
||||
@@ -699,60 +703,62 @@ void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bo
|
||||
this->publish_state();
|
||||
|
||||
if (this->fan_mode_ready_()) {
|
||||
Trigger<> *trig = &this->fan_mode_auto_trigger_;
|
||||
Trigger<> *trig = this->fan_mode_auto_trigger_;
|
||||
switch (fan_mode) {
|
||||
case climate::CLIMATE_FAN_ON:
|
||||
trig = &this->fan_mode_on_trigger_;
|
||||
trig = this->fan_mode_on_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_ON mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_OFF:
|
||||
trig = &this->fan_mode_off_trigger_;
|
||||
trig = this->fan_mode_off_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_OFF mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_AUTO:
|
||||
// trig = &this->fan_mode_auto_trigger_;
|
||||
// trig = this->fan_mode_auto_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_AUTO mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
trig = &this->fan_mode_low_trigger_;
|
||||
trig = this->fan_mode_low_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_LOW mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_MEDIUM:
|
||||
trig = &this->fan_mode_medium_trigger_;
|
||||
trig = this->fan_mode_medium_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_MEDIUM mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
trig = &this->fan_mode_high_trigger_;
|
||||
trig = this->fan_mode_high_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_HIGH mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_MIDDLE:
|
||||
trig = &this->fan_mode_middle_trigger_;
|
||||
trig = this->fan_mode_middle_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_MIDDLE mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_FOCUS:
|
||||
trig = &this->fan_mode_focus_trigger_;
|
||||
trig = this->fan_mode_focus_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_FOCUS mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_DIFFUSE:
|
||||
trig = &this->fan_mode_diffuse_trigger_;
|
||||
trig = this->fan_mode_diffuse_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_DIFFUSE mode");
|
||||
break;
|
||||
case climate::CLIMATE_FAN_QUIET:
|
||||
trig = &this->fan_mode_quiet_trigger_;
|
||||
trig = this->fan_mode_quiet_trigger_;
|
||||
ESP_LOGVV(TAG, "Switching to FAN_QUIET mode");
|
||||
break;
|
||||
default:
|
||||
// we cannot report an invalid mode back to HA (even if it asked for one)
|
||||
// and must assume some valid value
|
||||
fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
// trig = &this->fan_mode_auto_trigger_;
|
||||
// trig = this->fan_mode_auto_trigger_;
|
||||
}
|
||||
if (this->prev_fan_mode_trigger_ != nullptr) {
|
||||
this->prev_fan_mode_trigger_->stop_action();
|
||||
this->prev_fan_mode_trigger_ = nullptr;
|
||||
}
|
||||
this->start_timer_(thermostat::THERMOSTAT_TIMER_FAN_MODE);
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
this->prev_fan_mode_ = fan_mode;
|
||||
this->prev_fan_mode_trigger_ = trig;
|
||||
}
|
||||
@@ -769,25 +775,25 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_
|
||||
this->prev_mode_trigger_->stop_action();
|
||||
this->prev_mode_trigger_ = nullptr;
|
||||
}
|
||||
Trigger<> *trig = &this->off_mode_trigger_;
|
||||
Trigger<> *trig = this->off_mode_trigger_;
|
||||
switch (mode) {
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
trig = &this->auto_mode_trigger_;
|
||||
trig = this->auto_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_HEAT_COOL:
|
||||
trig = &this->heat_cool_mode_trigger_;
|
||||
trig = this->heat_cool_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
trig = &this->cool_mode_trigger_;
|
||||
trig = this->cool_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
trig = &this->heat_mode_trigger_;
|
||||
trig = this->heat_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_FAN_ONLY:
|
||||
trig = &this->fan_only_mode_trigger_;
|
||||
trig = this->fan_only_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_DRY:
|
||||
trig = &this->dry_mode_trigger_;
|
||||
trig = this->dry_mode_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
default:
|
||||
@@ -796,7 +802,9 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_
|
||||
mode = climate::CLIMATE_MODE_OFF;
|
||||
// trig = this->off_mode_trigger_;
|
||||
}
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
this->mode = mode;
|
||||
this->prev_mode_ = mode;
|
||||
this->prev_mode_trigger_ = trig;
|
||||
@@ -816,27 +824,29 @@ void ThermostatClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mo
|
||||
this->prev_swing_mode_trigger_->stop_action();
|
||||
this->prev_swing_mode_trigger_ = nullptr;
|
||||
}
|
||||
Trigger<> *trig = &this->swing_mode_off_trigger_;
|
||||
Trigger<> *trig = this->swing_mode_off_trigger_;
|
||||
switch (swing_mode) {
|
||||
case climate::CLIMATE_SWING_BOTH:
|
||||
trig = &this->swing_mode_both_trigger_;
|
||||
trig = this->swing_mode_both_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_SWING_HORIZONTAL:
|
||||
trig = &this->swing_mode_horizontal_trigger_;
|
||||
trig = this->swing_mode_horizontal_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_SWING_OFF:
|
||||
// trig = &this->swing_mode_off_trigger_;
|
||||
// trig = this->swing_mode_off_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_SWING_VERTICAL:
|
||||
trig = &this->swing_mode_vertical_trigger_;
|
||||
trig = this->swing_mode_vertical_trigger_;
|
||||
break;
|
||||
default:
|
||||
// we cannot report an invalid mode back to HA (even if it asked for one)
|
||||
// and must assume some valid value
|
||||
swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
// trig = &this->swing_mode_off_trigger_;
|
||||
// trig = this->swing_mode_off_trigger_;
|
||||
}
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
trig->trigger();
|
||||
this->swing_mode = swing_mode;
|
||||
this->prev_swing_mode_ = swing_mode;
|
||||
this->prev_swing_mode_trigger_ = trig;
|
||||
@@ -1014,8 +1024,10 @@ void ThermostatClimate::check_humidity_change_trigger_() {
|
||||
this->prev_target_humidity_ = this->target_humidity;
|
||||
}
|
||||
// trigger the action
|
||||
Trigger<> *trig = &this->humidity_change_trigger_;
|
||||
trig->trigger();
|
||||
Trigger<> *trig = this->humidity_change_trigger_;
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
void ThermostatClimate::check_temperature_change_trigger_() {
|
||||
@@ -1038,8 +1050,10 @@ void ThermostatClimate::check_temperature_change_trigger_() {
|
||||
}
|
||||
}
|
||||
// trigger the action
|
||||
Trigger<> *trig = &this->temperature_change_trigger_;
|
||||
trig->trigger();
|
||||
Trigger<> *trig = this->temperature_change_trigger_;
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
bool ThermostatClimate::cooling_required_() {
|
||||
@@ -1188,10 +1202,12 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
|
||||
if (config != nullptr) {
|
||||
ESP_LOGV(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
|
||||
if (this->change_preset_internal_(*config) || (!this->preset.has_value()) || this->preset.value() != preset) {
|
||||
// Fire preset changed trigger
|
||||
Trigger<> *trig = &this->preset_change_trigger_;
|
||||
// Fire any preset changed trigger if defined
|
||||
Trigger<> *trig = this->preset_change_trigger_;
|
||||
this->set_preset_(preset);
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
|
||||
this->refresh();
|
||||
ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
|
||||
@@ -1218,11 +1234,13 @@ void ThermostatClimate::change_custom_preset_(const char *custom_preset, size_t
|
||||
ESP_LOGV(TAG, "Custom preset %s requested", custom_preset);
|
||||
if (this->change_preset_internal_(*config) || !this->has_custom_preset() ||
|
||||
this->get_custom_preset() != custom_preset) {
|
||||
// Fire preset changed trigger
|
||||
Trigger<> *trig = &this->preset_change_trigger_;
|
||||
// Fire any preset changed trigger if defined
|
||||
Trigger<> *trig = this->preset_change_trigger_;
|
||||
// Use the base class method which handles pointer lookup and preset reset internally
|
||||
this->set_custom_preset_(custom_preset);
|
||||
trig->trigger();
|
||||
if (trig != nullptr) {
|
||||
trig->trigger();
|
||||
}
|
||||
|
||||
this->refresh();
|
||||
ESP_LOGI(TAG, "Custom preset %s applied", custom_preset);
|
||||
@@ -1287,7 +1305,41 @@ void ThermostatClimate::set_custom_preset_config(std::initializer_list<CustomPre
|
||||
this->custom_preset_config_ = presets;
|
||||
}
|
||||
|
||||
ThermostatClimate::ThermostatClimate() = default;
|
||||
ThermostatClimate::ThermostatClimate()
|
||||
: cool_action_trigger_(new Trigger<>()),
|
||||
supplemental_cool_action_trigger_(new Trigger<>()),
|
||||
cool_mode_trigger_(new Trigger<>()),
|
||||
dry_action_trigger_(new Trigger<>()),
|
||||
dry_mode_trigger_(new Trigger<>()),
|
||||
heat_action_trigger_(new Trigger<>()),
|
||||
supplemental_heat_action_trigger_(new Trigger<>()),
|
||||
heat_mode_trigger_(new Trigger<>()),
|
||||
heat_cool_mode_trigger_(new Trigger<>()),
|
||||
auto_mode_trigger_(new Trigger<>()),
|
||||
idle_action_trigger_(new Trigger<>()),
|
||||
off_mode_trigger_(new Trigger<>()),
|
||||
fan_only_action_trigger_(new Trigger<>()),
|
||||
fan_only_mode_trigger_(new Trigger<>()),
|
||||
fan_mode_on_trigger_(new Trigger<>()),
|
||||
fan_mode_off_trigger_(new Trigger<>()),
|
||||
fan_mode_auto_trigger_(new Trigger<>()),
|
||||
fan_mode_low_trigger_(new Trigger<>()),
|
||||
fan_mode_medium_trigger_(new Trigger<>()),
|
||||
fan_mode_high_trigger_(new Trigger<>()),
|
||||
fan_mode_middle_trigger_(new Trigger<>()),
|
||||
fan_mode_focus_trigger_(new Trigger<>()),
|
||||
fan_mode_diffuse_trigger_(new Trigger<>()),
|
||||
fan_mode_quiet_trigger_(new Trigger<>()),
|
||||
swing_mode_both_trigger_(new Trigger<>()),
|
||||
swing_mode_off_trigger_(new Trigger<>()),
|
||||
swing_mode_horizontal_trigger_(new Trigger<>()),
|
||||
swing_mode_vertical_trigger_(new Trigger<>()),
|
||||
humidity_change_trigger_(new Trigger<>()),
|
||||
temperature_change_trigger_(new Trigger<>()),
|
||||
preset_change_trigger_(new Trigger<>()),
|
||||
humidity_control_dehumidify_action_trigger_(new Trigger<>()),
|
||||
humidity_control_humidify_action_trigger_(new Trigger<>()),
|
||||
humidity_control_off_action_trigger_(new Trigger<>()) {}
|
||||
|
||||
void ThermostatClimate::set_default_preset(const char *custom_preset) {
|
||||
// Find the preset in custom_preset_config_ and store pointer from there
|
||||
@@ -1461,49 +1513,49 @@ void ThermostatClimate::set_supports_humidification(bool supports_humidification
|
||||
}
|
||||
}
|
||||
|
||||
Trigger<> *ThermostatClimate::get_cool_action_trigger() { return &this->cool_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() {
|
||||
return &this->supplemental_cool_action_trigger_;
|
||||
Trigger<> *ThermostatClimate::get_cool_action_trigger() const { return this->cool_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() const {
|
||||
return this->supplemental_cool_action_trigger_;
|
||||
}
|
||||
Trigger<> *ThermostatClimate::get_dry_action_trigger() { return &this->dry_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_only_action_trigger() { return &this->fan_only_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_action_trigger() { return &this->heat_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() {
|
||||
return &this->supplemental_heat_action_trigger_;
|
||||
Trigger<> *ThermostatClimate::get_dry_action_trigger() const { return this->dry_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_only_action_trigger() const { return this->fan_only_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_action_trigger() const { return this->heat_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() const {
|
||||
return this->supplemental_heat_action_trigger_;
|
||||
}
|
||||
Trigger<> *ThermostatClimate::get_idle_action_trigger() { return &this->idle_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_auto_mode_trigger() { return &this->auto_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_cool_mode_trigger() { return &this->cool_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_dry_mode_trigger() { return &this->dry_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() { return &this->fan_only_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_mode_trigger() { return &this->heat_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() { return &this->heat_cool_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_off_mode_trigger() { return &this->off_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() { return &this->fan_mode_on_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() { return &this->fan_mode_off_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() { return &this->fan_mode_auto_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() { return &this->fan_mode_low_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() { return &this->fan_mode_medium_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() { return &this->fan_mode_high_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() { return &this->fan_mode_middle_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() { return &this->fan_mode_focus_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() { return &this->fan_mode_diffuse_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() { return &this->fan_mode_quiet_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() { return &this->swing_mode_both_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() { return &this->swing_mode_off_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() { return &this->swing_mode_horizontal_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() { return &this->swing_mode_vertical_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_humidity_change_trigger() { return &this->humidity_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_temperature_change_trigger() { return &this->temperature_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_preset_change_trigger() { return &this->preset_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() {
|
||||
return &this->humidity_control_dehumidify_action_trigger_;
|
||||
Trigger<> *ThermostatClimate::get_idle_action_trigger() const { return this->idle_action_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_auto_mode_trigger() const { return this->auto_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_cool_mode_trigger() const { return this->cool_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_dry_mode_trigger() const { return this->dry_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() const { return this->fan_only_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_mode_trigger() const { return this->heat_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() const { return this->heat_cool_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_off_mode_trigger() const { return this->off_mode_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() const { return this->fan_mode_on_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() const { return this->fan_mode_off_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() const { return this->fan_mode_auto_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() const { return this->fan_mode_low_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() const { return this->fan_mode_medium_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() const { return this->fan_mode_high_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() const { return this->fan_mode_middle_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() const { return this->fan_mode_focus_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() const { return this->fan_mode_diffuse_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() const { return this->fan_mode_quiet_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() const { return this->swing_mode_both_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() const { return this->swing_mode_off_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() const { return this->swing_mode_horizontal_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() const { return this->swing_mode_vertical_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_humidity_change_trigger() const { return this->humidity_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_temperature_change_trigger() const { return this->temperature_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_preset_change_trigger() const { return this->preset_change_trigger_; }
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() const {
|
||||
return this->humidity_control_dehumidify_action_trigger_;
|
||||
}
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() {
|
||||
return &this->humidity_control_humidify_action_trigger_;
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() const {
|
||||
return this->humidity_control_humidify_action_trigger_;
|
||||
}
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() {
|
||||
return &this->humidity_control_off_action_trigger_;
|
||||
Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() const {
|
||||
return this->humidity_control_off_action_trigger_;
|
||||
}
|
||||
|
||||
void ThermostatClimate::dump_config() {
|
||||
|
||||
@@ -146,40 +146,40 @@ class ThermostatClimate : public climate::Climate, public Component {
|
||||
void set_preset_config(std::initializer_list<PresetEntry> presets);
|
||||
void set_custom_preset_config(std::initializer_list<CustomPresetEntry> presets);
|
||||
|
||||
Trigger<> *get_cool_action_trigger();
|
||||
Trigger<> *get_supplemental_cool_action_trigger();
|
||||
Trigger<> *get_dry_action_trigger();
|
||||
Trigger<> *get_fan_only_action_trigger();
|
||||
Trigger<> *get_heat_action_trigger();
|
||||
Trigger<> *get_supplemental_heat_action_trigger();
|
||||
Trigger<> *get_idle_action_trigger();
|
||||
Trigger<> *get_auto_mode_trigger();
|
||||
Trigger<> *get_cool_mode_trigger();
|
||||
Trigger<> *get_dry_mode_trigger();
|
||||
Trigger<> *get_fan_only_mode_trigger();
|
||||
Trigger<> *get_heat_mode_trigger();
|
||||
Trigger<> *get_heat_cool_mode_trigger();
|
||||
Trigger<> *get_off_mode_trigger();
|
||||
Trigger<> *get_fan_mode_on_trigger();
|
||||
Trigger<> *get_fan_mode_off_trigger();
|
||||
Trigger<> *get_fan_mode_auto_trigger();
|
||||
Trigger<> *get_fan_mode_low_trigger();
|
||||
Trigger<> *get_fan_mode_medium_trigger();
|
||||
Trigger<> *get_fan_mode_high_trigger();
|
||||
Trigger<> *get_fan_mode_middle_trigger();
|
||||
Trigger<> *get_fan_mode_focus_trigger();
|
||||
Trigger<> *get_fan_mode_diffuse_trigger();
|
||||
Trigger<> *get_fan_mode_quiet_trigger();
|
||||
Trigger<> *get_swing_mode_both_trigger();
|
||||
Trigger<> *get_swing_mode_horizontal_trigger();
|
||||
Trigger<> *get_swing_mode_off_trigger();
|
||||
Trigger<> *get_swing_mode_vertical_trigger();
|
||||
Trigger<> *get_humidity_change_trigger();
|
||||
Trigger<> *get_temperature_change_trigger();
|
||||
Trigger<> *get_preset_change_trigger();
|
||||
Trigger<> *get_humidity_control_dehumidify_action_trigger();
|
||||
Trigger<> *get_humidity_control_humidify_action_trigger();
|
||||
Trigger<> *get_humidity_control_off_action_trigger();
|
||||
Trigger<> *get_cool_action_trigger() const;
|
||||
Trigger<> *get_supplemental_cool_action_trigger() const;
|
||||
Trigger<> *get_dry_action_trigger() const;
|
||||
Trigger<> *get_fan_only_action_trigger() const;
|
||||
Trigger<> *get_heat_action_trigger() const;
|
||||
Trigger<> *get_supplemental_heat_action_trigger() const;
|
||||
Trigger<> *get_idle_action_trigger() const;
|
||||
Trigger<> *get_auto_mode_trigger() const;
|
||||
Trigger<> *get_cool_mode_trigger() const;
|
||||
Trigger<> *get_dry_mode_trigger() const;
|
||||
Trigger<> *get_fan_only_mode_trigger() const;
|
||||
Trigger<> *get_heat_mode_trigger() const;
|
||||
Trigger<> *get_heat_cool_mode_trigger() const;
|
||||
Trigger<> *get_off_mode_trigger() const;
|
||||
Trigger<> *get_fan_mode_on_trigger() const;
|
||||
Trigger<> *get_fan_mode_off_trigger() const;
|
||||
Trigger<> *get_fan_mode_auto_trigger() const;
|
||||
Trigger<> *get_fan_mode_low_trigger() const;
|
||||
Trigger<> *get_fan_mode_medium_trigger() const;
|
||||
Trigger<> *get_fan_mode_high_trigger() const;
|
||||
Trigger<> *get_fan_mode_middle_trigger() const;
|
||||
Trigger<> *get_fan_mode_focus_trigger() const;
|
||||
Trigger<> *get_fan_mode_diffuse_trigger() const;
|
||||
Trigger<> *get_fan_mode_quiet_trigger() const;
|
||||
Trigger<> *get_swing_mode_both_trigger() const;
|
||||
Trigger<> *get_swing_mode_horizontal_trigger() const;
|
||||
Trigger<> *get_swing_mode_off_trigger() const;
|
||||
Trigger<> *get_swing_mode_vertical_trigger() const;
|
||||
Trigger<> *get_humidity_change_trigger() const;
|
||||
Trigger<> *get_temperature_change_trigger() const;
|
||||
Trigger<> *get_preset_change_trigger() const;
|
||||
Trigger<> *get_humidity_control_dehumidify_action_trigger() const;
|
||||
Trigger<> *get_humidity_control_humidify_action_trigger() const;
|
||||
Trigger<> *get_humidity_control_off_action_trigger() const;
|
||||
/// Get current hysteresis values
|
||||
float cool_deadband();
|
||||
float cool_overrun();
|
||||
@@ -417,65 +417,115 @@ class ThermostatClimate : public climate::Climate, public Component {
|
||||
/// The sensor used for getting the current humidity
|
||||
sensor::Sensor *humidity_sensor_{nullptr};
|
||||
|
||||
/// Trigger for cooling action/mode
|
||||
Trigger<> cool_action_trigger_;
|
||||
Trigger<> supplemental_cool_action_trigger_;
|
||||
Trigger<> cool_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to cooling action/mode.
|
||||
///
|
||||
/// A null value for this attribute means that the controller has no cooling action
|
||||
/// For example electric heat, where only heating (power on) and not-heating
|
||||
/// (power off) is possible.
|
||||
Trigger<> *cool_action_trigger_{nullptr};
|
||||
Trigger<> *supplemental_cool_action_trigger_{nullptr};
|
||||
Trigger<> *cool_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for dry (dehumidification) mode
|
||||
Trigger<> dry_action_trigger_;
|
||||
Trigger<> dry_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to dry (dehumidification) mode.
|
||||
///
|
||||
/// In dry mode, the controller is assumed to have both heating and cooling disabled,
|
||||
/// although the system may use its cooling mechanism to achieve drying.
|
||||
Trigger<> *dry_action_trigger_{nullptr};
|
||||
Trigger<> *dry_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for heating action/mode
|
||||
Trigger<> heat_action_trigger_;
|
||||
Trigger<> supplemental_heat_action_trigger_;
|
||||
Trigger<> heat_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to heating action/mode.
|
||||
///
|
||||
/// A null value for this attribute means that the controller has no heating action
|
||||
/// For example window blinds, where only cooling (blinds closed) and not-cooling
|
||||
/// (blinds open) is possible.
|
||||
Trigger<> *heat_action_trigger_{nullptr};
|
||||
Trigger<> *supplemental_heat_action_trigger_{nullptr};
|
||||
Trigger<> *heat_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for heat/cool mode
|
||||
Trigger<> heat_cool_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to heat/cool mode.
|
||||
///
|
||||
/// In heat/cool mode, the controller will enable heating/cooling as necessary and switch
|
||||
/// to idle when the temperature is within the thresholds/set points.
|
||||
Trigger<> *heat_cool_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for auto mode
|
||||
Trigger<> auto_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to auto mode.
|
||||
///
|
||||
/// In auto mode, the controller will enable heating/cooling as supported/necessary and switch
|
||||
/// to idle when the temperature is within the thresholds/set points.
|
||||
Trigger<> *auto_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for idle action/off mode
|
||||
Trigger<> idle_action_trigger_;
|
||||
Trigger<> off_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to idle action/off mode.
|
||||
///
|
||||
/// In these actions/modes, the controller is assumed to have both heating and cooling disabled.
|
||||
Trigger<> *idle_action_trigger_{nullptr};
|
||||
Trigger<> *off_mode_trigger_{nullptr};
|
||||
|
||||
/// Trigger for fan-only action/mode
|
||||
Trigger<> fan_only_action_trigger_;
|
||||
Trigger<> fan_only_mode_trigger_;
|
||||
/// The trigger to call when the controller should switch to fan-only action/mode.
|
||||
///
|
||||
/// In fan-only mode, the controller is assumed to have both heating and cooling disabled.
|
||||
/// The system should activate the fan only.
|
||||
Trigger<> *fan_only_action_trigger_{nullptr};
|
||||
Trigger<> *fan_only_mode_trigger_{nullptr};
|
||||
|
||||
/// Fan mode triggers
|
||||
Trigger<> fan_mode_on_trigger_;
|
||||
Trigger<> fan_mode_off_trigger_;
|
||||
Trigger<> fan_mode_auto_trigger_;
|
||||
Trigger<> fan_mode_low_trigger_;
|
||||
Trigger<> fan_mode_medium_trigger_;
|
||||
Trigger<> fan_mode_high_trigger_;
|
||||
Trigger<> fan_mode_middle_trigger_;
|
||||
Trigger<> fan_mode_focus_trigger_;
|
||||
Trigger<> fan_mode_diffuse_trigger_;
|
||||
Trigger<> fan_mode_quiet_trigger_;
|
||||
/// The trigger to call when the controller should switch on the fan.
|
||||
Trigger<> *fan_mode_on_trigger_{nullptr};
|
||||
|
||||
/// Swing mode triggers
|
||||
Trigger<> swing_mode_both_trigger_;
|
||||
Trigger<> swing_mode_off_trigger_;
|
||||
Trigger<> swing_mode_horizontal_trigger_;
|
||||
Trigger<> swing_mode_vertical_trigger_;
|
||||
/// The trigger to call when the controller should switch off the fan.
|
||||
Trigger<> *fan_mode_off_trigger_{nullptr};
|
||||
|
||||
/// Trigger for target humidity changes
|
||||
Trigger<> humidity_change_trigger_;
|
||||
/// The trigger to call when the controller should switch the fan to "auto" mode.
|
||||
Trigger<> *fan_mode_auto_trigger_{nullptr};
|
||||
|
||||
/// Trigger for target temperature changes
|
||||
Trigger<> temperature_change_trigger_;
|
||||
/// The trigger to call when the controller should switch the fan to "low" speed.
|
||||
Trigger<> *fan_mode_low_trigger_{nullptr};
|
||||
|
||||
/// Trigger for preset mode changes
|
||||
Trigger<> preset_change_trigger_;
|
||||
/// The trigger to call when the controller should switch the fan to "medium" speed.
|
||||
Trigger<> *fan_mode_medium_trigger_{nullptr};
|
||||
|
||||
/// Humidity control triggers
|
||||
Trigger<> humidity_control_dehumidify_action_trigger_;
|
||||
Trigger<> humidity_control_humidify_action_trigger_;
|
||||
Trigger<> humidity_control_off_action_trigger_;
|
||||
/// The trigger to call when the controller should switch the fan to "high" speed.
|
||||
Trigger<> *fan_mode_high_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the fan to "middle" position.
|
||||
Trigger<> *fan_mode_middle_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the fan to "focus" position.
|
||||
Trigger<> *fan_mode_focus_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the fan to "diffuse" position.
|
||||
Trigger<> *fan_mode_diffuse_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the fan to "quiet" position.
|
||||
Trigger<> *fan_mode_quiet_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the swing mode to "both".
|
||||
Trigger<> *swing_mode_both_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the swing mode to "off".
|
||||
Trigger<> *swing_mode_off_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the swing mode to "horizontal".
|
||||
Trigger<> *swing_mode_horizontal_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the controller should switch the swing mode to "vertical".
|
||||
Trigger<> *swing_mode_vertical_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the target humidity changes.
|
||||
Trigger<> *humidity_change_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the target temperature(s) change(es).
|
||||
Trigger<> *temperature_change_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when the preset mode changes
|
||||
Trigger<> *preset_change_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when dehumidification is required
|
||||
Trigger<> *humidity_control_dehumidify_action_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when humidification is required
|
||||
Trigger<> *humidity_control_humidify_action_trigger_{nullptr};
|
||||
|
||||
/// The trigger to call when (de)humidification should stop
|
||||
Trigger<> *humidity_control_off_action_trigger_{nullptr};
|
||||
|
||||
/// A reference to the trigger that was previously active.
|
||||
///
|
||||
|
||||
@@ -132,15 +132,15 @@ void TimeBasedCover::start_direction_(CoverOperation dir) {
|
||||
Trigger<> *trig;
|
||||
switch (dir) {
|
||||
case COVER_OPERATION_IDLE:
|
||||
trig = &this->stop_trigger_;
|
||||
trig = this->stop_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_OPENING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->open_trigger_;
|
||||
trig = this->open_trigger_;
|
||||
break;
|
||||
case COVER_OPERATION_CLOSING:
|
||||
this->last_operation_ = dir;
|
||||
trig = &this->close_trigger_;
|
||||
trig = this->close_trigger_;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
@@ -14,9 +14,9 @@ class TimeBasedCover : public cover::Cover, public Component {
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() { return &this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() { return &this->stop_trigger_; }
|
||||
Trigger<> *get_open_trigger() const { return this->open_trigger_; }
|
||||
Trigger<> *get_close_trigger() const { return this->close_trigger_; }
|
||||
Trigger<> *get_stop_trigger() const { return this->stop_trigger_; }
|
||||
void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; }
|
||||
void set_close_duration(uint32_t close_duration) { this->close_duration_ = close_duration; }
|
||||
cover::CoverTraits get_traits() override;
|
||||
@@ -34,11 +34,11 @@ class TimeBasedCover : public cover::Cover, public Component {
|
||||
|
||||
void recompute_position_();
|
||||
|
||||
Trigger<> open_trigger_;
|
||||
Trigger<> *open_trigger_{new Trigger<>()};
|
||||
uint32_t open_duration_;
|
||||
Trigger<> close_trigger_;
|
||||
Trigger<> *close_trigger_{new Trigger<>()};
|
||||
uint32_t close_duration_;
|
||||
Trigger<> stop_trigger_;
|
||||
Trigger<> *stop_trigger_{new Trigger<>()};
|
||||
|
||||
Trigger<> *prev_command_trigger_{nullptr};
|
||||
uint32_t last_recompute_time_{0};
|
||||
|
||||
@@ -197,7 +197,7 @@ void VoiceAssistant::loop() {
|
||||
switch (this->state_) {
|
||||
case State::IDLE: {
|
||||
if (this->continuous_ && this->desired_state_ == State::IDLE) {
|
||||
this->idle_trigger_.trigger();
|
||||
this->idle_trigger_->trigger();
|
||||
this->set_state_(State::START_MICROPHONE, State::START_PIPELINE);
|
||||
} else {
|
||||
this->deallocate_buffers_();
|
||||
@@ -254,7 +254,7 @@ void VoiceAssistant::loop() {
|
||||
if (this->api_client_ == nullptr ||
|
||||
!this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) {
|
||||
ESP_LOGW(TAG, "Could not request start");
|
||||
this->error_trigger_.trigger("not-connected", "Could not request start");
|
||||
this->error_trigger_->trigger("not-connected", "Could not request start");
|
||||
this->continuous_ = false;
|
||||
this->set_state_(State::IDLE, State::IDLE);
|
||||
break;
|
||||
@@ -384,7 +384,7 @@ void VoiceAssistant::loop() {
|
||||
this->wait_for_stream_end_ = false;
|
||||
this->stream_ended_ = false;
|
||||
|
||||
this->tts_stream_end_trigger_.trigger();
|
||||
this->tts_stream_end_trigger_->trigger();
|
||||
}
|
||||
#endif
|
||||
if (this->continue_conversation_) {
|
||||
@@ -425,7 +425,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
|
||||
return;
|
||||
}
|
||||
this->api_client_ = nullptr;
|
||||
this->client_disconnected_trigger_.trigger();
|
||||
this->client_disconnected_trigger_->trigger();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
|
||||
}
|
||||
|
||||
this->api_client_ = client;
|
||||
this->client_connected_trigger_.trigger();
|
||||
this->client_connected_trigger_->trigger();
|
||||
}
|
||||
|
||||
static const LogString *voice_assistant_state_to_string(State state) {
|
||||
@@ -491,7 +491,7 @@ void VoiceAssistant::set_state_(State state, State desired_state) {
|
||||
|
||||
void VoiceAssistant::failed_to_start() {
|
||||
ESP_LOGE(TAG, "Failed to start server. See Home Assistant logs for more details.");
|
||||
this->error_trigger_.trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
|
||||
this->error_trigger_->trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
|
||||
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
|
||||
}
|
||||
|
||||
@@ -637,18 +637,18 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->defer([this]() { this->start_trigger_.trigger(); });
|
||||
this->defer([this]() { this->start_trigger_->trigger(); });
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_WAKE_WORD_START:
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_WAKE_WORD_END: {
|
||||
ESP_LOGD(TAG, "Wake word detected");
|
||||
this->defer([this]() { this->wake_word_detected_trigger_.trigger(); });
|
||||
this->defer([this]() { this->wake_word_detected_trigger_->trigger(); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_STT_START:
|
||||
ESP_LOGD(TAG, "STT started");
|
||||
this->defer([this]() { this->listening_trigger_.trigger(); });
|
||||
this->defer([this]() { this->listening_trigger_->trigger(); });
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_STT_END: {
|
||||
std::string text;
|
||||
@@ -665,12 +665,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
text += "...";
|
||||
}
|
||||
ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str());
|
||||
this->defer([this, text]() { this->stt_end_trigger_.trigger(text); });
|
||||
this->defer([this, text]() { this->stt_end_trigger_->trigger(text); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_INTENT_START:
|
||||
ESP_LOGD(TAG, "Intent started");
|
||||
this->defer([this]() { this->intent_start_trigger_.trigger(); });
|
||||
this->defer([this]() { this->intent_start_trigger_->trigger(); });
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_INTENT_PROGRESS: {
|
||||
ESP_LOGD(TAG, "Intent progress");
|
||||
@@ -693,7 +693,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_.trigger(tts_url_for_trigger); });
|
||||
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_->trigger(tts_url_for_trigger); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_INTENT_END: {
|
||||
@@ -704,7 +704,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
this->continue_conversation_ = (arg.value == "1");
|
||||
}
|
||||
}
|
||||
this->defer([this]() { this->intent_end_trigger_.trigger(); });
|
||||
this->defer([this]() { this->intent_end_trigger_->trigger(); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_TTS_START: {
|
||||
@@ -724,7 +724,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
}
|
||||
ESP_LOGD(TAG, "Response: \"%s\"", text.c_str());
|
||||
this->defer([this, text]() {
|
||||
this->tts_start_trigger_.trigger(text);
|
||||
this->tts_start_trigger_->trigger(text);
|
||||
#ifdef USE_SPEAKER
|
||||
if (this->speaker_ != nullptr) {
|
||||
this->speaker_->start();
|
||||
@@ -756,7 +756,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
}
|
||||
this->started_streaming_tts_ = false; // Helps indicate reaching the TTS_END stage
|
||||
#endif
|
||||
this->tts_end_trigger_.trigger(url);
|
||||
this->tts_end_trigger_->trigger(url);
|
||||
});
|
||||
State new_state = this->local_output_ ? State::STREAMING_RESPONSE : State::IDLE;
|
||||
if (new_state != this->state_) {
|
||||
@@ -776,7 +776,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
// No TTS start event ("nevermind")
|
||||
this->set_state_(State::IDLE, State::IDLE);
|
||||
}
|
||||
this->defer([this]() { this->end_trigger_.trigger(); });
|
||||
this->defer([this]() { this->end_trigger_->trigger(); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_ERROR: {
|
||||
@@ -796,7 +796,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
// Wake word is not set up or not ready on Home Assistant so stop and do not retry until user starts again.
|
||||
this->defer([this, code, message]() {
|
||||
this->request_stop();
|
||||
this->error_trigger_.trigger(code, message);
|
||||
this->error_trigger_->trigger(code, message);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -805,7 +805,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
this->signal_stop_();
|
||||
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
|
||||
}
|
||||
this->defer([this, code, message]() { this->error_trigger_.trigger(code, message); });
|
||||
this->defer([this, code, message]() { this->error_trigger_->trigger(code, message); });
|
||||
break;
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: {
|
||||
@@ -813,7 +813,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
if (this->speaker_ != nullptr) {
|
||||
this->wait_for_stream_end_ = true;
|
||||
ESP_LOGD(TAG, "TTS stream start");
|
||||
this->defer([this] { this->tts_stream_start_trigger_.trigger(); });
|
||||
this->defer([this] { this->tts_stream_start_trigger_->trigger(); });
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -829,12 +829,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||
}
|
||||
case api::enums::VOICE_ASSISTANT_STT_VAD_START:
|
||||
ESP_LOGD(TAG, "Starting STT by VAD");
|
||||
this->defer([this]() { this->stt_vad_start_trigger_.trigger(); });
|
||||
this->defer([this]() { this->stt_vad_start_trigger_->trigger(); });
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_STT_VAD_END:
|
||||
ESP_LOGD(TAG, "STT by VAD end");
|
||||
this->set_state_(State::STOP_MICROPHONE, State::AWAITING_RESPONSE);
|
||||
this->defer([this]() { this->stt_vad_end_trigger_.trigger(); });
|
||||
this->defer([this]() { this->stt_vad_end_trigger_->trigger(); });
|
||||
break;
|
||||
default:
|
||||
ESP_LOGD(TAG, "Unhandled event type: %" PRId32, msg.event_type);
|
||||
@@ -876,17 +876,17 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse
|
||||
|
||||
switch (msg.event_type) {
|
||||
case api::enums::VOICE_ASSISTANT_TIMER_STARTED:
|
||||
this->timer_started_trigger_.trigger(timer);
|
||||
this->timer_started_trigger_->trigger(timer);
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_TIMER_UPDATED:
|
||||
this->timer_updated_trigger_.trigger(timer);
|
||||
this->timer_updated_trigger_->trigger(timer);
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED:
|
||||
this->timer_cancelled_trigger_.trigger(timer);
|
||||
this->timer_cancelled_trigger_->trigger(timer);
|
||||
this->timers_.erase(timer.id);
|
||||
break;
|
||||
case api::enums::VOICE_ASSISTANT_TIMER_FINISHED:
|
||||
this->timer_finished_trigger_.trigger(timer);
|
||||
this->timer_finished_trigger_->trigger(timer);
|
||||
this->timers_.erase(timer.id);
|
||||
break;
|
||||
}
|
||||
@@ -910,13 +910,13 @@ void VoiceAssistant::timer_tick_() {
|
||||
}
|
||||
res.push_back(timer);
|
||||
}
|
||||
this->timer_tick_trigger_.trigger(res);
|
||||
this->timer_tick_trigger_->trigger(res);
|
||||
}
|
||||
|
||||
void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) {
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
if (this->media_player_ != nullptr) {
|
||||
this->tts_start_trigger_.trigger(msg.text);
|
||||
this->tts_start_trigger_->trigger(msg.text);
|
||||
|
||||
this->media_player_response_state_ = MediaPlayerResponseState::URL_SENT;
|
||||
|
||||
@@ -939,8 +939,8 @@ void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg)
|
||||
this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE);
|
||||
}
|
||||
|
||||
this->tts_end_trigger_.trigger(msg.media_id);
|
||||
this->end_trigger_.trigger();
|
||||
this->tts_end_trigger_->trigger(msg.media_id);
|
||||
this->end_trigger_->trigger();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -195,38 +195,38 @@ class VoiceAssistant : public Component {
|
||||
void set_conversation_timeout(uint32_t conversation_timeout) { this->conversation_timeout_ = conversation_timeout; }
|
||||
void reset_conversation_id();
|
||||
|
||||
Trigger<> *get_intent_end_trigger() { return &this->intent_end_trigger_; }
|
||||
Trigger<> *get_intent_start_trigger() { return &this->intent_start_trigger_; }
|
||||
Trigger<std::string> *get_intent_progress_trigger() { return &this->intent_progress_trigger_; }
|
||||
Trigger<> *get_listening_trigger() { return &this->listening_trigger_; }
|
||||
Trigger<> *get_end_trigger() { return &this->end_trigger_; }
|
||||
Trigger<> *get_start_trigger() { return &this->start_trigger_; }
|
||||
Trigger<> *get_stt_vad_end_trigger() { return &this->stt_vad_end_trigger_; }
|
||||
Trigger<> *get_stt_vad_start_trigger() { return &this->stt_vad_start_trigger_; }
|
||||
Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; }
|
||||
Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; }
|
||||
Trigger<std::string> *get_intent_progress_trigger() const { return this->intent_progress_trigger_; }
|
||||
Trigger<> *get_listening_trigger() const { return this->listening_trigger_; }
|
||||
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
|
||||
Trigger<> *get_start_trigger() const { return this->start_trigger_; }
|
||||
Trigger<> *get_stt_vad_end_trigger() const { return this->stt_vad_end_trigger_; }
|
||||
Trigger<> *get_stt_vad_start_trigger() const { return this->stt_vad_start_trigger_; }
|
||||
#ifdef USE_SPEAKER
|
||||
Trigger<> *get_tts_stream_start_trigger() { return &this->tts_stream_start_trigger_; }
|
||||
Trigger<> *get_tts_stream_end_trigger() { return &this->tts_stream_end_trigger_; }
|
||||
Trigger<> *get_tts_stream_start_trigger() const { return this->tts_stream_start_trigger_; }
|
||||
Trigger<> *get_tts_stream_end_trigger() const { return this->tts_stream_end_trigger_; }
|
||||
#endif
|
||||
Trigger<> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; }
|
||||
Trigger<std::string> *get_stt_end_trigger() { return &this->stt_end_trigger_; }
|
||||
Trigger<std::string> *get_tts_end_trigger() { return &this->tts_end_trigger_; }
|
||||
Trigger<std::string> *get_tts_start_trigger() { return &this->tts_start_trigger_; }
|
||||
Trigger<std::string, std::string> *get_error_trigger() { return &this->error_trigger_; }
|
||||
Trigger<> *get_idle_trigger() { return &this->idle_trigger_; }
|
||||
Trigger<> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
|
||||
Trigger<std::string> *get_stt_end_trigger() const { return this->stt_end_trigger_; }
|
||||
Trigger<std::string> *get_tts_end_trigger() const { return this->tts_end_trigger_; }
|
||||
Trigger<std::string> *get_tts_start_trigger() const { return this->tts_start_trigger_; }
|
||||
Trigger<std::string, std::string> *get_error_trigger() const { return this->error_trigger_; }
|
||||
Trigger<> *get_idle_trigger() const { return this->idle_trigger_; }
|
||||
|
||||
Trigger<> *get_client_connected_trigger() { return &this->client_connected_trigger_; }
|
||||
Trigger<> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; }
|
||||
Trigger<> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
|
||||
Trigger<> *get_client_disconnected_trigger() const { return this->client_disconnected_trigger_; }
|
||||
|
||||
void client_subscription(api::APIConnection *client, bool subscribe);
|
||||
api::APIConnection *get_api_connection() const { return this->api_client_; }
|
||||
|
||||
void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; }
|
||||
|
||||
Trigger<Timer> *get_timer_started_trigger() { return &this->timer_started_trigger_; }
|
||||
Trigger<Timer> *get_timer_updated_trigger() { return &this->timer_updated_trigger_; }
|
||||
Trigger<Timer> *get_timer_cancelled_trigger() { return &this->timer_cancelled_trigger_; }
|
||||
Trigger<Timer> *get_timer_finished_trigger() { return &this->timer_finished_trigger_; }
|
||||
Trigger<std::vector<Timer>> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; }
|
||||
Trigger<Timer> *get_timer_started_trigger() const { return this->timer_started_trigger_; }
|
||||
Trigger<Timer> *get_timer_updated_trigger() const { return this->timer_updated_trigger_; }
|
||||
Trigger<Timer> *get_timer_cancelled_trigger() const { return this->timer_cancelled_trigger_; }
|
||||
Trigger<Timer> *get_timer_finished_trigger() const { return this->timer_finished_trigger_; }
|
||||
Trigger<std::vector<Timer>> *get_timer_tick_trigger() const { return this->timer_tick_trigger_; }
|
||||
void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; }
|
||||
const std::unordered_map<std::string, Timer> &get_timers() const { return this->timers_; }
|
||||
|
||||
@@ -243,37 +243,37 @@ class VoiceAssistant : public Component {
|
||||
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
||||
struct sockaddr_storage dest_addr_;
|
||||
|
||||
Trigger<> intent_end_trigger_;
|
||||
Trigger<> intent_start_trigger_;
|
||||
Trigger<> listening_trigger_;
|
||||
Trigger<> end_trigger_;
|
||||
Trigger<> start_trigger_;
|
||||
Trigger<> stt_vad_start_trigger_;
|
||||
Trigger<> stt_vad_end_trigger_;
|
||||
Trigger<> *intent_end_trigger_ = new Trigger<>();
|
||||
Trigger<> *intent_start_trigger_ = new Trigger<>();
|
||||
Trigger<> *listening_trigger_ = new Trigger<>();
|
||||
Trigger<> *end_trigger_ = new Trigger<>();
|
||||
Trigger<> *start_trigger_ = new Trigger<>();
|
||||
Trigger<> *stt_vad_start_trigger_ = new Trigger<>();
|
||||
Trigger<> *stt_vad_end_trigger_ = new Trigger<>();
|
||||
#ifdef USE_SPEAKER
|
||||
Trigger<> tts_stream_start_trigger_;
|
||||
Trigger<> tts_stream_end_trigger_;
|
||||
Trigger<> *tts_stream_start_trigger_ = new Trigger<>();
|
||||
Trigger<> *tts_stream_end_trigger_ = new Trigger<>();
|
||||
#endif
|
||||
Trigger<std::string> intent_progress_trigger_;
|
||||
Trigger<> wake_word_detected_trigger_;
|
||||
Trigger<std::string> stt_end_trigger_;
|
||||
Trigger<std::string> tts_end_trigger_;
|
||||
Trigger<std::string> tts_start_trigger_;
|
||||
Trigger<std::string, std::string> error_trigger_;
|
||||
Trigger<> idle_trigger_;
|
||||
Trigger<std::string> *intent_progress_trigger_ = new Trigger<std::string>();
|
||||
Trigger<> *wake_word_detected_trigger_ = new Trigger<>();
|
||||
Trigger<std::string> *stt_end_trigger_ = new Trigger<std::string>();
|
||||
Trigger<std::string> *tts_end_trigger_ = new Trigger<std::string>();
|
||||
Trigger<std::string> *tts_start_trigger_ = new Trigger<std::string>();
|
||||
Trigger<std::string, std::string> *error_trigger_ = new Trigger<std::string, std::string>();
|
||||
Trigger<> *idle_trigger_ = new Trigger<>();
|
||||
|
||||
Trigger<> client_connected_trigger_;
|
||||
Trigger<> client_disconnected_trigger_;
|
||||
Trigger<> *client_connected_trigger_ = new Trigger<>();
|
||||
Trigger<> *client_disconnected_trigger_ = new Trigger<>();
|
||||
|
||||
api::APIConnection *api_client_{nullptr};
|
||||
|
||||
std::unordered_map<std::string, Timer> timers_;
|
||||
void timer_tick_();
|
||||
Trigger<Timer> timer_started_trigger_;
|
||||
Trigger<Timer> timer_finished_trigger_;
|
||||
Trigger<Timer> timer_updated_trigger_;
|
||||
Trigger<Timer> timer_cancelled_trigger_;
|
||||
Trigger<std::vector<Timer>> timer_tick_trigger_;
|
||||
Trigger<Timer> *timer_started_trigger_ = new Trigger<Timer>();
|
||||
Trigger<Timer> *timer_finished_trigger_ = new Trigger<Timer>();
|
||||
Trigger<Timer> *timer_updated_trigger_ = new Trigger<Timer>();
|
||||
Trigger<Timer> *timer_cancelled_trigger_ = new Trigger<Timer>();
|
||||
Trigger<std::vector<Timer>> *timer_tick_trigger_ = new Trigger<std::vector<Timer>>();
|
||||
bool has_timers_{false};
|
||||
bool timer_tick_running_{false};
|
||||
|
||||
|
||||
@@ -38,8 +38,11 @@ async def to_code(config):
|
||||
cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1)
|
||||
return
|
||||
|
||||
# ESP32 uses IDF web server (early return above), so this is for other Arduino platforms
|
||||
if CORE.using_arduino:
|
||||
if CORE.is_esp32:
|
||||
cg.add_library("WiFi", None)
|
||||
cg.add_library("FS", None)
|
||||
cg.add_library("Update", None)
|
||||
if CORE.is_esp8266:
|
||||
cg.add_library("ESP8266WiFi", None)
|
||||
if CORE.is_libretiny:
|
||||
|
||||
@@ -3,7 +3,6 @@ from esphome.components.light.effects import register_addressable_effect
|
||||
from esphome.components.light.types import AddressableLightEffect
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_NAME, CONF_PORT
|
||||
from esphome.core import CORE
|
||||
|
||||
wled_ns = cg.esphome_ns.namespace("wled")
|
||||
WLEDLightEffect = wled_ns.class_("WLEDLightEffect", AddressableLightEffect)
|
||||
@@ -28,6 +27,4 @@ async def wled_light_effect_to_code(config, effect_id):
|
||||
cg.add(effect.set_port(config[CONF_PORT]))
|
||||
cg.add(effect.set_sync_group_mask(config[CONF_SYNC_GROUP_MASK]))
|
||||
cg.add(effect.set_blank_on_start(config[CONF_BLANK_ON_START]))
|
||||
if CORE.is_esp32:
|
||||
cg.add_library("WiFi", None)
|
||||
return effect
|
||||
|
||||
@@ -892,16 +892,6 @@ class EsphomeCore:
|
||||
library.name if "/" not in library.name else library.name.split("/")[-1]
|
||||
)
|
||||
|
||||
# Auto-enable Arduino libraries on ESP32 Arduino builds
|
||||
if self.is_esp32 and self.using_arduino:
|
||||
from esphome.components.esp32 import (
|
||||
ARDUINO_DISABLED_LIBRARIES,
|
||||
_enable_arduino_library,
|
||||
)
|
||||
|
||||
if short_name in ARDUINO_DISABLED_LIBRARIES:
|
||||
_enable_arduino_library(short_name)
|
||||
|
||||
if short_name not in self.platformio_libraries:
|
||||
_LOGGER.debug("Adding library: %s", library)
|
||||
self.platformio_libraries[short_name] = library
|
||||
|
||||
@@ -240,8 +240,6 @@
|
||||
#define USE_ETHERNET_KSZ8081
|
||||
#define USE_ETHERNET_MANUAL_IP
|
||||
#define USE_ETHERNET_IP_STATE_LISTENERS
|
||||
#define USE_ETHERNET_CONNECT_TRIGGER
|
||||
#define USE_ETHERNET_DISCONNECT_TRIGGER
|
||||
#define ESPHOME_ETHERNET_IP_STATE_LISTENERS 2
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -12,7 +12,3 @@ ethernet:
|
||||
gateway: 192.168.178.1
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
ethernet:
|
||||
type: OPENETH
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -13,7 +13,3 @@ ethernet:
|
||||
subnet: 255.255.255.0
|
||||
domain: .local
|
||||
mac_address: "02:AA:BB:CC:DD:01"
|
||||
on_connect:
|
||||
- logger.log: "Ethernet connected!"
|
||||
on_disconnect:
|
||||
- logger.log: "Ethernet disconnected!"
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
substitutions:
|
||||
i2s_bclk_pin: GPIO15
|
||||
i2s_lrclk_pin: GPIO4
|
||||
i2s_mclk_pin: GPIO5
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
wifi:
|
||||
ssid: test
|
||||
password: test1234
|
||||
|
||||
media_player:
|
||||
- platform: i2s_audio
|
||||
name: Test Media Player
|
||||
dac_type: internal
|
||||
mode: stereo
|
||||
@@ -296,6 +296,16 @@ select:
|
||||
// Migration guide: Store in std::string
|
||||
std::string stored_option(id(template_select).current_option());
|
||||
ESP_LOGI("test", "Stored: %s", stored_option.c_str());
|
||||
- platform: template
|
||||
id: template_select_with_action
|
||||
name: "Template select with action"
|
||||
options:
|
||||
- option_a
|
||||
- option_b
|
||||
set_action:
|
||||
- logger.log:
|
||||
format: "Selected: %s"
|
||||
args: ["x.c_str()"]
|
||||
|
||||
lock:
|
||||
- platform: template
|
||||
|
||||
@@ -56,7 +56,21 @@ select:
|
||||
std::string prefix = x.substr(0, 6);
|
||||
ESP_LOGI("test", "Substr prefix: %s", prefix.c_str());
|
||||
|
||||
# Second select with numeric options to test ADL functions
|
||||
# Second select with set_action trigger (uses TemplateSelectWithSetAction subclass)
|
||||
- platform: template
|
||||
name: "Action Select"
|
||||
id: action_select
|
||||
options:
|
||||
- "Action A"
|
||||
- "Action B"
|
||||
set_action:
|
||||
then:
|
||||
# Test: set_action trigger receives StringRef
|
||||
- logger.log:
|
||||
format: "set_action triggered: %s"
|
||||
args: ['x.c_str()']
|
||||
|
||||
# Third select with numeric options to test ADL functions
|
||||
- platform: template
|
||||
name: "Baud Rate"
|
||||
id: baud_select
|
||||
|
||||
@@ -28,6 +28,8 @@ async def test_select_stringref_trigger(
|
||||
find_substr_future = loop.create_future()
|
||||
find_char_future = loop.create_future()
|
||||
substr_future = loop.create_future()
|
||||
# set_action trigger (TemplateSelectWithSetAction subclass)
|
||||
set_action_future = loop.create_future()
|
||||
# ADL functions
|
||||
stoi_future = loop.create_future()
|
||||
stol_future = loop.create_future()
|
||||
@@ -43,6 +45,8 @@ async def test_select_stringref_trigger(
|
||||
find_substr_pattern = re.compile(r"Found 'Option' in value")
|
||||
find_char_pattern = re.compile(r"Space at position: 6") # space at index 6
|
||||
substr_pattern = re.compile(r"Substr prefix: Option")
|
||||
# set_action trigger pattern (TemplateSelectWithSetAction subclass)
|
||||
set_action_pattern = re.compile(r"set_action triggered: Action B")
|
||||
# ADL function patterns (115200 from baud rate select)
|
||||
stoi_pattern = re.compile(r"stoi result: 115200")
|
||||
stol_pattern = re.compile(r"stol result: 115200")
|
||||
@@ -67,6 +71,9 @@ async def test_select_stringref_trigger(
|
||||
find_char_future.set_result(True)
|
||||
if not substr_future.done() and substr_pattern.search(line):
|
||||
substr_future.set_result(True)
|
||||
# set_action trigger
|
||||
if not set_action_future.done() and set_action_pattern.search(line):
|
||||
set_action_future.set_result(True)
|
||||
# ADL functions
|
||||
if not stoi_future.done() and stoi_pattern.search(line):
|
||||
stoi_future.set_result(True)
|
||||
@@ -89,22 +96,21 @@ async def test_select_stringref_trigger(
|
||||
# List entities to find our select
|
||||
entities, _ = await client.list_entities_services()
|
||||
|
||||
select_entity = next(
|
||||
(e for e in entities if hasattr(e, "options") and e.name == "Test Select"),
|
||||
None,
|
||||
)
|
||||
select_entity = next((e for e in entities if e.name == "Test Select"), None)
|
||||
assert select_entity is not None, "Test Select entity not found"
|
||||
|
||||
baud_entity = next(
|
||||
(e for e in entities if hasattr(e, "options") and e.name == "Baud Rate"),
|
||||
None,
|
||||
)
|
||||
baud_entity = next((e for e in entities if e.name == "Baud Rate"), None)
|
||||
assert baud_entity is not None, "Baud Rate entity not found"
|
||||
|
||||
action_entity = next((e for e in entities if e.name == "Action Select"), None)
|
||||
assert action_entity is not None, "Action Select entity not found"
|
||||
|
||||
# Change select to Option B - this should trigger on_value with StringRef
|
||||
client.select_command(select_entity.key, "Option B")
|
||||
# Change baud to 115200 - this tests ADL functions (stoi, stol, stof, stod)
|
||||
client.select_command(baud_entity.key, "115200")
|
||||
# Change action select - tests set_action trigger (TemplateSelectWithSetAction)
|
||||
client.select_command(action_entity.key, "Action B")
|
||||
|
||||
# Wait for all log messages confirming StringRef operations work
|
||||
try:
|
||||
@@ -118,6 +124,7 @@ async def test_select_stringref_trigger(
|
||||
find_substr_future,
|
||||
find_char_future,
|
||||
substr_future,
|
||||
set_action_future,
|
||||
stoi_future,
|
||||
stol_future,
|
||||
stof_future,
|
||||
@@ -135,6 +142,7 @@ async def test_select_stringref_trigger(
|
||||
"find_substr": find_substr_future.done(),
|
||||
"find_char": find_char_future.done(),
|
||||
"substr": substr_future.done(),
|
||||
"set_action": set_action_future.done(),
|
||||
"stoi": stoi_future.done(),
|
||||
"stol": stol_future.done(),
|
||||
"stof": stof_future.done(),
|
||||
|
||||
@@ -780,78 +780,3 @@ class TestEsphomeCore:
|
||||
target.config = {const.CONF_ESPHOME: {"name": "test"}, "logger": {}}
|
||||
|
||||
assert target.has_networking is False
|
||||
|
||||
def test_add_library__esp32_arduino_enables_disabled_library(self, target):
|
||||
"""Test add_library auto-enables Arduino libraries on ESP32 Arduino builds."""
|
||||
target.data[const.KEY_CORE] = {
|
||||
const.KEY_TARGET_PLATFORM: "esp32",
|
||||
const.KEY_TARGET_FRAMEWORK: "arduino",
|
||||
}
|
||||
|
||||
library = core.Library("WiFi", None)
|
||||
|
||||
with patch("esphome.components.esp32._enable_arduino_library") as mock_enable:
|
||||
target.add_library(library)
|
||||
mock_enable.assert_called_once_with("WiFi")
|
||||
|
||||
assert "WiFi" in target.platformio_libraries
|
||||
|
||||
def test_add_library__esp32_arduino_ignores_non_arduino_library(self, target):
|
||||
"""Test add_library doesn't enable libraries not in ARDUINO_DISABLED_LIBRARIES."""
|
||||
target.data[const.KEY_CORE] = {
|
||||
const.KEY_TARGET_PLATFORM: "esp32",
|
||||
const.KEY_TARGET_FRAMEWORK: "arduino",
|
||||
}
|
||||
|
||||
library = core.Library("SomeOtherLib", "1.0.0")
|
||||
|
||||
with patch("esphome.components.esp32._enable_arduino_library") as mock_enable:
|
||||
target.add_library(library)
|
||||
mock_enable.assert_not_called()
|
||||
|
||||
assert "SomeOtherLib" in target.platformio_libraries
|
||||
|
||||
def test_add_library__esp32_idf_does_not_enable_arduino_library(self, target):
|
||||
"""Test add_library doesn't auto-enable Arduino libraries on ESP32 IDF builds."""
|
||||
target.data[const.KEY_CORE] = {
|
||||
const.KEY_TARGET_PLATFORM: "esp32",
|
||||
const.KEY_TARGET_FRAMEWORK: "esp-idf",
|
||||
}
|
||||
|
||||
library = core.Library("WiFi", None)
|
||||
|
||||
with patch("esphome.components.esp32._enable_arduino_library") as mock_enable:
|
||||
target.add_library(library)
|
||||
mock_enable.assert_not_called()
|
||||
|
||||
assert "WiFi" in target.platformio_libraries
|
||||
|
||||
def test_add_library__esp8266_does_not_enable_arduino_library(self, target):
|
||||
"""Test add_library doesn't auto-enable Arduino libraries on ESP8266."""
|
||||
target.data[const.KEY_CORE] = {
|
||||
const.KEY_TARGET_PLATFORM: "esp8266",
|
||||
const.KEY_TARGET_FRAMEWORK: "arduino",
|
||||
}
|
||||
|
||||
library = core.Library("WiFi", None)
|
||||
|
||||
with patch("esphome.components.esp32._enable_arduino_library") as mock_enable:
|
||||
target.add_library(library)
|
||||
mock_enable.assert_not_called()
|
||||
|
||||
assert "WiFi" in target.platformio_libraries
|
||||
|
||||
def test_add_library__extracts_short_name_from_path(self, target):
|
||||
"""Test add_library extracts short name from library paths like owner/lib."""
|
||||
target.data[const.KEY_CORE] = {
|
||||
const.KEY_TARGET_PLATFORM: "esp32",
|
||||
const.KEY_TARGET_FRAMEWORK: "arduino",
|
||||
}
|
||||
|
||||
library = core.Library("arduino/Wire", None)
|
||||
|
||||
with patch("esphome.components.esp32._enable_arduino_library") as mock_enable:
|
||||
target.add_library(library)
|
||||
mock_enable.assert_called_once_with("Wire")
|
||||
|
||||
assert "Wire" in target.platformio_libraries
|
||||
|
||||
Reference in New Issue
Block a user